使用苹果的加速框架,FFT,汉宁窗口和重叠。

3

我正在为一个项目设置FFT,但是没有很清晰的概念...
基本上,我使用Audio Units从设备的麦克风获取数据。然后我想对那些数据做FFT。目前我的理解是:我需要为我的数据设置一个环形缓冲区。在每个填满的缓冲区上,我应用一个Hann窗口,然后做一个FFT。然而,我仍然需要一些关于重叠的帮助。为了获得更精确的结果,尤其是因为我正在使用窗口函数,我了解到我需要使用这个。但是我找不到任何相关内容...
这是我目前拥有的(用于音高检测):

// Setup -------------  
UInt32 log2N          = 10; // 1024 samples  
UInt32 N              = (1 << log2N);  
FFTSetup FFTSettings  = vDSP_create_fftsetup(log2N, kFFTRadix2);  
COMPLEX_SPLIT FFTData;  
FFTData.realp         = (float *) malloc(sizeof(float) * N/2);  
FFTData.imagp         = (float *) malloc(sizeof(float) * N/2);  
float * hannWindow = (float *) malloc(sizeof(float) * N);  

// create an array of floats to represent a hann window  
vDSP_hann_window(hannWindow, N, 0);

// FFT Time ----------  
// Moving data from A to B via hann window  
vDSP_vmul(A, 1, hannWindow, 1, B, 1, N);                                 

// Converting data in B into split complex form  
vDSP_ctoz((COMPLEX *) B, 2, &FFTData, 1, N/2);  

// Doing the FFT  
vDSP_fft_zrip(FFTSettings, &FFTData, 1, log2N, kFFTDirection_Forward);   

// calculating square of magnitude for each value  
vDSP_zvmags(&FFTData, 1, FFTData.realp, 1, N/2);  

// Inverse FFT  
vDSP_fft_zrip(FFTSettings, &FFTData, 1, log2N, kFFTDirection_Inverse);  

// Storing the autocorrelation results in B  
vDSP_ztoc(&FFTData, 1, (COMPLEX *)B, 2, N/2);  

vDSP_Length lastZeroCrosssing;  
vDSP_Length zeroCrossingCount;  
vDSP_nzcros(B, 1, N, &lastZeroCrossing, &zeroCrossingCount, N);  

// Cleanup -----------  
vDSP_destroy_fftsetup(FFTSettings);  
free(FFTOutput.realp);  
free(FFTOutput.imagp);  
free(hannWindow);

那么我应该在哪里以及如何包含重叠?同时,任何代码片段都将不胜感激。谢谢。

更新:

该项目的最终目标是对音频进行指纹识别,尽可能接近实时,因此我需要尽可能准确的结果 - 因此需要重叠。出于这个目的,我认为我实际上可以删除从反转到清理的所有部分。

1个回答

1
你实际上不需要重叠 - 通常情况下,帧是重叠的,以在时间轴上提供更高的分辨率,例如用于绘制声谱图或估计音符起始时间。你可以先让代码正常运行而不进行重叠,因为这样做会更简单,然后再决定是否需要在时间轴上获得更高的分辨率。
如果你决定要添加重叠,那么你需要保存前一缓冲区的一部分(例如50%),然后对于每个新缓冲区,你将按如下方式处理两个完整的缓冲区:
- 处理旧缓冲区的最后50%+新缓冲区的第一个50% - 处理新缓冲区的100% - 保存新缓冲区的最后50%以备下一次迭代使用
对于不同的重叠百分比,类似的逻辑也适用。
请注意,将重叠增加到一定程度可能会适得其反,因为所需的处理带宽会大大增加,而分辨率的提高却很少。

好的 - 请查看我的回答最后一部分以了解如何进行重叠。 - Paul R
我正在考虑将采样率降低到约16kHz,而不是典型的44.1KHz。这应该可以让我增加更大的重叠,而不会显著增加处理带宽。无论如何,我会尝试一下并告诉你结果如何。 - Andrei Filip
如果您对更高频率的组件不感兴趣,那么请尽可能降低采样率以减少计算带宽。我建议从50%重叠开始,这会使计算需求增加一倍。我肯定不会超过75%的重叠(4倍计算带宽)。 - Paul R
我对语音频率比其他任何事情都更感兴趣,考虑到这一点,我认为我可以降到10kHz以下。你是否知道任何样本代码或者可以在哪里找到一些样本代码?这里有很多C代码,而不是我习惯使用的Objective-C。 - Andrei Filip
好的,缓冲区管理方面的内容相当简单。我认为您可以使用现有的iOS API以较低的采样率获取音频。还有其他需要编写代码的吗? - Paul R
一切都将是理想的:))(不开玩笑) - Andrei Filip

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接