虽然我在这个网站上有很多关于音高检测概念的问题......他们都处理这个我不熟悉的神奇FFT 。我正在尝试构建一个需要实现音高检测的 Android 应用程序。我完全不了解用于执行此操作的算法。
不可能那么难吧?毕竟,Android 市场上有大约 80 亿个吉他调音器应用程序。
有人可以帮忙吗?
FFT 并不是实现音高检测或音高跟踪的最佳方式。一个问题是最响亮的频率并不总是基频。另一个原因是,FFT 本身需要大量数据和处理才能获得调整仪器所需的分辨率,因此它的响应速度可能看起来很慢(即延迟)。另一个问题是,FFT 的结果必然是直观的:你得到一个复数数组,你必须知道如何解释它们。
如果你真的想使用 FFT,这里有一种方法:
您如何根据索引计算频率?好吧,假设你有一个大小为 N 的窗口。在你 FFT 之后,你将有 N 个复数。如果您的峰值是第 n 个,并且您的采样率为 44100,那么您的峰值频率将接近 (44100/2)*n/N。为什么近?那么你有一个错误(44100/2)* 1/N。对于 4096 的 bin 大小,这大约是 5.3 Hz——在 A440 上很容易听到。您可以通过 1. 考虑相位来改进这一点(我只描述了如何考虑幅度),2. 使用更大的窗口(这将增加延迟和处理要求,因为 FFT 是 N Log N 算法),或 3. 使用更好的算法,如 YIN http://www.ircam.fr/pcm/cheveign/pss/2002_JASA_YIN.pdf
您可以跳过窗口化步骤,只需将音频分解为您想要分析的多个样本的离散块。这等效于使用方形窗口,虽然有效,但您的结果中可能会出现更多噪音。
顺便说一句:许多调谐器应用程序许可代码来自第三方,例如 z-plane 和 iZotope。
更新:如果您想要 C 源代码和 FFT 方法的完整教程,我已经编写了一个. 该代码可以在 Mac OS X 上编译和运行,并且应该可以很容易地转换到其他平台。它的设计不是最好的,但它的设计目的是易于理解。
快速傅立叶变换将函数从时域更改为频域。因此,不是您从麦克风获得的信号f(t)
在哪里,并且是该信号的时间索引,而是在哪里是 FFT和是频率。一旦你有了,你只需要找到具有最高振幅的那个,这意味着“最响亮”的频率。这将是您正在拾取的声音的主要音高。f
t
g(θ)
g
f
θ
g(θ)
θ
至于实际实现 FFT,如果你在谷歌上搜索“快速傅立叶变换示例代码”,你会得到一堆例子。