Python scipy.fftpack.rfft频率bin映射
我试图根据给定的频率得到正确的FFT bin索引。音频采样频率为Python scipy.fftpack.rfft频率bin映射,python,numpy,scipy,signal-processing,fft,Python,Numpy,Scipy,Signal Processing,Fft,我试图根据给定的频率得到正确的FFT bin索引。音频采样频率为44.1k Hz,FFT大小为1024。假设信号是真实的(从PyAudio捕获,通过numpy.fromstring解码,通过scipy.signal.hann加窗),然后通过scipy.fftpack.rfft执行FFT,并计算结果的分贝,总的来说,幅值=20*scipy.log10(abs(rfft(音频样本)) 基于和,我最初将FFT bin索引k映射到任何频率F,如下所示: F=k*Fs/N表示k=0。。。N/2-1其中Fs
44.1k Hz
,FFT大小为1024
。假设信号是真实的(从PyAudio捕获,通过numpy.fromstring
解码,通过scipy.signal.hann
加窗),然后通过scipy.fftpack.rfft
执行FFT,并计算结果的分贝,总的来说,幅值=20*scipy.log10(abs(rfft(音频样本))
基于和,我最初将FFT bin索引k
映射到任何频率F
,如下所示:
F=k*Fs/N表示k=0。。。N/2-1
其中Fs
是采样率,N
是FFT单元大小,在这种情况下,1024
。反之亦然:
k=F*N/Fs表示F=0Hz。。。Fs/2-Fs/N
然而,意识到rfft
的结果不像fft
那样是对称的,并且在N
大小的数组中提供结果。我现在有一些关于映射和函数的问题。不幸的是,文档并没有提供太多的信息,因为我是这方面的新手
我的问题是:
rfft
结果可以直接从第一个存储箱使用到最后一个存储箱,因为输出中没有对称性,对吗rfft
,我从bin索引k
到频率F
的映射函数现在是F=k*Fs/(2N)表示k=0。。。N-1
是否正确F
到bin索引k
的反向映射函数现在变为k=2*F*N/Fs,F=0Hz。。。Fs/2-(Fs/2/N)
,这个的正确性如何我的一般困惑源于
rfft
如何与fft
相关,以及如何在使用rfft
时正确进行映射。我相信我的映射会被少量偏移,这在我的应用程序中是至关重要的。如果可能,请指出错误或就此提出建议,非常感谢。首先要为您澄清一些事情:
快速参考显示rfft仅提供0..512的输出向量(在您的示例中)。其原因正是因为计算实值输入的离散傅里叶变换时存在对称性:
y[k]=y*[N-k](参见)。因此,rfft函数仅计算和存储N/2+1值,因为您可以通过只获取复数共轭来计算另一半值(如果您真的希望它用于打印(比如))。fft函数对输入值不作任何假设(它们可以有实部和虚部),因此在输出中不能假设对称性,它提供了一个具有N个值的完整输出向量。诚然,大多数应用程序使用真实输入,因此人们倾向于假设对称性总是存在的。请注意,快速傅里叶变换(FFT)是计算离散傅里叶变换(DFT)的有效算法,rfft函数也使用FFT进行计算
鉴于上述情况,用于访问输出向量的索引超出范围,即>512。这样做的原因/方式取决于您的代码。您应该清楚地区分“逻辑N”(用于映射bin频率、定义DFT等)和“计算N”(输出向量中的实际值数),然后所有问题都应该消失
具体回答您的问题:
希望事情现在变得更清楚。您是否确实尝试过在长度为N的向量上使用
scipy.fftpack.rfft
?你会发现它确实给你一个长度N的输出。您可能正在考虑np.fft.rfft
,它将为您提供长度为N//2+1
的输出。我没有使用fftpack,也没有使用Python,但我引用的文档确实是用于fftpack的,并且不影响理论的解释,我认为这是造成混淆的原因。正如我所暗示的,我不知道N个元素可以访问的原因(可能是N个输入值被复制,转换运行到位),但我不相信N/2以上的值,因为它与文档以及rfft函数的基本要点相矛盾。再次查看文档,以获得均匀长度的输入,输出是[y(0),Re(y(1)),Im(y(1)),…,Re(y(n/2))]
,即它似乎包含交错的实部和虚部。进一步,它澄清了“如果未指定n(默认值),则n=x.shape[轴]
”。是对这个输出的解释混淆了OP,坦率地说,我也是。好的,我理解你的观点。我引用的(逻辑)值是复数值,而不是数组的实际元素(我假设它存储为复数数据类型)。假设输出将(n/2+1)复数值存储为向量中的n个独立元素,而不是复数数据类型,则应仅使用适当的索引来计算各个存储单元的大小。访问输出的机制/语法我无能为力。正如我所说,区分逻辑和计算