关于 Stackoverflow 以及 FFT 和音高检测的讨论已经不计其数了。
人们普遍认为,FFT 虽然速度很快,但对于许多应用程序来说并不是很准确,但通常不会解释原因。
我想解释一下我对为什么会这样的理解,希望比我聪明的人可以纠正我并填补我无法填补的空白。
FFT 将输入数据从时域转换到频域。
最初,我们从一系列数据开始,如果我们要在图表上绘制这些数据,则 Y 轴为给定时间点的声音幅度,X 轴为时间。这是在时域中。
FFT 将这些时间点的幅度值转换为不同频率的幅度。
FFT 输出的数据数量与输入的数据数量相同
如果我们输入 10 个时间点(10 个样本)的幅度,FFT 将输出这些样本中 10 个不同频率的幅度(在乘以虚数和实数的 sqrt 之后)。
哪些频率由以下因素决定:
我们将 FFT 的输出称为bin,每个 bin 的宽度通过将采样率除以 FFT 中的样本数来计算:
bin width = Sample Rate(Hz)/FFT Length (n samples)
使用一些实际值,可能是:
bin_width = 44100 / 512 = 86.132
因此,我们的 FFT 有 512 个 bin(请记住,输入和输出的数据数量相同),每个 bin 的频率跨度为 86.132 Hz。
因此,对于给定的 bin,我们可以通过以下方式计算它所代表的频率:
Bin Freq (Hz) = Bin number (n) * bin width (Hz)
使用上面的值,FFT 输出中的第 3 个 bin 将表示 258.398Hz 处的幅度:
Bin Freq (Hz) = 3 * 86.132 = 258.396Hz
这意味着在给定采样率和缓冲区大小的情况下,FFT 输出的准确度不能超过 ± 86.132Hz。
如果您需要更高的精度(例如 1Hz),则必须降低采样率或增加缓冲区大小(或两者兼而有之)。
desired bin width: 1Hz = 44100 / 44100 # A buffer size of 44100 would work in this instance
随着缓冲区大小越来越接近采样率,延迟问题变得更加严重。
FFT Results per second = Sample Rate / Buffer Size = 44100/44100 = 1 FFT per second
(每秒 44100 个样本,填充 44100 个样本缓冲区 = 每秒 1 个完整缓冲区)。
我意识到 FFT 不仅仅是计算基频(幅度最高的 bin),但到目前为止我对音高检测中的 FFT 的理解是否正确?
有什么方法可以在不牺牲延迟的情况下提高 FFT 的准确性?