我正在尝试根据给定的频率获得正确的FFT bin索引。音频正在44.1k Hz
采样,FFT大小为1024
。鉴于信号是真实的(从PyAudio捕获,通过numpy.fromstring
解码,由scipy.signal.hann
加窗),然后我通过scipy.fftpack.rfft
执行FFT,并计算整个结果的分贝{ {1}}
基于this和this,我最初将我的映射从FFT bin索引magnitude = 20 * scipy.log10(abs(rfft(audio_sample)))
到任意频率k
,如下:
F
其中F = k*Fs/N for k = 0 ... N/2-1
是采样率,Fs
是FFT bin大小,在本例中为N
。反之亦然:
1024
但是,在k = F*N/Fs for F = 0Hz ... Fs/2-Fs/N
大小数组中,意识到rfft
的结果与fft
不对称,并提供结果。我现在对映射和功能有一些疑问。不幸的是,文档并没有提供太多信息,因为我是这方面的新手。
我的问题:
对我来说,音频样本N
的结果可以直接从第一个bin到最后一个bin使用,因为输出中没有对称性,这是正确的吗?
鉴于上述缺乏对称性,频率分辨率似乎有所增加,这种解释是否正确?
由于使用rfft
,我从bin索引rfft
到频率k
的映射函数现在是F
这是正确的吗?
相反,从频率F = k*Fs/(2N) for k = 0 ... N-1
到bin索引F
的反向映射函数现在变为k
,这是正确的呢?
我的一般混淆源于k = 2*F*N/Fs for F = 0Hz ... Fs/2-(Fs/2/N)
与rfft
的关系,以及在使用fft
时如何正确完成映射。我相信我的映射会被少量偏移,这在我的应用程序中至关重要。如果可能,请指出错误或就此事提出建议,非常感谢。
答案 0 :(得分:1)
首先为你清理一些事情:
对fftpack documentation的快速参考显示,rfft仅为您提供0..512的输出向量(在您的情况下)。这是因为在计算实值输入的离散傅立叶变换时存在对称性: y [k] = y * [N-k](见Wikipedia page on DFTs)。因此,rfft函数仅计算和存储N / 2 + 1值,因为您可以通过仅使用复共轭来计算另一半(如果您真的想要它用于绘图(比方说))。 fft函数不对输入值进行假设(它们可以同时具有实部和虚部),因此在输出中不能假设对称性,它为您提供具有N个值的完整输出向量。不可否认,大多数应用程序都使用实际输入,因此人们倾向于认为对称性始终存在。请注意,快速傅里叶变换(FFT)是一种(高效)算法,用于计算离散傅里叶变换(DFT),而rfft函数也使用FFT进行计算。
鉴于上述情况,您访问输出向量的索引超出范围,即> 512.你为什么/如何做到这一点的原因取决于你的代码。您应该清楚地区分“逻辑N”(用于映射bin频率,定义DFT等)和“计算N”(输出向量中的实际值数),然后所有问题都应该消失
具体回答你的问题:
没有。有对称性,你需要用它来计算最后的箱子(但它们没有给你额外的信息)。
没有。提高DFT分辨率的唯一方法是增加样本长度。
不,但差不多。对于k = 0..N / 2
对于具有N个bin的输出向量,您将获得从0到(N-1)/ N * Fs的频率。使用rfft,你将得到一个带有N / 2 + 1个bin的输出向量。你做数学,但我得到0..Fs / 2
希望事情现在更加清晰。