向我解释FFT算法

15

我希望能够获取音频PCM数据并在其中找到峰值。具体来说,我想返回发生峰值的频率和时间。

我的理解是,我需要将PCM数据转储到一个数组中,并将其设置为实数值,复数部分设置为0。接着进行快速傅里叶变换(FFT),然后获得一个数组。如果数组中的每个数字都是幅度值,那么如何获得与之相关联的频率?此外,我应该取实部和虚部的幅值还是只保留幅值?

最后,如果我想要在一首单曲中找到峰值,我只需将一个小窗口设置为FFT,并将其滑动到所有音频上吗?关于窗口大小,您有什么建议吗?


1
在音频PCM数据中寻找峰值并不等同于在FFT中寻找峰值。你到底想做什么? - endolith
3个回答

15

如果您的PCM数据采样率为F,则FFT中的最高频率分量为F/2。假设您的PCM数据以44100Hz进行采样,则FFT值将从0Hz(直流分量)到22050Hz运行。如果您从N个样本开始(其中N是2的幂次方),则FFT可能返回N/2个值,表示从0到F/2的所有正频率,或者它可能返回N个值,也包括从-F/2到0的负频率。您应该检查FFT算法的规范,以找出每个数组项映射到哪个频率。

要查找峰值,您需要查看FFT值的幅度。因此,您需要将每个复杂值的实部和虚部的平方相加。

假设您的N个PCM样本的FFT返回N/2个表示正频率的复杂值。然后,两个复杂样本之间的距离为F/2N Hz。在F=44100Hz和N=1024个样本的情况下,这将是21.5Hz。这就是您的频率分辨率。如果您需要查找更低频率的节拍,则需要扩展FFT窗口。


4

首先,我们有一个大小为512的复数原始数组,表示输入波形。当使用FFT处理时,我们将用零替换虚部(根据预期用途),保留实部,然后将数组传递给采样率为8192 Hz的FFT。

现在,我们有一个512个FFT实值的数组,每个值都是无理数,每个无理数表示几个有用的值。

要获得基频,我们必须将采样率除以缓冲区大小:

8192/512 = 32;

32是FFT值的分辨率,意味着我们将了解靠近32倍数的高幅度频率的数字。

例如,如果我们有一个频率为3、48、23、128的波形

幅度:10 5 12 8 dB(参考值=1)

经过FFT后,我们得到:

频率:0 32 64 128

幅度:9 8 2 8

FFT是频域,意味着它按照频率排列

另一方面,时域意味着按时间排列,我们从第0秒到第N秒听音乐。

FFT只能在按频率排序时进行监听,从频率0到频率N。

因此,它按升序排列频率,因为它没有获取音频的所有实际样本(接近无限),例如每纳秒及更短的时间。FFT从音频中获取样本,每(1/采样率)秒获取一个样本。这些样本被缓冲(在我们的情况下:512),每512个样本被缓冲到FFT中,输出是512个FFT值。

由于FFT按频率排列,所以它会影响时间样本,现在样本按其频率排列。

显示在常规基础上的频率是基频,即采样率除以缓冲区大小,在我们的情况下为8192/512 = 32。

因此,每32个频率就显示一次频率功率,最近频率的功率根据其靠近索引的程度显示。

可以通过使用更高的采样率来实现高分辨率。

为了显示频率,我们按升序打印与幅度对应的索引。

幅度=20log10(输出/参考)

每个索引旁边打印的幅度显示其相应索引(频率)的功率,并根据分辨率的精度变得更加准确。

总之,FFT产生振幅指数,每个振幅表示其相应指数(频率)的功率。


3
你可能实际上正在寻找一个频谱图,它基本上是在时间轴上滑动的小窗口中数据的FFT。如果你有实现这个的软件,它可能会为你节省一些精力。它通常用于分析时间变化的声学信号,并且是观察声音的非常有用的方法。此外,还有一些技巧,例如对于FFT的数据进行窗口处理,频谱图可能会得到正确的结果,但是对于你来说可能会更难(尽管不是非常难)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接