当前位置:  开发笔记 > 编程语言 > 正文

使用快速傅里叶变换分析音频

如何解决《使用快速傅里叶变换分析音频》经验,为你挑选了3个好方法。

我正在尝试在python中创建一个图形频谱分析器.

我目前正在读取1024字节的16位双通道44,100 Hz采样率音频流,并将两个通道的幅度平均在一起.所以现在我有256个签名短裤阵列.我现在想要使用像numpy这样的模块在该阵列上预先形成一个fft,然后使用结果创建图形频谱分析器,开始时只需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个频道平均在一起吗?



1> A. Levy..:

您显示的阵列是音频信号的傅里叶变换系数.这些系数可用于获得音频的频率内容.FFT是针对复值输入函数定义的,因此即使您的输入都是实数值,您获得的系数也将是虚数.为了获得每个频率的功率量,您需要计算每个频率的FFT系数的幅度.这只是系数的真实分量,你需要计算它的实部和虚的平方之和的平方根.也就是说,如果你的系数是a + b*j,那么它的大小是sqrt(a ^ 2 + b ^ 2).

一旦计算出每个FFT系数的大小,就需要确定每个FFT系数属于哪个音频.N点FFT将以N等间隔频率为您提供信号的频率成分,从0开始.因为您的采样频率为44100样本/秒.并且FFT中的点数为256,您的频率间隔为44100/256 = 172 Hz(大约)

The first coefficient in your array will be the 0 frequency coefficient. That is basically the average power level for all frequencies. The rest of your coefficients will count up from 0 in multiples of 172 Hz until you get to 128. In an FFT, you only can measure frequencies up to half your sample points. Read these links on the Nyquist Frequency and Nyquist-Shannon Sampling Theorem if you are a glutton for punishment and need to know why, but the basic result is that your lower frequencies are going to be replicated or aliased in the higher frequency buckets. So the frequencies will start from 0, increase by 172 Hz for each coefficient up to the N/2 coefficient, then decrease by 172 Hz until the N - 1 coefficient.

这应该足以让您入门.如果你想要比维基百科上给出的更加平易近人的FFT介绍,你可以尝试理解数字信号处理:第二版..这对我很有帮助.

这就是那些数字所代表的.可以通过将每个频率分量幅度缩放所有分量幅度的总和来转换为高度的百分比.虽然,这只会给你一个相对频率分布的表示,而不是每个频率的实际功率.您可以尝试按频率分量的最大幅度进行缩放,但我不确定它会显示得非常好.找到可行的缩放因子的最快方法是试验大声和软音频信号以找到正确的设置.

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



2> 小智..:

虽然这个帖子已有多年历史,但我发现它非常有用.我只是想把我的意见交给那些发现这个并试图创造类似东西的人.

至于分为条形,这不应该像antti所建议的那样,通过基于条形数均等地划分数据.最有用的是将数据分成八度音阶,每个八度音程是前一个频率的两倍.(即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)

(1/3倍频程可以让你在~40hz和~20khz之间约30巴).正如你现在可以弄清楚的那样,随着我们走得更高,我们将平均更大的数字范围.低条通常仅包括1个或少量数据点.而较高的条形可以是数百个点的平均值.原因是86hz是一个高于43hz的八度音阶......而10086hz的声音几乎与10043hz相同.



3> Antti Huima..:

你所拥有的是一个样本,其时间长度为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个小节你想要的.


请注意,如果c是复数,则sqrt(c.real**2 + c.imag**2)== abs(c)
推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有