Matlab - 更好地理解FFT并找到Pitch

时间:2014-11-30 00:14:11

标签: matlab audio fft wav pitch-detection

我知道有很多关于从FFT中寻找音高的主题,并且我从转换时域数据样本中获得了对整个过程的正确理解 - >频域,但仍有一些领域(可能更先进),我有点坚持。

我将逐步完成目前的流程,希望有人能帮助我了解我哪里出错!

在开始之前,我在这里使用的示例是我在Logic中创建的Wav文件,它只是 A比例中的钢琴预设,从键A4开始,它只是向上移动比例(A4,B4,C#5,D5 ......)每半个柱,总共 4秒 120 bpm 。如果有帮助,这里是wav的链接:[a https://www.dropbox.com/s/zq1u9aylh5cwlmm/PianoA4_120.wav?dl=0]

第1步: 我解析出元数据和实际的样本数据。 元数据:      channels => 2, sample_rate => 44100, byte_rate => 176400, bits_per_sample => 16, data_chunk_size => 705600, data => ...

第2步: 由于有2个频道,我有一个左和右。右边的数组充满了相应的样本数据,然后将它们中的每一个放在FFT上。每个FFT的结果给出了给定频率的幅度和相位

第3步: 我现在需要找到每个FFT的最大幅度。我这样做是通过找到真实/复杂结果的所有大小然后找到最大值。我正在使用Matlab帮助我,所以我运行max(abs(fft(data)))。我从找到每个FFT的最大值得到的值 1275.6 1084.0

第4步: 从各自的FFT中找出这些最大值的索引,然后在映射的频域值的索引处找到频率。这给了我 1177.0 Hz 1177.5 Hz

这是我困惑的地方!我已经绘制了时域图,并通过查看期间并知道A4的周期是什么,看到了如何发现音高 A4 ,但我正在努力了解我的能力如何通过FFT得出相同的结论。任何帮助/指向我的地方将不胜感激!

1 个答案:

答案 0 :(得分:1)

A4通常是440Hz。我的猜测是你已经检测到440Hz的三次谐波,并且有一个一个一个错误。

以下是您正在使用的步骤的一些观察结果:

第2步:

对两个频道进行分析可能无法获得任何好处。通过将两者相加来转换为单声道信号

第3步:

这对于复音信号不可靠(或者就此而言,是现实世界的单声道乐器信号),此外,对于单声道信号,有时两个相邻音箱的功率具有相同的值 - 这是因为每个bin是一个带通滤波器,其频率响应具有指数尾部。准确地位于两个频带中间的信号对两者都有相同的贡献,并且在实际信号的情况下,尽管频率占主导频率,但频带中的频带都不具有最高能量:记住谐波将存在并且可能很大。另外请注意,对于一些真实世界的乐器声音,从根本上可能甚至没有部分乐器的最高能量。

FFT的相位分量提供了大量信号跨越频带的线索。

第4步:

您正在寻找具有最高能量的FFT箱的中心频率。由于音阶是对数基数-2,这对于更高的频率来说是合理的近似,但是在低频率下,即使你使用大的FFT也不会起作用(在这种情况下,你会消耗大量的CPU周期并输掉时间分辨率)。

为了做得更好,你可以使用Short-time Fourier Transform并使用  i)来自FFT数据的连续窗口的相位(Phi)  ii)并且F = dPhi / dt

通过这种方式,您可以获得非常准确的结果。