我有一个样本保存在DirectX的缓冲区中.这是从乐器演奏和捕捉的音符样本.如何分析样本的频率(如吉他调谐器)?我认为涉及到FFT,但我没有指向HOWTO.
FFT可以帮助您确定频率的位置,但它无法准确地告诉您频率是多少.FFT中的每个点都是频率的"bin",所以如果你的FFT中有一个峰值,你所知道的就是你想要的频率在那个bin或频率范围内.
如果你想要它真的准确,你需要一个具有高分辨率和大量垃圾箱的长FFT(=大量的内存和大量的计算).您还可以使用对数刻度光谱上的二次插值来猜测低分辨率FFT中的真实峰值,这非常有效.
如果计算成本最重要,您可以尝试将信号转换为可以计算过零点的形式,然后计算得越多,测量就越准确.
但是,如果缺少基础,这些都不会起作用.:)
我在这里概述了一些不同的算法,插值FFT通常是最准确的(尽管这只有在基波是最强的谐波时才有效- 否则你需要更聪明才能找到它),零交叉接近秒(尽管这仅适用于每个周期有一个交叉的波形).这些条件都不典型.
请记住,基本频率以上的部分不是钢琴或吉他等许多乐器中的完美谐波.每个部分实际上有点失调,或不和谐.因此,FFT中的较高频率峰值将不会精确地位于基波的整数倍上,并且波形将从一个周期稍微改变到下一个周期,这会抛弃自相关.
为了得到一个非常准确的频率读数,我会说使用自相关来猜测基波,然后使用二次插值找到真正的峰值.(您可以在频域中进行自相关以节省CPU周期.)有很多问题,正确的使用方法实际上取决于您的应用程序.
还有其他算法是基于时间的,而不是基于频率的.自相关是用于音调检测的相对简单的算法.参考:http://cnx.org/content/m11714/latest/
我编写了自相关的c#实现和其他可读的算法.查看http://code.google.com/p/yaalp/.
http://code.google.com/p/yaalp/source/browse/#svn/trunk/csaudio/WaveAudio/WaveAudio 列出文件,PitchDetection.cs就是您想要的文件.
(该项目是GPL;如果您使用该代码,请理解这些术语).
吉他调音器不使用FFT或DFT.通常他们只算零过境点.您可能无法获得基频,因为某些波形的交叉点比其他波形更多,但通常可以获得基频的倍数.这足以获得音符,尽管你可能会关闭一个或多个八度音阶.
在计算过零点之前进行低通滤波通常可以消除过多的过零点.调整低通滤波器需要知道您想要检测的频率范围
确实会涉及FFT(快速傅里叶变换).FFT允许您使用固定频率和不同幅度的简单正弦波之和来近似任何模拟信号.你基本上要做的是取样并将其分解为幅度 - >频率对,然后取出与最高幅度相对应的频率.
希望另一位SO读者可以填补我在理论和代码之间留下的空白!