我想获取音频 PCM 数据并在其中找到峰值。具体来说,我想返回峰值出现的频率和时间。
我对此的理解是,我必须获取 PCM 数据并将其转储到一个数组中,将其设置为实际值,并将复杂部分设置为 0。然后我进行 FFT,然后我得到一个数组。如果数组中的每个数字都是一个幅度值,我如何获得与每个数字相关的频率?另外,我是取实数和复数部分的大小还是只丢弃复数?
最后,如果我想在一首歌曲中找到峰值,我是否只需将一个小窗口设置为 FFT 并将其滑过所有音频?关于该窗口应该有多大的任何建议?
如果 PCM 数据的采样率为 F,则 FFT 中的最高频率分量为 F/2。假设您的 PCM 数据以 44100Hz 采样,那么您的 FFT 值将从 0Hz (DC) 运行到 22050Hz。如果您从 N 个样本开始(N 是 2 的幂),则 FFT 可能会返回 N/2 个值,表示从 0 到 F/2 的所有正频率,或者它可能会返回 N 个值,其中还包括来自 - F/2 到 0。您应该检查 FFT 算法的规范,以找出每个数组项映射到的频率。
要找到峰值,您需要查看 FFT 值的大小。因此,您需要添加每个复数值的平方实部和虚部。
假设您的 N 个 PCM 样本的 FFT 返回代表正频率的 N/2 个复数值。那么 2 个复杂样本之间的距离为 F/2N Hz。对于 F=44100Hz 和 N=1024 个样本,这将是 21.5Hz。这是您的频率分辨率。如果您需要找到较低频率的节拍,则需要扩展 FFT 窗口。
好吧,一个大小为 512 的表示输入波的复数的原始数组,当使用 FFT 处理时,我们将用零替换虚部(根据预期用途),留下实部,然后将数组传递给具有采样率的 FFT : 8192 赫兹。
现在我们有一个 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是频域的意思是它按照频率排列另一边的时域意思是按照我们听音乐的时间从零秒到N秒来排列。
FFT只能在从频率0到频率N按Frequency排列时才能监听。
所以它按升序排列频率,因为它没有从音频中获取所有实际样本(接近无限),就像每纳秒或更短时间到 FFT 一样,幸运的是这不会发生 FFT 从音频中获取样本,每(1/采样率)秒采样一次。这个样本被缓冲(在我们的例子中:512),每个 512 个样本缓冲到 FFT 中,输出是 512 个 FFT 值。
由于 FFT 排列频率,它与时间样本混淆,现在根据它们的频率排列样本。
在常规基础上显示的频率是基本频率,它是采样率除以缓冲区大小,在我们的例子中是 8192/512 = 32。
因此,频率功率每 32 个频率显示一次,最接近频率的功率是根据功率频率接近指数的多少来显示的。
通过使用更高的采样率可以实现高分辨率。
为了显示频率,我们以对应于振幅的升序打印索引。
幅度 = 20log10(输出/参考)
每个索引旁边打印的幅度显示频率的功率并根据分辨率的精度变得更准确。
结论,FFT 产生一个幅度指数,每个幅度表示其对应指数(频率)的功率。
您实际上可能正在寻找一个频谱图,它基本上是一个沿时间轴滑动的小窗口中的数据的 FFT。如果您有实现此功能的软件,它可能会为您节省一些精力。它通常用于分析随时间变化的声学信号,是查看声音的一种非常有用的方法。此外,还有一些技巧,例如,对于 FFT 的窗口数据,频谱图可能会正确,但对您来说更难(虽然不是很难)正确地完成。