Technology Sep 04, 2026 · 3 min read

I Built a Binaural Beat Generator — Then Proved It With a Live FFT Spectrum Analyzer

The "frequency healing" corner of the internet runs on faith. Apps ship MP3s labeled "40Hz gamma" and ask you to believe it. I'm a life scientist who builds web tools, and I couldn't ship that. So I built SereneSynth, a browser-based binaural beat and noise generator — and then I built a live spectr...

DE
DEV Community
by Serenesynth Team
I Built a Binaural Beat Generator — Then Proved It With a Live FFT Spectrum Analyzer

The "frequency healing" corner of the internet runs on faith. Apps ship MP3s labeled "40Hz gamma" and ask you to believe it. I'm a life scientist who builds web tools, and I couldn't ship that. So I built SereneSynth, a browser-based binaural beat and noise generator — and then I built a live spectrum analyzer into the page so anyone can audit the output in their own browser.

This is the engineering write-up: the Web Audio graph, the FFT gotcha that almost made me publish wrong numbers, and how I cross-verified everything in Audacity.

The honesty constraint first

A binaural beat is not a tone in the air. Play 200 Hz into the left ear and 240 Hz into the right, and the listener's superior olivary complex computes the 40 Hz difference. A microphone — or a mono spectrum analyzer — will never show a 40 Hz peak. So the only honest thing a generator can prove is its carriers and its spectral slope. That is exactly what we measure.

The synthesis graph

Two sine oscillators, hard-panned with StereoPannerNode, summed into a master GainNode, tapped by an AnalyserNode before the destination — the analyzer observes exactly what the headphones receive. Settings that matter: fftSize 16384, smoothingTimeConstant 0.8.

The FFT gotcha that almost made me ship garbage

My first version used fftSize 1024: one fat bump near 220 Hz instead of two peaks. Bin width = 44100 / 1024 ≈ 43 Hz, and my carriers are 40 Hz apart — same bin, merged. At fftSize 16384 the bin width drops to ≈ 2.7 Hz and the carriers resolve as razor-sharp spikes at 200.0 and 240.0 Hz. Lesson: FFT size is the magnifying glass. If a "frequency proof" doesn't state its FFT size, ask.

The widget renders a log axis (20–1000 Hz) because a linear axis wastes 90% of the canvas, and peak detection labels the top bins in the 100–500 Hz range live.

Bit-exact, downloadable verification

The page also renders 10-second stereo WAVs via OfflineAudioContext (16-bit PCM, 44.1 kHz): same graph, offline render, RIFF encode. No lossy compression between the engine and the evidence.

Cross-check: two instruments, same answer

Opened the exported WAVs in Audacity (Analyze → Plot Spectrum, FFT 16,384, Hann window):

  • 40 Hz preset: two spikes at 200.0 / 240.0 Hz
  • 432 Hz preset: single spike at 432.0 Hz, no harmonics
  • Brown noise: continuous ≈ -6 dB/octave rolloff on a log axis

Browser analyzer and desktop DAW agree. The proof is re-runnable, not rhetorical.

Audit it yourself

Live analyzer + WAV downloads: serenesynth.com/proof-lab

The generator: serenesynth.com/binaural-beat-generator

Methodology + figures: GitHub repo

No mysticism. Just math.

DE
Source

This article was originally published by DEV Community and written by Serenesynth Team.

Read original article on DEV Community
Back to Discover

Reading List