Implementation of Goertzel algorithm in C

前端 未结 3 1206
难免孤独
难免孤独 2020-12-29 10:13

I am implementing BFSK frequency hopping communication system on a DSP processor. It was suggested by some of the forum members to use Goertzel algorithm for the demodulatio

相关标签:
3条回答
  • 2020-12-29 10:56

    Consider two input sample wave-forms:

    1) a sine wave with amplitude A and frequency W

    2) a cosine wave with the same amplitude and frequency A and W

    Goertzel algorithm should yield the same results for two mentioned input wave-forms but the provided code results in different return values. I think the code should be revised as follows:

    float goertzel_mag(int numSamples,int TARGET_FREQUENCY,int SAMPLING_RATE, float* data)
    {
        int     k,i;
        float   floatnumSamples;
        float   omega,sine,cosine,coeff,q0,q1,q2,magnitude,real,imag;
    
        float   scalingFactor = numSamples / 2.0;
    
        floatnumSamples = (float) numSamples;
        k = (int) (0.5 + ((floatnumSamples * TARGET_FREQUENCY) / SAMPLING_RATE));
        omega = (2.0 * M_PI * k) / floatnumSamples;
        sine = sin(omega);
        cosine = cos(omega);
        coeff = 2.0 * cosine;
        q0=0;
        q1=0;
        q2=0;
    
        for(i=0; i<numSamples; i++)
        {
            q2 = q1;
            q1 = q0;
            q0 = coeff * q1 - q2 + data[i];
        }
    
        // calculate the real and imaginary results
        // scaling appropriately
        real = (q0 - q1 * cosine) / scalingFactor;
        imag = (-q1 * sine) / scalingFactor;
    
        magnitude = sqrtf(real*real + imag*imag);
        return magnitude;
    }
    
    0 讨论(0)
  • 2020-12-29 11:06

    If you are saying that the Matlab implementation is good because its results match the result for that frequency of a DFT or FFT of your data, then it's probably because the Matlab implementation is normalizing the results by a scaling factor as is done with the FFT.

    Change your code to take this into account and see if it improves your results. Note that I also changed the function and result names to reflect that your goertzel is calculating the magnitude, not the complete complex result, for clarity:

    float goertzel_mag(int numSamples,int TARGET_FREQUENCY,int SAMPLING_RATE, float* data)
    {
        int     k,i;
        float   floatnumSamples;
        float   omega,sine,cosine,coeff,q0,q1,q2,magnitude,real,imag;
    
        float   scalingFactor = numSamples / 2.0;
    
        floatnumSamples = (float) numSamples;
        k = (int) (0.5 + ((floatnumSamples * TARGET_FREQUENCY) / SAMPLING_RATE));
        omega = (2.0 * M_PI * k) / floatnumSamples;
        sine = sin(omega);
        cosine = cos(omega);
        coeff = 2.0 * cosine;
        q0=0;
        q1=0;
        q2=0;
    
        for(i=0; i<numSamples; 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 = sqrtf(real*real + imag*imag);
        return magnitude;
    }
    
    0 讨论(0)
  • 2020-12-29 11:16

    Often you can just use the square of the magnitude in your computations, for example for tone detection.

    Some excellent examples of Goertzels are in the Asterisk PBX DSP code Asterisk DSP code (dsp.c) and in the spandsp library SPANDSP DSP Library

    0 讨论(0)
提交回复
热议问题