我已经为iPhone实现了Demetri的Pitch Detector项目,并且遇到了两个问题。1)任何类型的背景噪声都会发出频率读数香蕉;2)低频声音的音调不正确。我试着调整我的吉他,当更高的弦工作时-调谐器不能正确地识别低音E。
基音检测代码位于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);
然后Demetri继续确定“主导”频率,如下所示:
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)];
首先,我认为我需要应用一个低通滤波器。但我不是快速傅立叶变换专家,我不确定在哪里或者如何对从vDSP函数返回的数据进行快速傅立叶变换。我也不确定如何在较低的频率下提高代码的准确性。似乎还有其他算法可以确定主导频率-但同样,在使用Apple的Accelerate框架返回的数据时,要在正确的方向上寻找突破口。
更新:
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_vmul(outputBuffer, 1, window, 1, transferBuffer, 1, windowSize);
在vDSP_ctoz函数之前。然后我将代码的其余部分改为使用“transferBuffer”而不是outputBuffer……但到目前为止,还没有注意到最终的音高猜测有任何戏剧性的变化。
发布于 2011-08-25 04:35:38
间距与峰值幅值频率bin不同(这是加速框架中的FFT可能直接提供给您的)。因此,任何峰值频率检测器对于基音估计都是不可靠的。当音符的基音缺失或非常弱(在某些声音、钢琴和吉他声音中很常见)和/或其频谱中有大量强大的泛音时,低通滤波器将无济于事。
看看你音乐声音的宽带谱或光谱图,你就会发现问题所在。
通常需要其他方法来更可靠地估计音高。其中一些包括自相关方法(AMDF、ASDF)、倒谱/倒谱分析、谐波乘积谱、相位声码器和/或复合算法(例如,用于音调跟踪的鲁棒算法)和YAAPT。FFT仅作为上述方法中的一个子部分有用。
发布于 2011-08-25 16:30:52
在计算window function之前,您至少需要对时域数据应用快速傅立叶变换。如果没有这一步,功率谱将包含伪影(参见:spectral leakage),这将干扰您提取基音信息的尝试。
一个简单的Hann (也就是Hanning)窗口应该足够了。
发布于 2011-08-25 17:14:03
你的样本频率和区块大小是多少?低E约为80 Hz,因此您需要确保捕获块足够长,以此频率捕获多个周期。这是因为傅立叶变换将频谱分成多个频段,每个频段宽几赫兹。例如,如果您以44.1 kHz采样,并且具有1024点的时域采样,则每个面元将是44100/1024 = 43.07 Hz宽。因此,低E会出现在第二个仓位中。由于一系列原因(与频谱泄漏和有限时间块的性质有关),实际上,您应该非常怀疑地考虑FFT结果中的前3或4个数据桶。
如果将采样率降至8 kHz,则相同的块大小会为您提供7.8125 Hz宽的存储箱。现在,低E将在第10或第11位,这要好得多。你也可以使用更长的块大小。
作为Paul R points out,您必须使用窗口来减少频谱泄漏。
https://stackoverflow.com/questions/7181630
复制相似问题