我已经为iPhone实施了Demetri的Pitch Detector项目,并解决了两个问题。 1)任何种类的背景噪音都会传送频率读数香蕉,2)低频率的声音没有正确传送。我试着调整我的吉他,而较高的琴弦工作 - 调谐器不能正确辨别低E.iPhone上的FFT忽略背景噪音并找到较低音高
基音检测代码位于RIOInterface.mm,去这样的事情...
// get the data
AudioUnitRender(...);
// convert int16 to float
Convert(...);
// divide the signal into even-odd configuration
vDSP_ctoz((COMPLEX*)outputBuffer, 2, &A, 1, nOver2);
// apply the fft
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);
// convert split real form to split vector
vDSP_ztoc(&A, 1, (COMPLEX *)outputBuffer, 2, nOver2);
德米特里然后继续确定为“显性”频率如下:
float dominantFrequency = 0;
int bin = -1;
for (int i=0; i<n; i+=2) {
float curFreq = MagnitudeSquared(outputBuffer[i], outputBuffer[i+1]);
if (curFreq > dominantFrequency) {
dominantFrequency = curFreq;
bin = (i+1)/2;
}
}
memset(outputBuffer, 0, n*sizeof(SInt16));
// Update the UI with our newly acquired frequency value.
[THIS->listener frequencyChangedWithValue:bin*(THIS->sampleRate/bufferCapacity)];
首先,我认为我需要申请一个低通滤波器......但我不是专家FFT,而不是确切地确定在哪里或如何对vDSP函数返回的数据做到这一点秒。我也不确定如何提高低频率代码的准确性。似乎还有其他算法来确定主频 - 但是,当使用Apple的Accelerate框架返回的数据时,再次寻找正确的方向。
更新:
加速框架实际上有一些窗口功能。我建立一个基本的窗口,这样
windowSize = maxFrames;
transferBuffer = (float*)malloc(sizeof(float)*windowSize);
window = (float*)malloc(sizeof(float)*windowSize);
memset(window, 0, sizeof(float)*windowSize);
vDSP_hann_window(window, windowSize, vDSP_HANN_NORM);
我再由vDSP_ctoz功能之前插入
vDSP_vmul(outputBuffer, 1, window, 1, transferBuffer, 1, windowSize);
适用。然后我改变其余的代码来使用'transferBuffer'而不是outputBuffer ...但是到目前为止,还没有注意到最终音调猜测有任何显着的变化。
我记得几年前玩过这些东西的两件事:你可以通过从预定量中减去原始输入数据来设置背景声音的静噪水平(你现在可以猜到,直到你的数字出了一个好的算法),设置任何低于0到0的值,并且由于某些原因,我记不起来了,所以不要记录为更大的声音,因此在比较之前需要按指数规模放大低频率音量到更高的主导频率。 –
在FFT之前,您似乎没有应用合适的窗口函数,因此在功率谱中将会出现很多伪影,这可能会扰乱任何尝试进行基音检测的尝试。 –
这里有一个类似的答案几乎重复的问题:http://stackoverflow.com/questions/4227420/matlab-missing-fundamental-from-an-fft – hotpaw2