我知道有很多关于从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得出相同的结论。任何帮助/指向我的地方将不胜感激!
答案 0 :(得分:1)
以下是您正在使用的步骤的一些观察结果:
第2步:
对两个频道进行分析可能无法获得任何好处。通过将两者相加来转换为单声道信号
第3步:
这对于复音信号不可靠(或者就此而言,是现实世界的单声道乐器信号),此外,对于单声道信号,有时两个相邻音箱的功率具有相同的值 - 这是因为每个bin是一个带通滤波器,其频率响应具有指数尾部。准确地位于两个频带中间的信号对两者都有相同的贡献,并且在实际信号的情况下,尽管频率占主导频率,但频带中的频带都不具有最高能量:记住谐波将存在并且可能很大。另外请注意,对于一些真实世界的乐器声音,从根本上可能甚至没有部分乐器的最高能量。
FFT的相位分量提供了大量信号跨越频带的线索。
第4步:
您正在寻找具有最高能量的FFT箱的中心频率。由于音阶是对数基数-2,这对于更高的频率来说是合理的近似,但是在低频率下,即使你使用大的FFT也不会起作用(在这种情况下,你会消耗大量的CPU周期并输掉时间分辨率)。
为了做得更好,你可以使用Short-time Fourier Transform并使用 i)来自FFT数据的连续窗口的相位(Phi) ii)并且F = dPhi / dt
通过这种方式,您可以获得非常准确的结果。