假人的频率/音高检测

bra*_*hy1 7 java audio android

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

这可不是那么难吗?毕竟,Android市场上有大约80亿个吉他调谐器应用程序.

有人可以帮忙吗?

Bjo*_*che 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以获得更一致的结果.

你如何计算指数的频率?好吧,假设你有一个大小为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

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

顺便说一句:许多调谐器应用许可代码形成第三方,如z-plane和iZotope.

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

  • 事实上,您所要求的信息通常在大学水平课程的一两个学期中涵盖,并非所有细节都可以在这里涵盖。 (2认同)

Jon*_*Lin 5

快速傅里叶变换将函数从时域更改为频域。因此,您得到的不是f(t)f麦克风获得的信号 和t是该信号的时间索引,g(\xce\xb8)而是gFFTf\xce\xb8频率。一旦有了g(\xce\xb8),您只需找到\xce\xb8振幅最高的那个,即“最响亮”的频率。这将是您拾取的声音的主要音高。

\n\n

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

\n

  • 这个[示例](http://stackoverflow.com/a/2065693/230513)可能对测试有用。 (2认同)
  • @brainmurphy1取决于FFT函数,但通常你会遍历新数组并寻找最大值,索引是频率。 (2认同)