Under the Hood: The Architecture of Ambient Noise Masker & Binaural Focus Frequency Mixer
Streamed “focus playlists” are telemetry products. They know when you pressed play, which device decoded the AAC, and they mix licensed noise on a CDN with session cookies. A binaural beats generator does not need that graph. The Web Audio API can instantiate two OscillatorNodes, pan them with StereoPannerNode to −1 and +1, and overlay a looping AudioBufferSourceNode of white, pink, or brown noise through a BiquadFilterNode low-pass. Carrier and beat frequencies are numbers in RAM. There is no media file, no upload, and no account.
Binaural encoding is a stereo trick: left ear receives frequency f, right receives f + Δ. The auditory system can perceive Δ as a beat. Speakers collapse the image because both ears hear the sum; headphones are mandatory. Ambient masking sits under the tones so the mix is usable as a focus bed, which is the differentiator versus a bare tone generator.
Memory Allocation & Browser Threading Mechanics
Rendering runs on the browser audio thread (separate from the main JS thread). React only constructs the graph on Play and writes AudioParam values when carrier/beat change. Noise is a two-second AudioBuffer: at 48 kHz mono that is ~375 KB of Float32Array, then loop = true. Pink noise uses a Paul Kellet IIR on white samples; brown noise is a leaky integrator. Those loops execute once when the buffer is filled—not every animation frame—so the UI thread is not in a DSP spin. GainNode values are clamped to small amplitudes to reduce clipping risk.
AudioContext.close() on Stop (and on unmount) releases the DAC callback. Leaving a context running in a background tab would keep the audio hardware alive and continue consuming power; the cleanup effect exists to prevent that leak.
Algorithmic Deep-Dive: Code Snippet & Logical Analysis
const ctx = new AudioContext(); const master = ctx.createGain(); master.connect(ctx.destination); const left = ctx.createOscillator(); const right = ctx.createOscillator(); left.type = right.type = "sine"; left.frequency.value = carrier; right.frequency.value = carrier + beat; const lp = ctx.createStereoPanner(); const rp = ctx.createStereoPanner(); lp.pan.value = -1; rp.pan.value = 1; left.connect(ctx.createGain()).connect(lp).connect(master); right.connect(ctx.createGain()).connect(rp).connect(master); left.start(); right.start();
Sine oscillators minimize harmonic distraction. The beat is the difference of the two frequency params, not a third AM oscillator. Noise, if enabled, is a separate source mixed at master so tone and masker have independent gains. Edge case: calling Play twice without Stop would leak oscillators; the implementation stops the previous graph first.
The Local Storage Sandbox & Volatile Data Pipelines
Nothing is written to disk. There is no MediaRecorder hooked up, so the mix cannot silently become a file. Buffers die with the AudioContext. Slider state is React state only—not localStorage—so a shared computer does not remember your last session as a “preference cookie.”
Verifying True Privacy: How to Audit Your Browser's Network Tab
F12 → Network → clear, then Play mix. You should see no audio/mpeg or HLS range requests. Web Audio does not open WebSockets. If the document’s JS is cached, the log can be empty for the entire session. That empty log is the proof a binaural beats generator is local synthesis, not a stream.