使用快速傅里叶变换分析audio

我正尝试在python中创build一个graphics频谱分析仪。

我正在读取一个16位双通道44,100Hz采样率audiostream的1024个字节,并将这两个通道的幅度平均在一起。 所以现在我有一个256签名的短裤arrays。 我现在想要使用像numpy这样的模块在该arrays上进行fft预处理,然后使用结果创buildgraphics频谱分析仪,该分析仪的启动时间仅为32个小节。

我已经阅读了关于快速傅立叶变换和离散傅里叶变换的维基百科文章,但我仍然不清楚结果数组表示什么。 这是使用numpy在我的数组上执行fft之后数组的样子:

[ -3.37260500e+05 +0.00000000e+00j 7.11787022e+05 +1.70667403e+04j 4.10040193e+05 +3.28653370e+05j 9.90933073e+04 +1.60555003e+05j 2.28787050e+05 +3.24141951e+05j 2.09781047e+04 +2.31063376e+05j -2.15941453e+05 +1.63773851e+05j -7.07833051e+04 +1.52467334e+05j -1.37440802e+05 +6.28107674e+04j -7.07536614e+03 +5.55634993e+03j -4.31009964e+04 -1.74891657e+05j 1.39384348e+05 +1.95956947e+04j 1.73613033e+05 +1.16883207e+05j 1.15610357e+05 -2.62619884e+04j -2.05469722e+05 +1.71343186e+05j -1.56779748e+04 +1.51258101e+05j -2.08639913e+05 +6.07372799e+04j -2.90623668e+05 -2.79550838e+05j -1.68112214e+05 +4.47877871e+04j -1.21289916e+03 +1.18397979e+05j -1.55779104e+05 +5.06852464e+04j 1.95309737e+05 +1.93876325e+04j -2.80400414e+05 +6.90079265e+04j 1.25892113e+04 -1.39293422e+05j 3.10709174e+04 -1.35248953e+05j 1.31003438e+05 +1.90799303e+05j... 

我想知道这些数字代表什么,以及如何将这些数字转换为每个32条高度的百分比。 另外,我应该一起平均2个频道?

您显示的arrays是audio信号的傅里叶变换系数。 这些系数可以用来获取audio的频率内容。 FFT是为复数值input函数定义的,所以即使您的input都是实数值,您所得出的系数也是虚数。 为了获得每个频率的功率量,需要计算每个频率的FFT系数的大小。 这不仅是系数的真实组成部分,还需要计算其实部和虚部的平方和的平方根。 也就是说,如果你的系数是a + b * j,那么它的幅度是sqrt(a ^ 2 + b ^ 2)。

一旦你计算了每个FFT系数的大小,你需要计算出每个FFT系数属于哪个audio。 一个N点的FFT会给你在N个等间隔频率的信号的频率内容,从0开始。因为你的采样频率是44100样本/秒。 而你的FFT中的点数是256,你的频率间隔是44100/256 = 172Hz(近似)

数组中的第一个系数是0频率系数。 这基本上是所有频率的平均功率水平。 其余的系数将从172的倍数中的0开始计数,直到达到128.在FFT​​中,您只能测量高达一半采样点的频率。 如果你是一个贪婪的惩罚者,并且需要知道为什么,请阅读奈奎斯特频率和奈奎斯特 – 香农采样定理的这些链接,但基本结果是你的较低频率将在较高频率的桶中被复制或混淆 。 所以频率将从0开始,每个系数增加172 Hz,直到N / 2系数,然后减less172 Hz,直到N – 1系数。

这应该是足够的信息,让你开始。 如果你想要一个比维基百科更加平易近人的FFT介绍,你可以尝试理解数字信号处理:第二版。 。 这对我很有帮助。

这就是这些数字所代表的。 转换为高度的百分比可以通过缩放每个频率分量幅度的所有分量幅度之和来完成。 虽然,这只会给你一个相对频率分布的表示,而不是每个频率的实际功率。 您可以尝试按照频率分量尽可能大的范围进行缩放,但是我不确定那会显示得很好。 find一个可行的缩放因子最快的方法是试验大声和柔和的audio信号,以find正确的设置。

最后,如果要显示整个audio信号的频率内容,则应该将这两个通道平均。 您将立体声audio混合为单声道audio并显示组合的频率。 如果您需要为左右两个频率显示两个单独的显示,则需要分别在每个通道上执行傅立叶变换。

虽然这个线程已经有几年了,但我发现它非常有帮助。 我只是想给我的投入,任何人谁发现这一点,并试图创造类似的东西。

至于把酒吧划分,这不应该作为anttibuild议,根据酒吧的数量平均分配数据。 最有用的是将数据分成八度音阶部分,每个八度音阶是前一个频率的两倍。 (即100hz是50Hz以上的一个八度音阶,这是25hz以上的一个八度音阶)。

根据您想要的条数,将整个范围分为1 / X八度范围。 根据棒上给定的A的中心频率,可以得到棒的上限和下限:

 upper limit = A * 2 ^ ( 1 / 2X ) lower limit = A / 2 ^ ( 1 / 2X ) 

要计算下一个相邻的中心频率,请使用类似的计算:

 next lower = A / 2 ^ ( 1 / X ) next higher = A * 2 ^ ( 1 / X ) 

然后,将适合这些范围的数据进行平均,以获得每个小节的幅度。

例如:我们要分成1/3个八度的范围,我们以1khz的中心频率开始。

 Upper limit = 1000 * 2 ^ ( 1 / ( 2 * 3 ) ) = 1122.5 Lower limit = 1000 / 2 ^ ( 1 / ( 2 * 3 ) ) = 890.9 

给定44100hz和1024个样本(每个数据点之间43hz),我们应该将21到26的值平均。(890.9 / 43 = 20.72-21和1122.5 / 43 = 26.10-26)

(三分之一左右的八度杆会让你在〜40hz和〜20khz之间的30巴左右)。 正如你现在可以看出,随着我们走高,我们将平均更大范围的数字。 低栏通常只包含1个或less量的数据点。 而更高的酒吧可以是平均数百个点。 原因是86hz是43hz以上的八度音阶,而10086hz听起来几乎与10043hz相同。

你所拥有的是一个时间长度为256/44100 = 0.00580499秒的样本。 这意味着您的频率分辨率是1 / 0.00580499 = 172 Hz。 从Python获得的256个值对应于频率,基本上是从86 Hz到255 * 172 + 86 Hz = 43946 Hz。 你得到的数字是复数(因此在每秒结束时的“j”)。

编辑:固定的错误信息

您需要通过计算sqrt(i 2 + j 2 )将复数转换为幅度,其中i和j是实部和虚部,

如果你想有32个小节,你应该尽可能地把连续四个幅度的平均值作为你想要的256/4 = 32个小节。