1

我有这段代码,但它不断返回从 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

4 回答 4

7

假设oSignal以这样的方式填充复数,实部和虚部交替,它可能有助于改变

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

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

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

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

编辑:对于声音和吉他,你不走运。我前段时间写了一个显示频域的程序,试试看,你会发现问题。如果您有兴趣,也有可用的资源。

最后编辑:您可能想阅读有关音高检测的 Wikipedia 文章。专注于时域方法。

于 2009-08-29T13:06:51.760 回答
1

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

此外,您在整数除法中失去了一些精度。改成双音F = pitch / (8192.0/1024);

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

于 2009-08-29T13:07:32.790 回答
0

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

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

于 2009-08-29T13:07:06.643 回答
0

两件事情:

  • 你确定你fft正确使用你的功能吗?您将输出视为复杂的数组[R_1 I_1 R_2 I_2 ...],但您将输入数组视为已组织[R_1 R_2 R_3 ... R_1024 I_1 I_2 ...],并且正如 Henrik 所说,然后将复杂部分保持未初始化。
  • 您的峰值检测非常原始,尽管它应该适用于简单的输入(如单个吉他刺痛)。对于与人声一起使用,您几乎肯定需要更复杂的方法。

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

于 2009-08-30T15:35:30.023 回答