The Goertzel algorithm detects the presence of a chosen frequency range in an audio stream.
It's often used for tone decoding, such as in DTMF (tone dialing) and CTCSS (subaudible tone
squelch). Unlike many frequency-domain techniques such as the FFT, the Goertzel algorithm can be
done with SigmaStudio on SigmaDSP chips. This post describes a basic implementation, which I hope
others would improve on.
Goertzel's method is described in R. G. Lyons' book Understanding Digital Signal Processing,
pages 529-532, also in Wikipedia. It looks like a high-Q IIR filter but instead of running continuously
it processes frames of samples, like the FFT. Thus as with the FFT, you can easily trade off
frequency accuracy with aquisition time.
Most SigmaDSP flows operate at 48KHz, too high to efficiently detect DTMF tones around 1KHz.
That's why each delay in the signal path below totals six samples. This effectively runs the
Goertzel algorithm at (48/6) = 8KHz, the usual telephone rate. From here on in my text, fs' refers
to this effective sample rate. The rest of your system can still process hi-fi audio at 48KHz.
As with the FFT, choose the number of bins N dividing the input frequency range from 0 to
fs'. Your frequency resolution is (fs'/N), here (8000Hz/200) = 40 Hz. The algorithm updates after
each N samples, in the time (N/fs'). In the case shown that's (200/8000Hz) = 25mS. In the upper
right a square wave oscillator sets the frame time -- the frame runs while this is high, so set its
frequency to (fs'/2N). Here that's 20Hz.
Multiply your target frequency by N, then divide by fs' to get its frequency bin m. For example,
m = 1480*200 / 8000 = 37. Unlike the FFT, m need not be an integer -- Goertzel's method allows in-between bins.
Plug m into this formula to get the needed filter coefficient:
coeff = 2cos(2pi*m/N)
The cosine is in radians. If your coefficient is nearly 2.0, either the calculator is set for degrees, or your
effective sample rate is rather high for your target frequency. This coefficient is used twice in
the algorithm, in the second place it's negative. To change frequency within the constraints of fs' and
N, all you need do is change the coefficient.
As shown the project runs the Goertzel algorithm while the square wave timer is high, saves
the result at the square wave's downward transition, then flushes out the delays and rests during the
low time. Unfortunately this halves your update rate. There's probably a more efficient way to time
the algorithm (perhaps with counters), which I'll leave for later.
The attached project file runs directly on a mini ADAU1701 board. How well does it work? I
made the test input a VCO to produce the graph below. You get quite a precise resolution of frequency.
In addition, each update jumps right to its new value -- there's no long tail to wait for.
Goertzel's method is the standard for DSP tone detection -- and yes, you really can run it on any
Message was edited by: Robert Blowsky to correct the example calculation for m.