32 samples of a tone, padded with more and more zeros. Watch the dashed curve while the new points arrive: it never moves.
More points on the same curve
32 samples of a 1100 Hz tone at f_s = 8 kHz, padded with zeros to N_fft. Sizes ÷ (N/2), N = 32.
N_fft = 32, no padding: points every 250 Hz. The highest sits at 1000 Hz, 100 Hz from the tone.
Describe this picture
32 samples of a 1100 Hz tone at kHz, padded with zeros to ; sizes ÷ , . Two stacked panels. The time panel runs over sample from 0 to 127: the 32 samples are stems with dot heads, and the added zeros small open circles on the axis, labelled “zeros added”. The spectrum panel has frequency from 0 to 2000 Hz and size ÷ from 0 to 1.1. A faint dashed curve, labelled “DTFT of the 32 samples”, is the DTFT; the FFT points are filled dots with thin stems, labelled “FFT points”. The highest point is ringed, and an upward triangle under the axis at 1100 Hz is labelled “tone”. The readouts are and the frequency of the highest point, in hertz with 2 decimals.
The clip runs for 14 s and plays once. During each of three growths the new points grow out of the curve and the old points stay, with the caption blank; the captions appear on the holds. At the start (32, 1000.00 Hz): “N_fft = 32, no padding: points every 250 Hz. The highest sits at 1000 Hz, 100 Hz from the tone.” At 4 s (64, 1125.00 Hz): “Padded to 64: points every 125 Hz, and every new point lands on the same curve. The highest is now at 1125 Hz.” At 6.5 s (128, 1125.00 Hz): “128: every 62.5 Hz. The curve has not changed; we see more of it.” At the end, 14 s (512, 1093.75 Hz): “512: every 15.6 Hz, the highest point at 1093.75 Hz, near the curve’s peak at 1100.4 Hz. Zero-padding interpolates: it samples the same curve more finely.”
After the clip ends, a slider named “FFT length N_fft” appears on the plot, with the hint “Drag across the plot, or use the arrow keys, to set N_fft (32 to 4096).” It moves in powers of two: the arrow keys double and halve the length, and Home and End jump to 32 and 4096. At 32, 64, 128 and 512 the captions above show. At any other length the caption has the form “N_fft = 1024: points every 7.8 Hz; the highest at 1101.56 Hz.” and follows the slider.
Zeros add points, not detail
An FFT of samples gives bins, spaced apart. Sometimes I want the points closer together, for a smoother plot or a better reading of a peak. The cheapest way is to append zeros to the record before the FFT. This is zero-padding, and the FFT length that results is , as in Fast convolution (14.3).
Padding changes nothing about the spectrum curve itself. The DTFT of Sampling the spectrum (13.1) is a sum over the samples, and a zero sample adds nothing to a sum. So is the same curve with or without the zeros. What changes is how many points I read from it. An FFT of length samples the curve at , which is every hertz.
The same idea appeared as the zoom of Goertzel and the chirp z-transform (14.4): a finer grid over a band, on the same curve. Here the finer grid covers the whole range. A surveyed road makes the picture. Marking a post every kilometre, then every 100 metres, gives more posts, and the road is the same road.
More points on the same curve
The picture at the top of this page takes 32 samples of an 1100 Hz tone at kHz and pads them to . The tone sits at bins, so it lies between two bins, which is the interesting case.
With no padding the points are every 250 Hz, and the highest sits at 1000 Hz, 100 Hz from the tone. Padded to 64, the points are every 125 Hz, every new point lands on the same curve, and the highest is at 1125 Hz. At 128 they are every 62.5 Hz: the curve has not changed, and we see more of it. At 512 they are every 15.6 Hz, and the highest point is at 1093.75 Hz, near the curve’s peak at 1100.4 Hz.
The dashed curve never moves while the new points arrive. The highest point does move, from 1000 Hz to 1125 Hz, because a finer grid has a point closer to the top. At 512 points the highest point is 6.69 Hz from the curve’s peak.
When the clip ends, drag across the plot to set yourself, from 32 to 4096. At 1024 the points are every 7.8 Hz and the highest is at 1101.56 Hz. At 4096 the highest point is at 1099.61 Hz, with size 0.998, the same as the curve’s peak to three decimals. Between 0 and 2000 Hz there are 9, 17, 33 and 129 points for lengths 32, 64, 128 and 512.
Key idea
Zero-padding interpolates the spectrum: it reads more points of the same curve. It adds no information about the signal, because the zeros are not measurements.
Padding cannot split two tones
If padding gave more detail, two close tones would separate once I pad enough. They do not. The DTFT of a record of samples is a lumpy curve: each tone leaves a lump whose width is set by the record. Padding samples that same curve more finely, so the lumps stay as wide as they were.
The record length is seconds. A rectangular window gives lumps about hertz wide. Two tones hertz apart therefore need a record of about samples, which is about seconds. This is the rule of thumb of The DFT (13.2), where 1000 Hz and 1100 Hz needed about 80 samples at 8 kHz. Padding does not appear in this rule, and only the record length does. Enlarging a blurred photograph makes a bigger blur, not a sharper picture.
The picture below tests this, with tones at 1000 and 1100 Hz, kHz and a rectangular window. Watch the number of peaks: padding does not change it, and a longer record does.
Padding cannot split two tones
Tones at 1000 and 1100 Hz, f_s = 8 kHz, rectangular window. Sizes ÷ (N/2).
40 samples (5 ms), no padding: points every 200 Hz, and one peak, at 1000 Hz.
Describe this picture
Tones at 1000 and 1100 Hz, kHz, rectangular window, sizes ÷ . One panel, with frequency from 800 to 1300 Hz and size ÷ from 0 to 1.5. The FFT points are filled dots joined by a thin line, the dots hidden when they are closer than 4 px. Two upward triangles under the axis at 1000 and 1100 Hz mark the tones, and each peak taller than half the highest is marked with a downward triangle above it. A key names the marks “FFT points”, “peak” and “tones”. The readouts are the record , for example “40 samples, 5 ms”, and .
The clip runs for 15 s: first the FFT length grows to 1024 and the points fill in, then the record grows to 80 samples, then to 160. The captions appear on the holds, and the area is blank during each change. At the start, 40 samples and : “40 samples (5 ms), no padding: points every 200 Hz, and one peak, at 1000 Hz.” At 4.75 s (“40 samples, 5 ms”, 1024): “Padded to 1024: a smooth curve, but still one lump, topping out at 1055 Hz. Padding filled in the curve; it could not split it.” At 8.25 s (“80 samples, 10 ms”, 1024): “A record of 80 samples (10 ms), padding unchanged: two peaks, near 984 and 1117 Hz.” At the end, 15 s (“160 samples, 20 ms”, 1024): “160 samples (20 ms): two clear peaks, near 992 and 1109 Hz. Only a longer record separates the tones: about f_s/gap samples, a record of about 1/gap seconds.”
After the clip ends, a slider named “Record length N” appears, with the hint “Drag across the plot, or use the arrow keys, to set the record length (16 to 320).” The arrow keys change by 1, Page Up and Page Down by 16, and Home and End jump to 16 and 320, with . Records of 36 samples or fewer rise above 1.42, so for them the size axis grows to 2.1. At 40, 80 and 160 samples the captions above show. At any other length the caption has the form “N = 120: a record of 15 ms; two peaks.” or the same with “one peak.” at the end, with milliseconds to 1 decimal when not whole.
At first the record is 40 samples (5 ms), with no padding: points every 200 Hz, and one peak, at 1000 Hz. Padded to 1024, the curve is smooth, but still one lump, topping out at 1055 Hz: padding filled in the curve, and it could not split it. A record of 80 samples (10 ms), with the padding unchanged, gives two peaks, near 984 and 1117 Hz, and 160 samples (20 ms) give two clear peaks, near 992 and 1109 Hz. Only a longer record separates the tones.
Compare the first two. The same 40 samples give one lump, however finely I read it. The padded curve even tops out at 1055 Hz, between the tones, so a single peak there would mislead. Only the record growing to 80 samples gives two peaks.
When the clip ends, drag across the plot to set the record length yourself, from 16 to 320 samples. I found that the first record showing two peaks is 53 samples, 6.6 ms, so “about 80” is the right order of size and not a sharp threshold.
The maths behind it · interpolation matrices
Padding appends zero rows to the data vector, and the longer DFT matrix has extra rows that are new probe frequencies. Each new output is a linear combination of the old bins, an interpolation matrix, so the new points carry no new information.
The picket fence
The bins see the spectrum only at their pickets, which are apart. This is the picket-fence effect. A tone between two pickets is missed twice. Its level reads low, as the scalloping loss of Window functions compared (15.2) showed, and its frequency reads wrong, because the tallest bar is the nearest picket.
I can recover both from the bars I already have. Take the tallest bar and its two neighbours, with heights , and in decibels, where is bin and is bin . The three points lie close to a parabola. Place at 0 and the neighbours at and bins, and the parabola is
Its top is where the slope is zero. Setting the slope to zero gives the offset from bin , in bins, and a frequency estimate :
This is parabolic interpolation of a spectral peak. Since is the tallest, is negative, and lies between and .
A parabola through three bins
The picture below uses a 1037 Hz tone, the one from the zoom of Goertzel and the chirp z-transform (14.4), so the answer can be checked against it. Watch the diamond land on the parabola’s top, between the pickets and close to the tone.
A parabola through three bins
A 1037 Hz tone, N = 256 at f_s = 8 kHz, Hann window: bins every 31.25 Hz. Values are 20 log₁₀ |X[k]|.
Describe this picture
A 1037 Hz tone, at kHz, Hann window: bins every 31.25 Hz, with values . One panel, with frequency from 960 to 1100 Hz, ticks at 1000, 1031.25 and 1062.5, and from 15 to 40 dB. Bars at the five bins from 968.75 to 1093.75 Hz carry filled squares on top; the three tallest are labelled with their values to 2 decimals. The outer two are faint, and here they read 2.62 and 8.52 dB, below the axis, so their squares sit on its floor. The parabola is a dashed curve, and a filled diamond at its top is labelled “parabola peak”. A dotted vertical line at the true frequency is labelled “tone”. A key names the squares “bins” and the dashed curve “parabola”. The readouts are the nearest bin and what the parabola says, which reads “not yet” before the diamond lands.
The clip runs for 12 s. The five bars rise for 2 s with no caption. At 2 s (1031.25 Hz, “not yet”): “The tallest bar is at 1031.25 Hz, 5.75 Hz below the tone: the pickets miss it.” From 4 s to 7.5 s the parabola draws through the three tops and the diamond drops onto its top: “A parabola through the three tallest bars, in dB.” At the end, 12 s (1031.25 Hz, 1037.41 Hz): “Its top is d = 0.197 bins past the tallest bar: 1037.41 Hz, 0.41 Hz from the tone. With a Hann window the error stays within about 0.5 Hz wherever the tone sits.”
After the clip ends, the dotted tone line can be dragged; the hint reads “Drag the tone line, or use the arrow keys, to move the tone across one bin.” The tone runs from 1031.25 to 1062.5 Hz in steps of 0.25 Hz, with Page Up and Page Down moving 5 Hz. At 1037 Hz the caption above shows. At any other tone the caption has the form “Tone 1046.00 Hz: nearest bin 1031.25 Hz; the parabola says 1046.14 Hz, 0.14 Hz off.”
The tallest bar is at 1031.25 Hz, 5.75 Hz below the tone: the pickets miss it. The parabola’s top is bins past the tallest bar, at 1037.41 Hz, 0.41 Hz from the tone. When the clip ends, drag the tone line across the bin. Move the tone to the middle of the bin and the estimate stays within a fraction of a hertz, although the nearest bar is up to 15.6 Hz away.
The same three bars also correct the level. The peak height of the parabola is . For this tone it is 36.17 dB, against a true level of 36.12 dB. The tallest bar read 35.93 dB, so the parabola undoes most of the scalloping.
How good is it? I measured over tones every 0.25 Hz across the whole bin from 1031.25 to 1062.5 Hz. On dB values with a Hann window the largest error is 0.50 Hz, about 0.02 bins. On linear values with a Hann window it is 1.65 Hz, and on linear values with a rectangular window it reaches 7.49 Hz. So the dB scale and the Hann window both help. The zoom of Goertzel and the chirp z-transform (14.4) found the same 1037 Hz with 81 extra points, and the parabola needs none.
The maths behind it · refining a grid maximum
Fitting a parabola to the three highest points is a classic way to refine the maximum of a likelihood found on a grid. Newton’s method takes the same step.
Worked example
Take 32 samples of an 1100 Hz tone at 8 kHz, with sizes divided by 16.
- With no padding, bins are 250 Hz apart and the highest point is at 1000 Hz, with size 0.755. At 64 and 128 points it is at 1125 Hz, with size 0.983. At 512 points it is at 1093.75 Hz, with size 0.997.
- The curve’s own peak is at 1100.44 Hz, with size 0.998. Padding to 4096 points gets to 1099.61 Hz, but the curve was there all along.
- For two tones 100 Hz apart at 8 kHz, the rule gives samples, which is 10 ms. The measured threshold is 53 samples. At 80 samples the peaks are near 984.4 and 1117.2 Hz.
- For the 1037 Hz tone with Hann and , the dB values are 27.38, 35.93 and 32.22 at bins 32, 33 and 34. The offset is and Hz. Other tones give 1040.50 Hz for 1040 Hz, 1046.87 Hz for 1046.875 Hz and 1049.62 Hz for 1050 Hz, the last from bin 34.
Here is a practice question. A recording of 1 s at 48 kHz has samples, so the bins are 1 Hz apart. Padding to four times the length gives points every 0.25 Hz. Two tones still need about 1 Hz of separation to show two peaks with a rectangular window, because the record is still 1 s long.
Where you’ll meet this
Spectrum plots in audio tools pad each frame so that peaks look smooth, and that is interpolation, not extra resolution. Spectrograms pad each frame in the same way, as in Spectrograms and the STFT (15.5). The resolution of the periodogram is the record length again (25.1). The parabola of this page reads a peak to a fraction of a bin without extra computation.
Reference card
| Quantity | Formula | Notes |
|---|---|---|
| Zero-padding | FFT of followed by zeros | samples the same |
| Point spacing | a finer grid, not finer detail | |
| Resolution | lumps about wide; record length | two tones need about samples |
| Picket fence | bins see the spectrum only at | level low (15.2), frequency off |
| Parabolic peak | , | in dB; Hann: within 0.02 bins |
| Peak level | undoes most of the scalloping |