我在这里看到了各种 FFT 问题,但我对部分实现感到困惑。我不想实时执行 FFT,而是想离线执行。可以说我有原始数据float[] audio
。采样率为 44100,因此audio[0] to audio[44099]
将包含 1 秒的音频。如果我的 FFT 函数处理窗口(例如 Hanning),我是否只需将整个audio
缓冲区一次性放入函数中?或者,我是否必须将音频切成 4096(我的窗口大小)的块,然后将其输入到 FFT 中,然后在顶部执行窗口功能?
3 回答
您可能需要将输入数据复制到单独的缓冲区并以正确的格式获取它,例如,如果您的 FFT 是就地的,或者它需要交错的复杂数据(实数/虚数)。但是,如果您的 FFT 例程可以采用纯真实输入并且不是就地(即非破坏性),那么您可能只能够传递指向原始样本数据的指针以及适当的大小参数。
通常对于 1 秒的音频,例如语音或音乐,您会选择一个 FFT 大小,该大小对应于一个合理固定的音频块,例如 10 毫秒或 20 毫秒。因此,在 44.1 kHz 时,您的 FFT 大小可能是 512 或 1024。然后,您将通过缓冲区前进并在每个起点执行新的 FFT 来生成连续频谱。请注意,通常的做法是重叠这些连续的缓冲区,通常为 50%。因此,如果 N = 1024,您的第一个 FFT 将用于样本 0..1023,您的第二个将用于样本 512..1535,然后是 1024..2047,等等。
是对整个数据集计算一个 FFT(在 OP 的情况下,44100 个样本代表 1 秒的数据),还是对整个数据集的较小子集进行一系列 FFT,取决于数据,以及 FFT 的预期目的。
如果整个数据集上的数据在光谱上是相对静态的,那么对整个数据集进行一次 FFT 可能就足够了。
然而,如果数据在数据集上是频谱动态的,那么在数据的小子集上的多个滑动 FFT 将创建更准确的数据时频表示。
下图显示了弹奏 A4 音符的原声吉他的功率谱。音频信号以 44.1 KHz 采样,数据集包含 131072 个样本,几乎是 3 秒的数据。该数据集预乘以 Hann 窗函数。
下图显示了从原声吉他 A4 音符的完整数据集中获取的 16384 个样本(0 到 16383)子集的功率谱。这个子集也预乘了一个 Hann 窗口函数。
请注意子集的光谱能量分布与完整数据集的光谱能量分布有何显着差异。
如果我们要从完整数据集中提取子集,使用滑动的 16384 样本帧,并计算每个帧的功率谱,我们将创建完整数据集的准确时频图。
参考:
真实音频信号数据、Hann 窗函数、绘图、FFT 和频谱分析在这里完成:
您选择的块大小或窗口长度控制 FFT 结果的频率分辨率和时间分辨率。你必须确定你想要什么或做出什么权衡。
更长的窗口给你更好的频率分辨率,但更差的时间分辨率。较短的窗口,反之亦然。每个 FFT 结果 bin 将包含大约 1 到 2 倍的采样率除以 FFT 长度的频率带宽,具体取决于窗口形状(矩形、von Hann 等),而不仅仅是一个单一频率。如果您的整个数据块是固定的(频率内容不变),那么您可能不需要任何时间分辨率,并且可以在 1 秒的数据中获得 1 到 2 Hz 的频率“分辨率”。平均多个短 FFT 窗口也可能有助于减少频谱估计的方差。