在 C 中使用 Goertzel 算法对复杂信号进行 DFT

信息处理 频谱 自由度
2022-01-25 15:17:58

我正在使用 TX 和 Rx 模块实现 BFSK 跳频系统。我在接收端使用 Goertzel 算法来解调数据,即确定接收信号数据的载波频率。以下是 goertzel 实现的实现:

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

floatnumSamples = (float) numSamples;
k = (int) (0.5 + ((floatnumSamples * TARGET_FREQUENCY) / SAMPLING_RATE));
omega = (2.0 * 3.1416 * k) / floatnumSamples;
sine = sin(omega);
cosine = cos(omega);
coeff = 2.0 * cosine;

q0=0;
q1=0;
q2=0;
result=0;

for(i=0; i<numSamples; i++)
{
    q0 = coeff * q1 - q2 + modData[i];
    q2 = q1;
    q1 = q0;
}

result = sqrtf(q1 * q1 + q2 * q2 - q1 * q2 * coeff);
return result;
}

该实现适用于接收信号是真实信号(一组浮点值)的信号。该算法是否仍适用于复杂信号。复数信号通常由一组浮点值表示,每个交替元素表示一个实数和虚数。在这种情况下,应该如何使用上述 goertzel 函数,应该使用它分别计算实部和虚部的输出,还是应该读取序列中的整个复信号数组元素(实部和虚部数组元素)然后计算它末尾的大小。如果没有,请指点我如何获得复杂信号样本的 goertzel 输出。我尝试用谷歌搜索它,但找不到任何关于如何在复杂信号上使用 goertzel 算法的具体信息。

另外,我还想问一件事。如果我的信号具有 4000 和 -4000 Hz 的载波频率和 18000 Hz 的采样频率,那么对于作为输入的真实信号,goertzel 输出对于 4000 Hz 和 14000Hz 的输入频率是相同的(这应该是) . 但由于 4000 Hz 和 -4000Hz 是我的载波频率之一,我无法确定接收到的信号是 4000 Hz 还是 -4000 Hz。有什么方法可以在不进行频移的情况下做到这一点。我能够使用频移来区分(在解调之前将接收到的信号与正弦波相乘)。但我正在寻找一种不使用频移技术的方法来做到这一点。

——安舒

1个回答

Goertzel 算法(实际上只是一种计算任意位置的单个 DFT bin 的有效方法)是为复杂输入定义的,就像 DFT 一样。实数输入信号实际上只是虚部等于 0 的一种特殊情况。就您的最后一个问题而言,如果您的输入信号是真实的,那么它的频谱是共轭对称的。这意味着 -4000 Hz 处的频谱值是 +4000 Hz 处的值的共轭。如果你想区分这两个频率,你需要一个复杂的输入信号。

其它你可能感兴趣的问题