Or record
Sing, whistle, or play something into the microphone. The recording stays in this tab.
Or start from a signal whose answer is known
A square wave's partials were worked out in 1822. If the bench disagrees with Fourier, the bench is wrong.
What it is
—
| n | Frequency | Note | Off note | Level | Amplitude | Off harmonic |
|---|
A spectrogram cannot be checked by looking at it: a broken transform draws one just as convincing as a working one. So the analysis is run backwards. Each row below is a sound this page can play, and the last column is how far it lands from the sound that went in.
| Signal | What it is | Against the input |
|---|
Cutting a sound into frames is multiplying it by a shape, and every shape lies about the sound in its own way. A rectangle — cutting with scissors and no shape at all — smears one steady sine across the whole band. The others trade a wider main lobe, which is coarser frequency resolution, for lower sidelobes, which is less of one partial appearing where another one isn't. Every figure here is measured from the array actually in use rather than quoted from a table, so it cannot drift from the code.
| Window | Main lobe | Highest sidelobe | Noise bandwidth | What it is for |
|---|
The transform is written here. No library parses, transforms or rebuilds anything: fourier.js is a radix-2 Cooley–Tukey butterfly over two arrays of doubles, with the real-input packing that halves the work, the five windows, and the overlap-add that goes back the other way. partials.js turns bins into partials, synth.js turns partials back into sound. The assertions are in selftest.js and they run in a browser at tools/verify/fourier-bench.html.
A bin is not a partial. A 440 Hz tone read through 11.7 Hz bins has no bin of its own: it appears as a hump a few bins wide whose tallest point is at 442 Hz and whose height is short of the true amplitude by up to 1.4 dB. Every frequency in the table is interpolated — by a parabola through the peak and its neighbours, and, where the partial holds still long enough for the two to agree, by the phase it advanced between frames, which is far the more accurate of the two. Every amplitude is divided by the window's known response at the offset the partial actually fell at. Those two corrections are the difference between a table that is roughly right and one that agrees with the closed forms to four decimal places.
The residual is the honest part. Splitting the spectrum into the bins under the peaks and every other bin gives two sounds that add back to the original exactly, so whatever the sines do not hold has to be somewhere and that somewhere is audible. It is where the breath, the bow, the hammer and the room went. A sound that is mostly residual is not a failure of the analysis — it is a sound that is mostly not sinusoids, and white noise is the extreme case.
Where it does worst is worth knowing. A sound that starts abruptly, a struck note, a consonant: at an onset the sound changes inside the frame that is measuring it, and no single spectrum describes a frame in which the answer changed. Shorten the frame and the onset sharpens while the partials blur together, which is the trade in the line under the spectrogram and the one thing about Fourier analysis that no amount of arithmetic gets around.