An5647 The Goertzel Algorithm To Compute Individual Terms of The Discrete Fourier Transform DFT in Stm32 Products Stmicroelectronics
An5647 The Goertzel Algorithm To Compute Individual Terms of The Discrete Fourier Transform DFT in Stm32 Products Stmicroelectronics
Application note
Introduction
This application note explains how to compute individual terms of the discrete Fourier transform using the Goertzel algorithm in
STM32 products.
The Goertzel algorithm is derived and implemented as an iteration loop and as an IIR filter. A reference implementation based
on the FFT is also included for verification.
The Goertzel algorithm is generalized to the non-integer frequency index case.
An application example is included: the dual-tone multi-frequency (DTMF) decoding. A MATLAB® script is used to generate a
test signal and perform floating point decoding. A fixed-point C implementation is also provided.
1 General information
A set of N signal samples x() is transformed into a set of N frequency coefficients y() using the discrete Fourier
transform (DFT): y(k) = sum of W(nk) x(n), where n and k go from 0 to N-1 and the twiddle factor W(t) is defined
as exp (-j 2 π/N t).
The twiddle factor has the property that W(-Nk) = 1 for all k, therefore the k-th coefficient y(k) is the y(k) = sum of
W (k (n-N)) x(n). The sum can be unfolded and manipulated to make it recursive:
It is evident that the frequency coefficient y(k) can be computed in N steps using the following recursive formula:
yn(k) = W(-k) [ x(n) + yn-1(k) ], where n goes from 0 to N-1, y0(k) = 0.
The recursive formula can be seen as a second order IIR filter because it is a weighted sum of the input sample
x and the previous output y. Of course, only the final output yN-1(k) is of interest, intermediate outputs are not
needed. It is possible to manipulate the coefficients of the filter so that the computation is done using real
numbers, except for the last step where the final complex output yN-1(k) is computed.
The recursive formula in z-domain is:
Y z = W −k X z + Y z z−1
Therefore the filter transfer function is:
Y z W −k
H z = =
X x 1 − W − k z−1
There is no change if the numerator and the denominator are multiplied by the same quantity (1 – W(+k) z-1).
W − k 1 − W + k z−1
H z =
1 − W − k z−1 1 − W + k z−1
W − k − W − k W + k z−1
H z =
1 − W − k + W + k z−1 + W − k W + k z−2
j2π − j2π
Remember that W − k = exp Nk and W + k = exp Nk , therefore W − k W + k = exp 0 = 1
2π
and W − k + W + k = 2cos Nk
W − k − z−1
H z =
1 − 2cos 2π/Nk z−1 + z−2
If the filter is implemented as direct II form (Figure 1), the status registers of the filter are real numbers, and
multiplications and additions in the feedback loop are real. One complex multiplication is needed at the last step
to compute the real and the imaginary part of the output y(k).
Figure 1. Direct II form for H(z) = (W – z – 1) / (1 – cz – 1 + z – 2), W = exp (j 2π/N k), c = 2cos(2π/N k)
w2 = 2*pi*k;
cw2 = cos(w2);
sw2 = sin(w2);
I = It*cw2 + Qt *sw2;
Q = -It*sw2 + Qt*cw2;
[I1,Q1] = goertzelC(x,k,N);
[I2,Q2] = goertzelIIR(x,k,N);
[I3,Q3] = goertzelFFT(x,k,N);
disp([I1 I2 I3]); % all equal
disp([Q1 Q2 Q3]); % all equal
[I4,Q4] = goertzelgen(x,kf,N);
[I5,Q5] = IQmixer(x,kf,N);
disp([I4 I5]); % all equal
disp([Q4 Q5]); % all equal
The dual-tone multi-frequency signaling (DTMF) has been developed by the Bell System in the United States. It is
standardized as ITU-T Rec Q.23. It is also known as “touch-tone” as tones are generated by pushing the buttons
in the keypad of telephones.
697 Hz 1 2 3 A
770 Hz 4 5 6 B
852 Hz 7 8 9 C
941 Hz * 0 # D
Whenever a button is pressed, two tones are generated with the frequency indicated in the corresponding row
and column. It would be inefficient to compute a full FFT to detect the presence of these tones. On the opposite,
the Goertzel algorithm can be used to efficiently compute the frequency coefficients of the eight tones that can be
present in the signal.
bits = 8;
Q = (max(x)-min(x))/(2^bits); % quantization step for 8 bit signal
x = round(x/Q); % some noise may also be added
th = max(myspec(:))/2; % threshold
myspecbin = myspec>th; % tone on/off detection
symout = [];
for i = 1 : xblocks,
i1 = find(myspecbin(i,1:4)>0); if length(i1)~=1, i1=0; end; % 1st tone
i2 = find(myspecbin(i,5:8)>0); if length(i2)~=1, i2=0; end; % 2nd tone
if (i1==0) || (i2==0), symdec=' '; % no symbol decoded
else symdec=sym(symmtx(i1,i2)); % symbol decoded
end;
symout = [symout, symdec]; % append decoded symbol
end;
figure; imagesc(fbin*k/1000,[0:xblocks]*N/Fs*1000,myspec);
axis xy; axis([0 Fs/2/1000 0 length(x)/Fs*1000]); colorbar;
xlabel('Frequency (kHz)'); ylabel('Time (ms)');
title(sprintf('DTMF test, %d-bit Fs=%.1f kHz, %d-point Goertzel',bits,Fs/1000,N));
figure; imagesc(fbin*k/1000,[0:xblocks]*N/Fs*1000,myspecbin);
axis xy; axis([0 Fs/2/1000 0 length(x)/Fs*1000]); colorbar;
xlabel('Frequency (kHz)'); ylabel('Time (ms)');
title(sprintf('DTMF test, %d-bit Fs=%.1f kHz, %d-point Goertzel, th=%1.f',bits,Fs/
1000,N,th));
The script plots the spectrogram of the generated signal (Figure 2), as well as the frequency coefficients
computed by the Goertzel algorithm (Figure 3 and Figure 4). The coefficients above threshold drive the decoding.
Figure 3. Frequency coefficients computed by the Figure 4. Frequency coefficients above threshold
Goertzel algorithm
The computation of the Goertzel constants is based on sin() and cos(). These functions can be implemented in
fixed-point using the CORDIC algorithm.
Note: For more informations about CORDIC algorithm refer to DT0087.
In the program the squared magnitude is computed, therefore a squared threshold must be used for decoding.
The magnitude can also be computed and used: the sqrt() function must be implemented in fixed-point using the
CORDIC algorithm.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// DTMF frequencies
int frow[4] = { 697, 770, 852, 941 }; // 1st tone
int fcol[4] = { 1209, 1336, 1477, 1633 }; // 2nd tone
// DTMF symbols
char sym[16] = { '1', '4', '7', '*', '2', '5', '8', '0',
'3', '6', '9', '#', 'A', 'B', 'C', 'D' };
// Goertzel
int c[8], cw[8], sw[8]; // Goertzel constants
int z1[8], z2[8]; // Goertzel status registers
int I[8], Q[8], M2[8]; // Goertzel output: real, imag, squared magnitude
for(n=0;!feof(f);) {
i = fscanf(f,"%d",&x); if(i<1) continue;
x = ((x*win[n])>>b); // windowing
if((n%N)==0) for(i=0;i<8;i++) { z1[i]=0; z2[i]=0; } // Goertzel reset
// **** GOERTZEL ITERATION ****
for(i=0;i<8;i++) {
z0 = x + ((c[i]*z1[i])>>b) - z2[i]; // Goertzel iteration
z2[i] = z1[i]; z1[i] = z0; } // Goertzel status update
// **** GOERTZEL ITERATION ****
n++; if((n%N)==0) { n=0; // finalize and decode
for(i1=i2=-1,i=0;i<8;i++) {
// CORDIC may be used here to compute atan2() and sqrt()
I[i] = ((cw[i]*z1[i])>>b) - z2[i]; // Goertzel final I
Q[i] = ((sw[i]*z1[i])>>b); // Goertzel final Q
M2[i] = I[i]*I[i] + Q[i]*Q[i]; // magnitude squared
if(M2[i]>th) { // DTMF decoding
if(i<4) { if(i1==-1) i1=i; else i1=4; } // find 1st tone, one peak allowed
else { if(i2==-1) i2=i-4; else i2=4; } // find 2nd tone, one peak allowed
} }
if((i1>-1)&&(i1<4)&&(i2>-1)&&(i2<4)) printf("%c",sym[symmtx[i1][i2]]);
else printf(" ");
} }
printf("\n\n"); fclose(f); return 0;
}
The C output for a typical run on the same signal as the MATLAB is the following:
Revision history
Contents
1 General information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1 Reference documents. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
List of tables
Table 1. Dual-tone multi-frequency (DTMF) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Table 2. Document revision history . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
List of figures
Figure 1. Direct II form for H(z) = (W – z – 1) / (1 – cz – 1 + z – 2), W = exp (j 2π/N k), c = 2cos(2π/N k) . . . . . . . . . . . . . 4
Figure 2. Spectrogram of the generated test signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Figure 3. Frequency coefficients computed by the Goertzel algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Figure 4. Frequency coefficients above threshold . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9