FFT问题(返回随机结果)

时间:2009-08-29 12:59:30

标签: c++ c fft

我已经有了这段代码,但它会随机返回0到1050左右的频率。请你能帮我理解为什么会这样。

我的数据长度为1024,采样率为8192,数据是一个填充了麦克风输入数据的短阵列。


float *iSignal = new float[2048];
float *oSignal = new float[2048];
int pitch = 0;

for(x=0;x<=1024;x++) {
    iSignal[x] = data[x];
}

fft(iSignal,oSignal,1024); //Input data, output data, length of input and output data

for(int y=0;y< 2048;y+=2) {
if((pow(oSignal[y],2)+pow(oSignal[y+1],2))>(pow(oSignal[pitch],2)+pow(oSignal[(pitch)+1],2))) {
        pitch = y;
    }
}

double pitchF = pitch / (8192.0/1024);
printf("Pitch: %f\n",pitchF);

谢谢,

尼尔。

编辑:更改了代码,但它仍然返回随机频率。

4 个答案:

答案 0 :(得分:7)

假设oSignal以这种方式填充了复数,实部和虚部交替出现,可能有助于改变

for(int y=0;y< 8191;y++)

for(int y=0;y< 8191;y+=2)

编辑:我甚至没有注意到你只传递了1024个样本。您必须传递与频域样本一样多的时域样本,在您的情况下为4096。

编辑:还有一件事:你显然试图找到某些东西的基频。除非某些东西是计算机生成的音调或人的哨声(两者都是非常纯净的音调),否则您可能会对结果感到失望。你发布的简单方法几乎不适用于长笛。

编辑:对于声音和吉他,你运气不好。我前段时间写过a program来显示频域,尝试一下,你会看到问题所在。如果您有兴趣,还有sources可用。

最终修改:您可能需要阅读维基百科article on pitch detection。专注于时域方法。

答案 1 :(得分:1)

似乎是iSignal [1025] .. iSignal [8191]包含随机数据。您可以尝试将其设置为0。 但是,如果数据长度为1024(或者是1025),为什么要将8192传递给fft()?

此外,你在整数除法中失去了一些精度。将其更改为 double pitchF = pitch /(8192.0 / 1024);

您的fft功能是否需要真实或复杂的输入数据?如果它需要复杂数据,则必须将iSignal的每个其他条目设置为0。

答案 2 :(得分:0)

“从0到大约1050的随机频率” - 典型的音频信号不是由频率组合组成的吗?由于您的采样率为8192 Hz,因此您的FFT可以检测到高达8192/2 = 4096 Hz。我希望你会看到许多频率的组合,但我不会称它们为“随机”。

你为什么感到惊讶?我错过了什么?

答案 3 :(得分:0)

两件事:

  • 您确定正确使用了fft功能吗?您将输出视为组织[R_1 I_1 R_2 I_2 ...]的复杂数组,但您将输入数组视为有组织[R_1 R_2 R_3 ... R_1024 I_1 I_2 ...]as Henrik says,然后将复杂部分保留为未初始化。
  • 你的peak detection是非常原始的,虽然它应该用于简单的输入(如单吉他刺)。为了与人类的声音一起使用,你几乎肯定想要一种更复杂的方法。

您是否尝试过将已知的简单(即纯正弦)信号作为输入?