【问题标题】:Implementation of Goertzel algorithm in C用 C 语言实现 Goertzel 算法
【发布时间】:2012-07-19 17:33:00
【问题描述】:

我正在 DSP 处理器上实现 BFSK 跳频通信系统。一些论坛成员建议使用 Goertzel 算法对特定频率的跳频进行解调。我已经尝试在 C 中实现 goertzel 算法。代码如下:

float goertzel(int numSamples,int TARGET_FREQUENCY,int SAMPLING_RATE, float* data)
{
    int     k,i;
    float   floatnumSamples;
    float   omega,sine,cosine,coeff,q0,q1,q2,result,real,imag;

    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;
    }
    real = (q1 - q2 * cosine);
    imag = (q2 * sine);
    result = sqrtf(real*real + imag*imag);
    return result;
}

当我使用该函数计算给定数据集的特定频率的结果时,我没有得到正确的结果。但是,如果我使用相同的数据集并使用 MATLAB goertzel() 函数计算 goertzel 结果,那么我会得到完美的结果。在网上找到的一些在线教程的帮助下,我使用 C 实现了算法。如果函数正确实现了 goertzel 算法,我只是想了解一下你们的看法。

【问题讨论】:

  • 您需要按样本数/2 来缩放您的答案
  • 如果你有一个好的 Matlab 实现和一个糟糕的 C 实现,你可以在 Matlab 版本中添加日志来计算循环中中间变量的值,然后将它们与 C 中的等价物进行比较版本。
  • 你发现你的问题了吗?
  • 嗨,这个解决方案确实有效,无论如何,我的实现的真正问题是,由于我的 IDE 错误地链接了文件,所以该值没有正确返回 .... 感谢您的帮助 ...

标签: c embedded signal-processing goertzel-algorithm


【解决方案1】:

考虑两个输入样本波形:

1) 幅度为 A 频率为 W 的正弦波

2) 幅度和频率A和W相同的余弦波

Goertzel 算法应该对提到的两个输入波形产生相同的结果,但提供的代码会产生不同的返回值。我认为代码应该修改如下:

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;
}

【讨论】:

    【解决方案2】:

    通常您可以在计算中使用幅度的平方, 例如用于音调检测。

    一些优秀的 Goertzel 示例在 Asterisk PBX DSP 代码中 Asterisk DSP code (dsp.c) 并在 spandsp 库中SPANDSP DSP Library

    【讨论】:

      【解决方案3】:

      如果您说 Matlab 实现很好,因为它的结果与数据的 DFT 或 FFT 频率的结果相匹配,那么可能是因为 Matlab 实现通过比例因子对结果进行归一化,就像使用FFT。

      更改您的代码以考虑到这一点,看看它是否会改善您的结果。请注意,为了清楚起见,我还更改了函数和结果名称以反映您的 goertzel 正在计算幅度,而不是完整的复杂结果:

      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;
      }
      

      【讨论】:

      • 嗨,这个解决方案确实有效,无论如何,我的实现的真正问题是,由于我的 IDE 错误地链接了文件,所以该值没有正确返回 .... 感谢您的帮助 ... .
      猜你喜欢
      • 2019-05-01
      • 1970-01-01
      • 2023-01-08
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2010-09-13
      • 2012-06-15
      相关资源
      最近更新 更多