我可以使用FFT识别钢琴上的音符吗?


13

我想创建一个可以识别一些音符的工具(我知道这是在重新发明轮子)。因此,我将在钢琴上弹奏中级C,D和E,它应该能够对这些音符进行分类。我认为应采用以下方式:

  1. 记录我演奏音符的样本
  2. 使用快速傅立叶变换将信号转换到频域
  3. 找到最存在的频率(基本上是频域数据的argmax)
  4. 假设频率来自演奏的音符,并使用该音符对音符进行分类

我还没有尝试过任何方法,因为我不想走错路。那么,从理论上讲,这会起作用吗?


如果您可以在标题中更具体一些,那就太好了。我试图包括一些有关钢琴音高识别的信息,但是我的(非母语)英语今天显然使我失望了。

1
@pipe ok,我更改了它
michaelsnowden '16

1
您演奏音符的“样本”应该已经是振幅和时间的波形。本质上,点2是多余的。对于一个相对简单的实现,您的上述步骤就可以了。
user2943160'8

@ user2943160我添加了它是明确的。声音可以以多种格式存储,并且随着时间的流逝,通常需要进行一些调整才能使其达到理想的振幅。
michaelsnowden '16

@michaelsnowden:您正在使用的术语“振幅”错误:正弦函数的振幅 是。它是信号的最大值(电压,位移等),并且是一个常数(或相对于频率缓慢变化)。您的意思只是信号。否则,我认为“随时间变化的幅度”是指信号的包络线,但据我所知并不是。Ý y(t)=Asin(ωt)Ay(t)
凝结

Answers:


23

这个概念很好,但是您会发现它在实践中并不是那么简单。

音调不仅是主要的音调,因此还有问题1。

FFT频率仓不能同时击中音阶的所有(甚至多个)音调。

我建议您玩一个包含FFT分析器和音频发生器的音频程序(例如Audacity),以便在尝试使用FFT实施特定任务之前先了解它可以(或不能做)什么。

如果您只需要检测一些特定的音调,您可能会发现Goertzel算法更加简便快捷。

音高检测很复杂,并且该领域仍在进行研究。音调检测非常简单,但可能无法满足您的需求。


如果我们假设样本是特定工具的,那么这个问题可能会更容易解决,对吧?
mkeith '16

这看起来真的很好。一个后续问题是:可以使用Goertzel算法检测同时播放的两个音符吗?
michaelsnowden '16

它可以用来检测同时发出的声音。这是否足以检测同时出现的音符是另一个问题,而我仍在努力。我有一个基于Goertzel的吉他音符检测器,多年来我一直在反复试验。
JRE

2
@mkeith:有点。您可以测试这些音符,然后查看检测主要音调是否足以满足特定乐器(也许只是感兴趣的音符)的要求。据我所知,目前尚没有通用的解决方案来检测所有乐器的所有音符。
JRE

3

我会说使用信号的多峰观察窗口会更好。音频信号的小波分解过程中有一些东西,使您可以识别音符内的多个泛音。是的,实际上是Wavelets,我想说的是要走的路。

这是什么是小波的非常概括的细分,但可以将它们视为像STFT一样通过信号的多分辨率窗口。因此,您可以识别出现在信号内不同时间位置的不同正弦波。这一点也很重要,因为您演奏的音符不是固定信号,它会演奏,然后随时间衰减。我不是音乐家,但是我相信在音符衰减期间,音调优势会发生变化。

当然,在小波分解之后,您将需要实现识别音符和外围音调的算法。

我认为小波确实可以解决人们在音调识别方面一直在谈论的问题。

如果您想了解小波的工作原理,这是惠普发布的精彩白皮书:) http://www.hpl.hp.com/hpjournal/94dec/dec94a6.pdfWavelet简介

为了实现,MATLAB有一个小波工具,我敢肯定还有很多其他软件包可用于R等平台。


1

我想您可能想到的是在钢琴音域的中间(例如200至500 Hz之间)演奏的音符,但是即使在该范围内,单个音符也会有许多泛音,这些泛音不是基频的精确倍数,而且在每个音符的开头或结尾处都有大量的宽带噪声。

对于音符范围较低端的响亮音符,您会发现很少有声能(小于1%)实际上位于音符的基本音高中。

另一个问题是,对FFT的天真的解释假设您要检测的信号具有恒定的幅度。这不适用于振幅实际上跟随几个叠加的指数衰减的钢琴音符-衰减的初始部分具有相对较短的时间常数,而后期具有较长的时间常数。

您可能会更好地研究短时傅立叶变换方法,例如Gabor变换或基于小波的方法。

请注意,由于连续音符的基本音高每个音符增加大约6%,因此识别音频中谐波的频率不一定需要非常高的精度。正确地识别音符与确定音符是否与乐谱准确一致并不是一个完全相同的问题,在这种情况下,可能需要测量频率以使其精度高于0.1%。


0

是的,这就是FFT的全部意义!为您提供所馈送数据的频谱。如前所述,最困难的部分是实现细节。

根据您要执行的操作,确切地更改答案。

如果您只是想分析自己的音乐,那么已经有软件可以做到这一点。您可以查看显示响应的EQ(基本上是FFT),也可以查看显示音高的“音乐EQ”。您可以将音频输入到Midi VST,将您演奏的内容转换为正确的Midi音符。如果您的键盘是midi,只需跳过VST,直接录制midi。

如果您想教自己FFT及其与音乐的关系,那么最好使用Matlab之类的东西,您可以在其中计算任何数据的FFT。它具有录制和回放以及读取wav文件等的功能。这些都是真正易于使用的。如果您知道语法,则可以绘制音频图并快速进行各种分析。

如果您想构建一个设备来做这样的事情,那就太复杂了。您将需要一个uC / dsp / fpga / etc进行计算。大多数流行的设备已经带有FFT代码,因此您不必自己进行编码(也很复杂)。

您将需要构建电路以及所有这些。这并不困难,但是取决于您的经验/知识,可能要花费一些时间,并且学习曲线很陡。这也取决于最终产品的质量。

在数学上,理想的音符由“基本”的几何系列组成。

假设F0是基频,那么大多数音符将近似为F(t)+ F0 * sum(a_k e ^(2 ^ k F0 * pi i t))= F0 + a_1 * F1 + a_2 * F2 +。 ...

a_k只是那些较高频率F_k的强度,而F_k只是F0的倍数。如果对于所有k a_k = 0,则我们有一个纯正弦曲线。其音高易于检测。只要找到FFT的最大值,频率就是音调的基础=音符。

进行FFT运算时,最终得到的是数据,然后进行数学运算。它基本上是微积分。

所有这些都是相对容易的。

您必须处理一些问题。请注意,并非所有这些都是“已解决”的。

  1. 延迟-如果您要进行任何类型的实时工作,这可能会成为问题。

  2. 多个音符-由于所有额外的谐波,很难确定音符组。如果播放A = 440hz,而A'= 880hz,则大多数谐波将重叠。您可以轻松获得A = 440hz,但是获得A'= 880hz则更加困难。当您想到和弦,快速运行等时,精确获取所有信息(注释)可能会非常困难。虽然从数学上讲一切都是可能的,但数据本身具有错误和像差,并且在某些情况下方程式定义不足。

  3. 噪声-信号中的噪声会给您带来虚假的结果。如果发生音乐噪音,可能会破坏您的效果。这样就需要更好的算法=时间+金钱+知识。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.