Re: Goertzl Algorithm

Hi,

> > I am looking for an open source implementation > for decoding DTMF signals using Goertzl Algorithm > in C language. I searched the internet, but did not > get an open source implementation in C language. > I searched the internet and landed in the below link, > but the 'Listing 1' as mentioned in the contents of > the below link does not seem to work -
formatting link
020819S0057
Any other links/open source implementation ? > > Thx in advans, > Karthik Balaguru

It worked for me. Here is Listing 1:

Listing 1 A Goertzel implementation

#include #include

#define FLOATING float #define SAMPLE unsigned char

#define SAMPLING_RATE 8000.0 //8kHz #define TARGET_FREQUENCY 941.0 //941 Hz #define N 205 //Block size

FLOATING coeff; FLOATING Q1; FLOATING Q2; FLOATING sine; FLOATING cosine;

SAMPLE testData[N];

/* Call this routine before every "block" (size=3DN) of samples. */ void ResetGoertzel(void) { Q2 =3D 0; Q1 =3D 0; }

/* Call this once, to precompute the constants. */ void InitGoertzel(void) { int k; FLOATING floatN; FLOATING omega;

floatN =3D (FLOATING) N; k =3D (int) (0.5 + ((floatN * TARGET_FREQUENCY) / SAMPLING_RATE)); omega =3D (2.0 * PI * k) / floatN; sine =3D sin(omega); cosine =3D cos(omega); coeff =3D 2.0 * cosine;

printf("For SAMPLING_RATE =3D %f", SAMPLING_RATE); printf(" N =3D %d", N); printf(" and FREQUENCY =3D %f,\n", TARGET_FREQUENCY); printf("k =3D %d and coeff =3D %f\n\n", k, coeff);

ResetGoertzel(); }

/* Call this routine for every sample. */ void ProcessSample(SAMPLE sample) { FLOATING Q0; Q0 =3D coeff * Q1 - Q2 + (FLOATING) sample; Q2 =3D Q1; Q1 =3D Q0; }

/* Basic Goertzel */ /* Call this routine after every block to get the complex result. */ void GetRealImag(FLOATING *realPart, FLOATING *imagPart) { *realPart =3D (Q1 - Q2 * cosine); *imagPart =3D (Q2 * sine); }

/* Optimized Goertzel */ /* Call this after every block to get the RELATIVE magnitude squared.

*/ FLOATING GetMagnitudeSquared(void) { FLOATING result;

result =3D Q1 * Q1 + Q2 * Q2 - Q1 * Q2 * coeff; return result; }

/*** End of Goertzel-specific code, the remainder is test code. */

/* Synthesize some test data at a given frequency. */ void Generate(FLOATING frequency) { int index; FLOATING step;

step =3D frequency * ((2.0 * PI) / SAMPLING_RATE);

/* Generate the test data */ for (index =3D 0; index < N; index++) { testData[index] =3D (SAMPLE) (100.0 * sin(index * step) + 100.0); } }

/* Demo 1 */ void GenerateAndTest(FLOATING frequency) { int index;

FLOATING magnitudeSquared; FLOATING magnitude; FLOATING real; FLOATING imag;

printf("For test frequency %f:\n", frequency); Generate(frequency);

/* Process the samples */ for (index =3D 0; index < N; index++) { ProcessSample(testData[index]); }

/* Do the "basic Goertzel" processing. */ GetRealImag(&real, &imag);

printf("real =3D %f imag =3D %f\n", real, imag);

magnitudeSquared =3D real*real + imag*imag; printf("Relative magnitude squared =3D %f\n", magnitudeSquared); magnitude =3D sqrt(magnitudeSquared); printf("Relative magnitude =3D %f\n", magnitude);

/* Do the "optimized Goertzel" processing */ magnitudeSquared =3D GetMagnitudeSquared(); printf("Relative magnitude squared =3D %f\n", magnitudeSquared); magnitude =3D sqrt(magnitudeSquared); printf("Relative magnitude =3D %f\n\n", magnitude);

ResetGoertzel(); }

/* Demo 2 */ void GenerateAndTest2(FLOATING frequency) { int index;

FLOATING magnitudeSquared; FLOATING magnitude; FLOATING real; FLOATING imag;

printf("Freq=3D%7.1f ", frequency); Generate(frequency);

/* Process the samples. */ for (index =3D 0; index < N; index++) { ProcessSample(testData[index]); }

/* Do the "standard Goertzel" processing. */ GetRealImag(&real, &imag);

magnitudeSquared =3D real*real + imag*imag; printf("rel mag^2=3D%16.5f ", magnitudeSquared); magnitude =3D sqrt(magnitudeSquared); printf("rel mag=3D%12.5f\n", magnitude);

ResetGoertzel(); }

int main(void) { FLOATING freq;

InitGoertzel();

/* Demo 1 */ GenerateAndTest(TARGET_FREQUENCY - 250); GenerateAndTest(TARGET_FREQUENCY); GenerateAndTest(TARGET_FREQUENCY + 250);

/* Demo 2 */ for (freq =3D TARGET_FREQUENCY - 300; freq

Reply to
2G
Loading thread data ...

20020819S0057

I think, the server would have been down or some other problem.

Thx, Karthik Balaguru

Reply to
karthikbalaguru

Why for the love of god would you do that!

Reply to
bigbrownbeastie

There's no accounting for style.

Jerry

-- Leopold Kronecker on mathematics: God created the integers, all else is the work of man. ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Reply to
Jerry Avins

Guessing but probably so that he can more easily port the code between platforms that only offer floats and those with real doubles or long doubles. Might not be best for production but I can see it for test code that's being sampled on assorted processors.

--
Rich Webb     Norfolk, VA
Reply to
Rich Webb

Note that there is a difference between just using a Goertzel filter, and decoding DTMF. For decoding, there needs to be a decision criteria, so you might want to do a running estimate the average signal power and the noise floor and use those as part of your decision criteria.

Also, a Goertzel filter is similar to a 1-bin DFT. And thus if the frequency of interest, or any other strong frequencies present, are non-periodic in the length of the filter, then you may get "leakage artifacts". You might be able to minimize these "artifacts" by pre-windowing the data.

Somewhere on my website is an explanation of this 1-bin DFT/Goertzel "leakage":

formatting link

IMHO. YMMV.

-- rhn A.T nicholson d.0.t C-o-M

Reply to
Ron N.

-

formatting link

...

... It worked after adding the following line: #define PI 3.14159265358979

PI is not defined by the either of the standard headers.

--
Thad
Reply to
Thad Smith

Did you try M_PI?

--

Tauno Voipio
tauno voipio (at) iki fi
Reply to
Tauno Voipio

That's not defined by a Standard C header, either. Either one of those might be defined in a non-conforming compiler, but not Standard C.

--
Thad
Reply to
Thad Smith

Hi Ron It's the "Frequency Response of Zero-padded FFT/DFT" section of your web page. By the way, I thnk your "Common FFT Usage Misconceptions" material is interesting.

See Ya', [-Rick-]

Reply to
Rick Lyons

The most common FFT misconception is the one with is scaling of the FFT results. It had been 1000 times when I had to explain them that they can't compare 512pt FFT to 4096pt FFT directly; people just don't seem to understand that. It is also very common to see a spectral plot without any reference to the bin width.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

So the C standard leaves PI defintion, as well as other constants (for example, log2e, log10e) to implementation?

--
Mark
Reply to
Mark

-

formatting link

Best use

#include double pi = acos(-1);

This will continue to work even if the value of pi changes in the future.

--

John Devereux
Reply to
John Devereux

I would believe there could be confusion about that. What do you find to be the most common area of misconception? The frequency represented by a particular bin number? The bin "width"? Something about the time/resolution trade-off when changing the number of points?

I'll add that to my list.

-- rhn A.T nicholson d.0.t C-o-M

Reply to
Ron N.

Let's say there is a mix of a sine wave and a white noise. They take a

512-pt FFT of this mix, measure the amplitude of the FFT peak and the noise floor level, then calculate peak to noise floor difference in dB. They are absolutely sure this number === actual SNR.

Then they take another measurement, using FFT with 4096 points at this time. They calculate SNR in the same way, and compare it to the first result. -Aha! We got an improvement!

Not very many people actually understand what is the meaning of the FFT result, and what is the relation between dB, V and V/root(Hz).

VLV

Reply to
Vladimir Vassilevsky

"Processing gain" seems counter-intuitive to some people. Sometimes you can get the idea across to people with an rf background by explaining it's no different than SNR improvement via BW reduction.

--
Eric Jacobsen
Minister of Algorithms
Abineau Communications
http://www.abineau.com
Reply to
Eric Jacobsen

Let's put it simpler. It is very common that FFT plots are in dB wrt full scale. What I really want to see is the spectral density plot (W/Hz). Most people just can't understand the difference.

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

No. It is left to the careful programmer. It could have been defined in Standard C, but wasn't (there may be a need to define separate values for double and long double, possibly float).

Since there is no definition of pi in Standard C, the careful programmer provides his own, giving a portable program. If compiler XYZ defines PI or M_PI, and you use it, the program works for that compiler, but not another.

There are probably portable add-on libraries that add those constants and other useful constants and functions.

For publishing code though, it makes more sense to me to add one additional line to make it not compiler-dependent.

--
Thad
Reply to
Thad Smith

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.