我正在尝试根据给定的频率获取正确的FFT bin索引。音频在44.1k Hz处采样,FFT大小为1024。给定信号是真实的(从PyAudio捕获,通过numpy.fromstring解码,通过scipy.signal.hann窗口化),然后我通过scipy.fftpack.rfft执行FFT,并计算结果的分贝,整体而言,magnitude = 20 * scipy.log10(abs(rfft(audio_sample)))

基于thisthis,我最初将FFT bin索引k映射到任何频率F,如下所示:

F = k*Fs/N for k = 0 ... N/2-1其中,Fs是采样率,N是FFT仓大小,在这种情况下为1024。反之为:

k = F*N/Fs for F = 0Hz ... Fs/2-Fs/N

但是,意识到rfft的结果不像fft那样对称,并且以N大小数组提供了结果。我现在对映射和功能有一些疑问。不幸的是,由于我是该领域的新手,文档没有提供太多信息。

我的问题:


对我来说,音频样本上的rfft结果可以直接从第一个bin到最后一个bin使用,因为输出中没有对称性,对吗?
鉴于上述缺乏对称性,频率分辨率似乎有所提高,这种解释正确吗?
由于使用rfft,我从bin索引k到频率F的映射函数现在是F = k*Fs/(2N) for k = 0 ... N-1,这是正确的吗?
相反,从频率F到bin索引k的反向映射函数现在变为k = 2*F*N/Fs for F = 0Hz ... Fs/2-(Fs/2/N),这的正确性如何?


我的一般困惑来自rfftfft的关系,以及在使用rfft时如何正确完成映射。我相信我的映射会被少量抵消,这对我的应用程序至关重要。请指出错误或在可能的情况下提供建议,非常感谢。

最佳答案

首先为您整理几件事:

快速参考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”(用于映射仓频率,定义DFT等)和“计算N”(输出矢量中实际值的数量),然后所有问题都应消除。

具体回答您的问题:


不会。存在对称性,您需要使用它来计算最后一个箱(但是它们没有给您额外的信息)。
不能。增加DFT分辨率的唯一方法是增加样本长度。
不,但是差不多。对于k = 0..N / 2,F = k * Fs / N
对于具有N个bin的输出矢量,您可以获得0到(N-1)/ N * Fs的频率。使用rfft,您将获得具有N / 2 + 1个bin的输出向量。你做数学,但我得到0..Fs / 2


希望现在一切都清楚了。

关于python - Python scipy.fftpack.rfft频点映射,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21517998/

10-11 08:37