假人的频率/音高检测

时间:2012-07-19 02:19:24

标签: java android audio

虽然我在这个网站上有很多关于音高检测概念的问题......但它们都处理了我不熟悉的神奇的 FFT 。我正在尝试构建一个需要实现音调检测的Android应用程序。我完全不了解用于执行此操作的算法。

难道不能吗?毕竟,Android市场上有大约80亿个吉他调谐器应用程序。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:13)

FFT实际上并不是实现音高检测或音高跟踪的最佳方式。一个问题是最响亮的频率并不总是基频。另一个原因是FFT本身需要相当大量的数据和处理才能获得调谐仪器所需的分辨率,因此响应速度似乎很慢(即延迟)。另一个问题是FFT的结果必然是直观的:你得到一系列复数,你必须知道如何解释它们。

如果你真的想使用FFT,这里有一种方法:

  1. 低通信号。这有助于防止噪声和高次谐波产生虚假结果。可以想象,您可以跳过此步骤,而是将结果加权到FFT的较低值。对于某些具有强基频的仪器,这可能没有必要。
  2. 聆听您的信号。 Windows应该至少4096。更大是更好的一点,因为它为您提供更好的频率分辨率。如果你太大,最终会增加你的计算时间和延迟。 hann功能是您窗口的不错选择。 http://en.wikipedia.org/wiki/Hann_function
  3. 尽可能频繁地对窗口信号进行FFT。即使重叠的窗户也很好。
  4. FFT的结果是复数。使用sqrt(real ^ 2 + imag ^ 2)查找每个复数的大小。具有最大幅度的FFT阵列中的索引是具有峰值频率的索引。
  5. 您可能希望平均多个FFT以获得更一致的结果。
  6. 如何计算指数的频率?好吧,假设你有一个大小为N的窗口。在FFT之后,你将有N个复数。如果您的峰值是第n个,并且您的采样率是44100,那么您的峰值频率将接近(44100/2)* n / N.为什么附近?你有错误(44100/2)* 1 / N.对于4096的箱子,这大约是5.3Hz - 在A440处容易听到。您可以通过以下方面进行改进:考虑到相位(我只描述了如何考虑幅度),2。使用更大的窗口(这将增加延迟和处理要求,因为FFT是N Log N算法),或3.使用更好的算法,如YIN http://www.ircam.fr/pcm/cheveign/pss/2002_JASA_YIN.pdf

    您可以跳过窗口步骤,只需将音频分解为您要分析的多个样本的离散块。这相当于使用方形窗口,但是在结果中可能会产生更多噪音。

    BTW:许多调谐器应用程序许可代码形成第三方,例如z-plane和iZotope。

    更新:如果你想要C源代码和FFT方法的完整教程,我written one。该代码在Mac OS X上编译和运行,并且应该可以很容易地转换为其他平台。它的设计并不是最好的,但它的设计很容易理解。

答案 1 :(得分:4)

快速傅立叶变换将函数从时域更改为频域。因此,f(t)而不是f,而t是从麦克风获取的信号而g(θ)是该信号的时间索引,而g位于f } {是θ的FFT和g(θ)是频率。获得θ之后,您只需找到幅度最高的{{1}},即“最响”的频率。这将是你正在接受的声音的主要音调。

至于实际实现FFT,如果你谷歌“快速傅里叶变换示例代码”,你会得到一堆例子。