我已经有了这段代码,但它会随机返回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);
谢谢,
尼尔。
编辑:更改了代码,但它仍然返回随机频率。
答案 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,然后将复杂部分保留为未初始化。 您是否尝试过将已知的简单(即纯正弦)信号作为输入?