Skip to content

Goertzel and the chirp z-transform

Compute one DFT bin with a loop that rotates and adds, decode phone keys with eight such loops, then zoom into a narrow band of the spectrum.

Before this3.4 · 6.1 · 1 more
Chapter 14 · Lesson 4 of 4

First, the picture

Two loops, each computing one DFT bin, hear a 770 Hz tone. Watch the one tuned near 770 Hz climb while the other wanders below 20.

A loop that rings at one frequency

Input: a 770 Hz tone at 8 kHz, 205 samples. Two loops, tuned to bins 20 and 18.

Both loops start with the first sample: size 1.00.

sample n
0
k = 20
1.00
k = 18
1.00
0.00 / 12.00 s
Describe this picture

One panel, for a 770 Hz tone at 8 kHz, 205 samples, fed to two loops tuned to bins 20 and 18. It shows the size of each loop’s running total against the sample nn from 0 to 204. The solid line, ending in a ring, is the loop for k=20k=20 (780.5 Hz); the dashed line, ending in a square, is the loop for k=18k=18 (702.4 Hz). The readouts are the sample nn and the two sizes to 2 decimals. There is no control.

The clip plays by itself, and the caption speaks only at the key frames. Both loops start at size 1.00. At the halfway frame, n=102n=102, they are at 49.93 and 7.54. At the end the caption reads “After 205 samples: 91.18 and 13.65. These are |X[20]| and |X[18]|, the same as the FFT gives, at one real multiply per sample each.” With reduced motion on, the picture steps through n=0n=0, 25, 50, 102, 150 and 204, with captions such as “n = 25: 13.06 and 11.52.” The “Hear the tone” button plays the 770 Hz input for 0.5 s.

A loop that rings at one frequency

Your phone’s keypad sends two tones per key. The exchange must know which of 8 frequencies are present, 25 ms at a time. An FFT computes 256 bins to read 8.

This page computes one bin at a time. I start from the sum of The DFT (13.2), where X[k]X[k] is the walking vector: each sample is multiplied by a probe that turns by Ωk=2πk/N\Omega_k=2\pi k/N per step, and the products are added. Now run that sum as a loop. Start from yk[−1]=0y_k[-1]=0 and, for each new sample, write

yk[n]=x[n]+ejΩk yk[n−1].y_k[n]=x[n]+e^{j\Omega_k}\,{y_k[n-1]}.

This is a loop of the kind in Difference equations (6.1): each output comes from the last one. The factor ejΩke^{j\Omega_k} is an arrow of length 1 (Complex exponentials, 3.4), so each step spins the running total by Ωk\Omega_k and does not make it bigger or smaller. Then the new sample is added.

After NN samples the loop holds

yk[N−1]=∑m=0N−1x[m] ejΩk(N−1−m).y_k[N-1]=\sum_{m=0}^{N-1}x[m]\,e^{j\Omega_k(N-1-m)}.

Because ΩkN=2πk\Omega_kN=2\pi k, the factor ejΩk(N−1)e^{j\Omega_k(N-1)} equals e−jΩke^{-j\Omega_k}, so yk[N−1]=e−jΩkX[k]y_k[N-1]=e^{-j\Omega_k}X[k]. The loop gives X[k]X[k] turned by a fixed angle: ∣yk[N−1]∣=∣X[k]∣\lvert y_k[N-1]\rvert=\lvert X[k]\rvert, and X[k]=ejΩkyk[N−1]X[k]=e^{j\Omega_k}y_k[N-1].

Why does it ring at one frequency? If the input matches the loop’s frequency, each new sample lands in step with the spinning total, and the total grows steadily. If not, the additions drift in and out of step, and the total stays small. It is pushing a child on a swing: in time with the swing, the swing climbs; out of time, your pushes cancel.

The picture at the top of the page runs two such loops on a 770 Hz tone, one tuned to bin 20 (780.5 Hz) and one to bin 18 (702.4 Hz). Both start with the first sample, at size 1. Step or pause on the halfway frame, n=102n=102: the loop tuned near 770 Hz has grown to 49.93, and the other is at 7.54 and going nowhere. After 205 samples they are 91.18 and 13.65. These are ∣X[20]∣\lvert X[20]\rvert and ∣X[18]∣\lvert X[18]\rvert, the same as the FFT gives.

A tone that sits exactly on a bin gives the largest possible answer. Unit-amplitude cosine on bin 20 gives ∣X[20]∣=N/2=102.5\lvert X[20]\rvert=N/2=102.5. The 770 Hz tone is between bins 18 and 20, so the loop at 20 reaches 91.18, and the loop at 18 reaches only 13.65.

The real form and the cost

The complex loop needs a complex multiply per sample, which is 4 real multiplies (Complex numbers for signals, 3.3). A rearrangement avoids that. Use two delays and a real coefficient:

qk[n]=x[n]+2cos⁡Ωk qk[n−1]−qk[n−2].q_k[n]=x[n]+2\cos\Omega_k\,{q_k[n-1]}-{q_k[n-2]}.

That is one real multiply per sample. This is Goertzel’s algorithm. After the last sample, two numbers are enough:

X[k]=ejΩk qk[N−1]−qk[N−2].X[k]=e^{j\Omega_k}\,{q_k[N-1]}-{q_k[N-2]}.

When you need only the size, no complex arithmetic remains:

∣X[k]∣2=qk[N−1]2+qk[N−2]2−2cos⁡Ωk qk[N−1] qk[N−2].\lvert X[k]\rvert^2={q_k[N-1]}^2+{q_k[N-2]}^2-2\cos\Omega_k\,{q_k[N-1]}\,{q_k[N-2]}.

For the 770 Hz tone and k=20k=20 the coefficient is 2cos⁡Ω20=1.63592\cos\Omega_{20}=1.6359, and the loop ends with q[204]=−118.605q[204]=-118.605 and q[203]=−157.493q[203]=-157.493. Then X[20]=ejΩ20q[204]−q[203]=60.483−68.236jX[20]=e^{j\Omega_{20}}q[204]-q[203]=60.483-68.236j, which is what the FFT gives.

A loop like this, which keeps ringing at one frequency, is a resonator. Resonators, notches and combs (17.4) designs them properly, and Transfer functions, poles and zeros (16.3) explains why it rings. I leave the poles until then.

Now the cost. Eight bins on 205 samples take 8×205=16408\times205=1640 real multiplies, plus a few at the end of each bin. A 256-point FFT has N2log⁡2N=1024\tfrac N2\log_2N=1024 complex multiplies (The FFT, 14.1), which is 4×1024=40964\times1024=4096 real multiplies. Its bins also sit at multiples of 31.25 Hz, not where the keypad tones are.

Per bin, Goertzel costs NN real multiplies and the FFT costs 4⋅N2log⁡2N=2Nlog⁡2N4\cdot\tfrac N2\log_2N=2N\log_2N in total. So Goertzel wins when you want fewer than about 2log⁡2N2\log_2N bins: 16 of them for N=256N=256.

The maths behind it · inner products

One Goertzel loop computes one row of the DFT matrix times x\mathbf{x}: an inner product with a probe, done by a recursion instead of a stored row.

Which key was pressed

Each key sends one row tone (697, 770, 852 or 941 Hz) and one column tone (1209, 1336, 1477 or 1633 Hz). This is the DTMF scheme of ITU-T Recommendations Q.23 and Q.24. With fs=8f_s=8 kHz and N=205N=205, which is 25.6 ms of sound, the bins are 8000/205=39.08000/205=39.0 Hz apart. Rounding k=Nf/fsk=Nf/f_s gives bins 18, 20, 22, 24, 31, 34, 38 and 42, at 702.4, 780.5, 858.5, 936.6, 1209.8, 1326.8, 1482.9 and 1639.0 Hz. Each is within 11 Hz of its tone.

Use eight loops, one per tone. The strongest row loop and the strongest column loop name the key. It is how a voicemail menu hears “press 1”. The next picture dials four keys by itself. Watch the bars: exactly two stand out each time, one in each group.

Which key was pressed

Eight Goertzel loops, N = 205 at 8 kHz, one per DTMF tone.

Key 1 sends 697 Hz and 1209 Hz.

key sent
1
decoded
listening…
0.00 / 13.50 s
Describe this picture

Two panels: eight Goertzel loops, N=205N=205 at 8 kHz, one per DTMF tone. The top panel is a telephone keypad of four rows and four columns, with the rows labelled 697, 770, 852 and 941 Hz and the columns 1209, 1336, 1477 and 1633 Hz. The dialled key is outlined and the decoded key is filled, so the two states differ without colour. The bottom panel has eight bars of ∣X[k]∣\lvert X[k]\rvert, one per loop, labelled with its tone in Hz, in a group of rows and a group of columns. The strongest bar of each group gets a ring on top and a thick outline. The readouts are the key sent and the key decoded, which shows “listening…” while the bars grow and then the form “770 + 1336 Hz → 5”.

The clip dials 1, 5, 9 and 0, and the caption names the two loops that stand out for each key. For key 5 they are 45.9 and 46.9, and every other loop stays below 7. The last caption reads “Dialled 1, 5, 9, 0. Each key needed 8 loops × 205 samples: 1640 multiplies, 25.6 ms of sound.” Once the clip has finished, pressing a key, or typing it (0 to 9, *, #, A to D), regrows the bars for that key. “Hear the key” plays the two tones for 0.2 s.

Key 1 sends 697 Hz and 1209 Hz, and those two loops stand out. For key 5, 770 and 1336 Hz stand out at 45.9 and 46.9, and every other loop stays below 7. Each key needs 8 loops × 205 samples: 1640 multiplies, for 25.6 ms of sound.

Then it is yours. Press a key, or type it, and the bars regrow for that key. Try key 0: its bars are about 51.6 at 941 Hz and 46.4 at 1336 Hz, and the other six stay below 4.

The sixteen keys are told apart because every pair of tones sits on its own pair of bins. The bars of the other six loops are small but not zero, because a tone between bins leaks a little into the rest. I come back to leakage in Windowing and spectral leakage (15.1).

The maths behind it · detection tests

Deciding “is this tone present?” by comparing ∣X[k]∣\lvert X[k]\rvert to a threshold is a detection test. Noise sets the false-alarm rate; 25.x returns to this.

Zoom into a band

Now the opposite need. The DFT samples the spectrum at NN evenly spaced points (Sampling the spectrum, 13.1). Suppose you want to see the curve finely between 1000 and 1080 Hz. You could zero-pad to 8192 points (Zero-padding and resolution, 15.3), which computes 8192 bins to use 81.

Instead, compute only the points you want. Choose a lowest frequency fLf_L, a highest frequency fHf_H, a step fstepf_\text{step} and a number of points NzoomN_\text{zoom}. Evaluate the spectrum at

f=fL+k fstep,k=0,1,…,Nzoom−1.f=f_L+k\,f_\text{step},\qquad k=0,1,\ldots,N_\text{zoom}-1.

Each point is a DFT-like sum with e−j2π(fL+kfstep)n/fse^{-j2\pi(f_L+kf_\text{step})n/f_s} in it. More FFT algorithms (14.2) showed that Bluestein’s chirp trick turns sums of this form into one convolution, which an FFT computes. The same trick handles all the zoom points at once. The next picture zooms into 80 Hz around a 1037 Hz tone. Watch the peak readout move from the nearest FFT bin to the tone.

Zoom into a band

A 1037 Hz tone, 256 samples at 8 kHz. FFT bins every 31.25 Hz.

peak at
–
grid spacing
31.25 Hz
0.00 / 12.00 s
Describe this picture

One panel for a 1037 Hz tone, 256 samples at 8 kHz, with FFT bins every 31.25 Hz: ∣X∣\lvert X\rvert against frequency from 900 to 1180 Hz. The FFT bins are stems with filled dots. A shaded stretch is the zoom band, and a solid line through 81 points, 1 Hz apart, crosses it, with a small open square every 10 Hz. A ring marks the highest FFT bin and a diamond marks the zoom’s peak. The readouts are where the peak is and the grid spacing.

The clip plays by itself. First the stems rise, and the caption says the tone is somewhere between the bins. The peak readout shows ”–” until the ring lands on bin 33, then 1031.25 Hz with a spacing of 31.25 Hz. The band shades in from 1000 to 1080 Hz and the line draws across it; when the diamond appears the readouts change to 1037.00 Hz and 1.00 Hz. The last caption reads “81 points, 1 Hz apart, from 1000 to 1080 Hz: the peak is at 1037 Hz. Same curve, finer grid; it cannot split two tones closer than about 31 Hz.” Once the clip has finished, dragging the band sideways, the arrow keys (steps of 5 Hz), Home or End move it, 80 Hz wide, with fLf_L from 900 to 1100 Hz, and the caption gives the highest point in the band.

The FFT’s nearest bin is 33, at 1031.25 Hz: the tone is somewhere between the bins. The zoom’s 81 points, 1 Hz apart from 1000 to 1080 Hz, put the peak at 1037 Hz.

Compare the two peak readouts. The FFT’s nearest bin is 5.75 Hz from the tone at 1037 Hz, while the 1 Hz grid lands 0.06 Hz from the true top of the curve at 1037.06 Hz. The zoom did not find a new tone. Like a map app, zooming in shows the same coastline in more detail; it does not add islands. In the same way, two tones closer than about 31 Hz still blur into one hump here, because 256 samples limit what the curve can show.

Afterwards the band is yours. Drag it sideways, or use the arrow keys, and the zoom recomputes. When the band leaves out 1037 Hz, the highest point sits at an edge of the band.

The cost of one zoom with Bluestein’s trick is three FFTs of 512 points, the first power of two at least 256+81−1=336256+81-1=336. That is 6912 complex multiplies, against 53 248 for the 8192-point zero-padded FFT.

The general version evaluates the spectrum along any spiral, not only along the circle you used here. The spiral lives in the z-plane of The z-transform (16.1), and that is why the method is called the chirp z-transform.

Worked example

Every number below was recomputed in Python and compared with numpy.fft.fft.

  1. DTMF bins (fs=8f_s=8 kHz, N=205N=205, spacing 39.02 Hz): k=round(Nf/fs)k=\mathrm{round}(Nf/f_s) gives 18, 20, 22, 24, 31, 34, 38 and 42, at 702.4, 780.5, 858.5, 936.6, 1209.8, 1326.8, 1482.9 and 1639.0 Hz.
  2. Goertzel on a 770 Hz tone (amplitude 1): ∣X[20]∣=91.183\lvert X[20]\rvert=91.183, ∣X[18]∣=13.646\lvert X[18]\rvert=13.646 and ∣X[24]∣=6.132\lvert X[24]\rvert=6.132, each equal to the FFT bin. In real form for k=20k=20: 2cos⁡Ω20=1.63592\cos\Omega_{20}=1.6359, q[204]=−118.605q[204]=-118.605, q[203]=−157.493q[203]=-157.493, and X[20]=60.483−68.236jX[20]=60.483-68.236j.
  3. A tone exactly on bin 20 gives ∣X[20]∣=N/2=102.5\lvert X[20]\rvert=N/2=102.5.
  4. Cost. Eight bins by Goertzel: 1640 real multiplies, plus 3 per bin at the end. A 256-point FFT: 4096 real multiplies. A direct DFT of 8 bins on real input: 2⋅205⋅8=32802\cdot205\cdot8=3280 real multiplies.
  5. Zoom. A 1037 Hz tone, N=256N=256, fs=8f_s=8 kHz. FFT bins 32, 33 and 34 sit at 1000, 1031.25 and 1062.5 Hz, with ∣X∣\lvert X\rvert of 19.16, 121.34 and 26.93. The zoom from 1000 to 1080 Hz, 81 points, peaks at 1037.0 Hz with ∣X∣=128.59\lvert X\rvert=128.59. SciPy’s zoom_fft (with endpoint=True) matches the direct sum to about 10−1210^{-12}.

Where you’ll meet this

Resonators and poles on the unit circle come in 16.3 and 17.4. Zero-padding and what resolution really means come in 15.3. Windowing, which tames the small leakage in the DTMF bars, is 15.1. Detection thresholds and false-alarm rates return in Chapter 25.

Reference card

QuantityFormulaNotes
Goertzel, complex formyk[n]=x[n]+ejΩkyk[n−1]y_k[n]=x[n]+e^{j\Omega_k}{y_k[n-1]}∣yk[N−1]∣=∣X[k]∣\lvert y_k[N-1]\rvert=\lvert X[k]\rvert
Goertzel, real formqk[n]=x[n]+2cos⁡Ωk qk[n−1]−qk[n−2]q_k[n]=x[n]+2\cos\Omega_k\,{q_k[n-1]}-{q_k[n-2]}one real multiply per sample
ResultX[k]=ejΩkqk[N−1]−qk[N−2]X[k]=e^{j\Omega_k}{q_k[N-1]}-{q_k[N-2]}Ωk=2πk/N\Omega_k=2\pi k/N
Power only∣X[k]∣2=qk[N−1]2+qk[N−2]2−2cos⁡Ωk qk[N−1] qk[N−2]\lvert X[k]\rvert^2={q_k[N-1]}^2+{q_k[N-2]}^2-2\cos\Omega_k\,{q_k[N-1]}\,{q_k[N-2]}no complex arithmetic
DTMFfs=8f_s=8 kHz, N=205N=205, bins 18, 20, 22, 24, 31, 34, 38, 424 row and 4 column tones
Zoom (chirp z)spectrum at fL+kfstepf_L+kf_\text{step}, k=0,…,Nzoom−1k=0,\ldots,N_\text{zoom}-1finer grid, not finer resolution

End of lesson 14.4

Where to go next.

Phasorium
LibraryEvery lesson, in order

Parts

About Phasorium
Look