I'm trying to detect some frequencies of 18Khz with sample rate of 44100 [samples/sec].

When I pass a buffer(~4500 samples) to the algorithm it returns a magnitude in a very strange range. Sometimes i get 0.1, or 7 or 250(!) or 154 or 25000 - very strange. I can't decide on a threshold boundary for the filter. Is there any way noramlizing that result? (My result is the magnitude of the complex calculation of real and image)

This is my Goertzel code:

public float goertzel_mag(float[] data,int numSamples, int TARGET_FREQUENCY, int SAMPLING_RATE,int start,int end)
        int k, i;
        float floatnumSamples;
        float omega, sine, cosine, coeff, q0, q1, q2, magnitude, real, imag;

        float scalingFactor = (float)(numSamples / 2.0);

        floatnumSamples = (float)numSamples;
        k = (int)(0.5 + ((floatnumSamples * TARGET_FREQUENCY) / SAMPLING_RATE));
        omega = (float)(2.0 * Math.PI * k) / floatnumSamples;
        sine = (float)Math.Sin(omega);
        cosine = (float)Math.Cos(omega);
        coeff = (float)2.0 * cosine;
        q0 = 0;
        q1 = 0;
        q2 = 0;

        for (i = start; i < end; i++)
            q0 = coeff * q1 - q2 + data[i];
            q2 = q1;
            q1 = q0;

        // calculate the real and imaginary results
        // scaling appropriately
        real = (q1 - q2 * cosine) / scalingFactor;
        imag = (q2 * sine) / scalingFactor;

        magnitude = (float)Math.Sqrt(real * real + imag * imag);
        return magnitude;

Your Goertzel code looks okay, the standard fare.

Regarding normalization and thresholds, if you're detecting 18kHz, you should calibrate your signal at different levels and establish a threshold from that data

  • Start with full-scale (1.0, 0dBFS) 18kHz tones, as those should give you the highest magnitude over the course of your buffer (4500 samples) and then
  • Repeat the Goertzel filter mag measurements on tones all the way down in level, as much as you care but I would measure at least 6dB.
  • Finally, run your Goertzel filter over non-tonal material, or buffers of audio that don't contain what you're looking for. This will give you an idea of what the filter will output in the non-tone case. In my application, environmental audio/speech can have incidental tones in the range I'm looking for (400-600Hz) and I want to make sure to understand what Goertzel magnitudes I would get versus Goertzel magnitudes in the presence of a real tone.
  • $\begingroup$ Hello ruoho, I tried to do a calibration but I got some big problems. What I try to do is like that: I send an ASCII where 1 is 18k of 75ms duration and 0 is a silence. When trying to detect that the Goertzel fro example gives for 0 a magnitude of 1.24 and for 1 a 0.3, and again 1 can be 1.5,1.7 or whatever. When changing 18k to 13k everything works fine. I got a spectrum analyzer to check if 18k is coming out of the speaker and it not get aliaised and the spectrum shows 18K. What can I do? $\endgroup$ May 29 '15 at 7:20
  • $\begingroup$ do you have a github project location or some project code to share? I don't have a clear sense of how you're setting up your calibration experiment $\endgroup$ May 29 '15 at 19:13
  • $\begingroup$ Hello, sorry for misunderstanding. You say that I start with 0db. My problem is that I have 2 freqs switching each other: 18k,20k. When the goertzel pass back the result it is so small that I can't know how to define the threshold. Of course I know how to define for a example a non tonal but it's out of my range. $\endgroup$ Jun 1 '15 at 7:07
  • $\begingroup$ okay, if the result is too small to be discriminable, i think you need a bigger buffer (so goertzel can observe longer) otherwise, this may not be the analysis method that is most suitable. Again, you're only starting at 0dB to be able to "sweep" the range, you can start anywhere, but you need to have an idea of what values goertzel will give you for any frequency at any level. Does that make sense? $\endgroup$ Jun 1 '15 at 17:01
  • $\begingroup$ I know that for 13Khz the average threshold is 20. So for 18KHz it so small I have no indication for that threshold. $\endgroup$ Jun 1 '15 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.