窗口大小、采样率如何影响 FFT 基音估计?

信息处理 fft
2022-01-05 19:25:12

我正在尝试创建一个音高检测程序,该程序提取从 FFT ( fftpack) 获得的功率谱中的峰值频率。我正在使用Quinn 的 First Estimator从频谱中提取峰值频率,以在 bin 编号之间进行插值。该方案似乎在某些条件下运行良好。例如,使用窗口大小为 1024,采样率为 16000 的矩形窗口函数,我的算法正确识别出纯 A440 音调的频率为 440.06,第二部分频率为 880.1。但是,在其他条件下,它会产生不准确的结果。如果我更改采样率(例如到 8000)或窗口大小(例如到 2048),它仍然正确地将第一个分音识别为 440,但第二个分音在 892 左右。对于像那些不和谐的音调,问题变得更糟由吉他或钢琴产生。

我的一般问题是:采样率、窗口大小和窗口函数以什么方式影响 FFT 峰值的频率估计?我的假设是简单地增加频谱的分辨率会增加峰值频率估计的准确性,但这显然不是我的经验(零填充也无济于事)。我还假设窗口函数的选择不会产生太大影响,因为频谱泄漏不应该改变峰值位置(尽管现在我考虑了一下,如果相邻的 bin 的幅度,频谱泄漏可能会影响插值频率估计峰是通过其他峰的泄漏人为增加的……)。

有什么想法吗?

3个回答
  1. 使用高斯窗口 - 高斯的傅里叶变换是高斯的
  2. 对频谱进行对数缩放以强调峰值并将高斯峰值变为抛物线峰值
  3. 使用抛物线插值来找到真正的峰值。

请注意,如 §D.1 中所述,高斯窗口变换幅度恰好是 dB 标度上的抛物线。结果,二次谱峰值插值在高斯窗口下是精确的。当然,在实践中,我们必须以某种方式去除高斯窗的无限长尾,但这不会导致抛物线有太大的偏差,如图 3.30 所示。

https://ccrma.stanford.edu/~jos/sasp/Quadratic_Interpolation_Spectral_Peaks.html

在此处输入图像描述

我以这种方式估计 1000.000004 Hz 的 1000 Hz 波形:https ://gist.github.com/255291#file_parabolic.py

如果您遇到问题,请绘制频谱图并用您的眼睛看看它为什么不起作用。

首先,峰值频率估计和基音估计是两个不同的东西。音高是一种心理声学现象。即使基本频率完全缺失,或者与大多数其他峰值相比相对较弱,人们也可以听到音调,例如某些乐器产生的低音。

其次,在 FFT 上不使用窗口相当于使用矩形窗口,它将您的频谱与 Sinc 函数进行卷积。Sinc 函数有很多远离峰值的驼峰,这些驼峰将显示在 FFT 长度中不完全周期性的所有频率(也称为“频谱泄漏”)。来自一个强频率的所有这些能量泄漏都会干扰其他频率峰值的位置估计。因此,更合适的窗函数(Hamming 或 von Hann)可能有助于减少峰之间的这种干扰。

较长的 FFT 将减少 bin 中心之间的 delta 频率,这应该会增加插值,从而增加固定频谱的频率估计精度。但是,如果 FFT 太长以至于频谱在 FFT 窗口内发生变化,那么所有这些变化的频率将在更长的 FFT 中一起模糊。

您肯定需要一个合适的窗口函数 - 频谱泄漏的影响会根据音调周期和 FFT 窗口长度的关系而显着变化 - 如果您在 FFT 窗口的最后一个样本和第一个样本之间获得很大的瞬态,那么这将产生非常讨厌的光谱的拖尾,而如果你很幸运并且这种不连续性很小,那么得到的光谱会更干净。这可能就是您在更改任何参数(例如 FFT 大小)时看到不一致的原因。使用合适的窗函数,随着音高的变化,您将获得一致的频谱。