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



我知道有很多关于从FFT中查找音高的主题,并且我已经对从时域->频域转换数据样本的整个过程有了很好的理解,但仍然有一些领域(可能更高级(我有点坚持。

我将逐步完成我当前的流程,所以希望有人可以帮助我了解我哪里出了问题!

在我开始之前,我在这里使用的示例是我在 Logic 中创建的 Wav 文件,它只是 A 音阶中的钢琴预设,从 A4 键开始,它只是每半小节向上移动音阶(A4、B4、C#5、D5...(,总共 4 秒,速度为 120 bpm。如果有帮助,这里有一个指向 wav 的链接:[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.61084.0

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

这就是我感到困惑的地方!我已经绘制了时域图,并通过查看周期并知道 A4 的周期来查看音高是如何发现为 A4 的,但我试图了解如何通过 FFT 得出相同的结论。任何帮助/地方可以指点我将不胜感激!

A4 通常为 440Hz。 我的猜测是,您已经检测到 440Hz 的 3 次谐波并出现一个偏差错误。

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

第 2 步:

对这两个渠道执行分析可能没有任何好处。通过将两者相加转换为单声道信号

第 3 步:

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

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

第 4 步:

您正在找到具有最高能量的FFT箱的中心频率。由于音阶是以对数为底-2,因此对于较高频率,这是合理的近似值,但在低频下,即使您使用大型FFT(在这种情况下,您会消耗大量CPU周期并失去时间分辨率(,也无法完成这项工作。

为了做得更好,您可以使用短时傅里叶变换并利用 i( 来自FFT数据连续窗口的相位(Phi( ii( 并且 F = dPhi/dt

由此您可以获得非常准确的结果。

相关内容

  • 没有找到相关文章

最新更新