Sinusoids and the frequency domain
A pure tone at frequency f is a sinusoid, x(t) = A·cos(2πft+φ). The Fourier transform decomposes an arbitrary signal into exactly the complex exponentials that add up to it:
X(f) = ∫ x(t)·e^(−i2πft) dt // analysis: signal → spectrum x(t) = ∫ X(f)·e^(+i2πft) df // synthesis: spectrum → signal |X(f)|² = power spectral density at frequency f
Digital audio samples this continuous signal at a fixed rate f_s — 44,100 Hz for CD audio. The Nyquist-Shannon theorem guarantees a bandlimited signal can be perfectly reconstructed from samples taken faster than twice its highest frequency; at 44.1 kHz that covers frequencies up to 22,050 Hz, spanning the entire audible range.
The Discrete Fourier Transform
Given N samples x[0]…x[N−1], the DFT produces N complex frequency-domain values, where bin k corresponds to physical frequency f_k = k·f_s/N:
X[k] = Σ_(n=0)^(N-1) x[n]·e^(−i2πkn/N), k = 0…N−1 // computed directly: O(N²) — unusably slow for N ≥ 4096
The Cooley-Tukey FFT
The key trick (Cooley & Tukey, 1965; also found by Gauss in 1805) splits a length-N DFT into two length-N/2 DFTs of the even- and odd-indexed samples, then recombines them with a "twiddle factor":
X[k] = E[k] + W_N^k · O[k] X[k+N/2] = E[k] − W_N^k · O[k] E[k] = DFT of even-indexed samples, O[k] = DFT of odd-indexed samples W_N^k = e^(−i2πk/N) // twiddle factor
Applied recursively across log₂N stages of N/2 "butterfly" combinations each, this costs O(N log₂N) instead of O(N²) — a 682× speedup at N = 4096. In practice the input is bit-reversed once up front, then the same butterfly kernel runs stage by stage:
function fft(re, im) { // radix-2 Cooley-Tukey, in-place
const N = re.length;
for (let i=1, j=0; i>1;
for (; j & bit; bit >>= 1) j ^= bit;
j ^= bit;
if (i < j) { [re[i],re[j]]=[re[j],re[i]]; [im[i],im[j]]=[im[j],im[i]]; }
}
for (let len=2; len<=N; len<<=1) { // butterfly stages
const ang = -2*Math.PI/len, wRe=Math.cos(ang), wIm=Math.sin(ang);
for (let i=0; i
Windowing and the spectrogram
The DFT implicitly assumes the analysed block is periodic; a raw block cut off abruptly is equivalent to multiplying by a rectangular window, whose spectrum is a wide sinc that leaks energy into neighbouring bins. A tapered window — Hann, Hamming, Blackman-Harris — suppresses that leakage at the cost of slightly wider main lobes. Sliding a windowed DFT along the signal in overlapping steps gives the Short-Time Fourier Transform; plotting its magnitude as time-vs-frequency-vs-intensity produces a spectrogram, where musical notes appear as horizontal lines and speech formants as vertical striping.
From bins to real applications
Pitch detection finds the fundamental frequency bin with the strongest magnitude; audio compression (MP3, AAC) discards frequency components the human ear can't hear thanks to psychoacoustic masking; the mel spectrogram — warping the frequency axis to match human pitch perception — is the standard input representation for speech models like Whisper. All of it traces back to the same Cooley-Tukey butterfly network.
Frequently asked questions
Why do we need the FFT instead of just computing the DFT directly?
The direct DFT formula costs O(N²) multiplications, which becomes unusable past a few thousand samples. The Cooley-Tukey Fast Fourier Transform recursively splits a length-N DFT into two length-N/2 DFTs, cutting the cost to O(N log N) — a 682× speedup at N = 4096 — by computing exactly the same numbers, just far more efficiently.
Why does the DFT of a real recording need to be windowed first?
Applying the DFT to a raw, abruptly-cut block is mathematically equivalent to multiplying the signal by a rectangular window, whose spectrum is a wide sinc function that leaks energy from strong tones into neighbouring bins. A smooth taper like a Hann or Hamming window reduces that leakage, at the cost of a slightly wider main lobe.
What is the trade-off in choosing the FFT block size N?
A larger N gives finer frequency resolution (fs/N Hz per bin) but coarser time resolution, since the whole block is treated as a single instant. Speech analysis typically uses N = 512–2048 (11–46 ms at 44.1 kHz); musical pitch detection often uses N = 4096 for sharper frequency bins.
Try it live
Add and remove harmonics and watch the resulting waveform update instantly in Fourier Series.
▶ Open Fourier Series simulation