【发布时间】:2010-09-30 22:27:06
【问题描述】:
在印度 IIT-Bombay 举办了一场科技节,他们在那里举办了一个名为“Artbots”的活动,我们应该设计具有艺术能力的艺术机器人。我有一个关于音乐机器人的想法,它以歌曲为输入,检测歌曲中的音符并在钢琴上播放。我需要一些方法来帮助我计算歌曲音符的音高。关于如何去做的任何想法/建议?
【问题讨论】:
标签: signal-processing detect frequency pitch-tracking
在印度 IIT-Bombay 举办了一场科技节,他们在那里举办了一个名为“Artbots”的活动,我们应该设计具有艺术能力的艺术机器人。我有一个关于音乐机器人的想法,它以歌曲为输入,检测歌曲中的音符并在钢琴上播放。我需要一些方法来帮助我计算歌曲音符的音高。关于如何去做的任何想法/建议?
【问题讨论】:
标签: signal-processing detect frequency pitch-tracking
这正是我作为我去年的项目在这里所做的 :) 除了我的项目是关于跟踪人类歌声的音高的一件事(而且我没有机器人来演奏曲调)
我能想到的最快方法是使用BASS library。它包含即用型功能,可以为您提供来自默认记录设备的 FFT 数据。看看 BASS 附带的“livespec”代码示例。
顺便说一下,原始 FFT 数据不足以确定基频。您需要 Harmonic Product Spectrum 等算法来获得 F0。
另一个考虑因素是音频源。如果您要进行 FFT 并在其上应用谐波乘积频谱。您需要确保输入只有一个音频源。如果它包含多个来源,例如在现代歌曲中,则需要考虑很多频率。
谐波乘积谱理论
如果输入信号是一个音符, 那么它的频谱应该包括一个 一系列峰,对应于 基频与谐波 在整数倍的组件 基频。因此当我们 压缩频谱的数量 次(下采样),并进行比较 使用原始光谱,我们可以看到 最强的谐波峰线 向上。原著中的第一个高峰 光谱与第二个重合 频谱中的峰值由 a 压缩 因子二,与 光谱中的第三个峰 压缩了三倍。 因此,当各种光谱 相乘,结果将 在基本形成清晰的峰值 频率。
方法
首先,我们将输入信号分为 通过应用汉宁窗分割, 窗口大小和跃点大小在哪里 作为输入给出。对于每个窗口, 我们利用短时傅里叶 变换以转换输入信号 从时域到频率 领域。一旦输入在 频域,我们应用 谐波产品频谱技术 每个窗口。
HPS 涉及两个步骤: 下采样和乘法。到 下采样,我们压缩了频谱 通过重采样在每个窗口中两次: 第一次,我们压缩 原始光谱由两个和 第二次,三分之二。一旦这是 完成后,我们将三个相乘 光谱一起找到 对应于峰值的频率 (最大值)。这个特别 频率代表基本 该特定窗口的频率。
HPS 方法的局限性
此方法的一些不错的功能 包括:它是计算的 便宜,合理地抵抗 加性和乘性噪声,以及 可调整到不同类型 输入。例如,我们可以改变 压缩光谱的数量 使用,我们可以替换光谱 与光谱相乘 添加。然而,由于人类音高 感知基本上是对数的, 这意味着低音可能是 跟踪精度低于高 球场。
HPS 的另一个严重不足 方法是它的分辨率是 仅与 FFT 的长度一样好 用于计算频谱。要是我们 执行一个短而快的 FFT,我们是 离散的数量有限 我们可以考虑的频率。为了 以获得更高的分辨率在我们的 输出(因此少见 我们的音高输出中的颗粒度),我们 需要更长的 FFT 需要更多时间。
【讨论】:
只是一个评论:基本谐波也可能从(谐波)声音中丢失,这不会改变感知的音高。作为极限情况,如果您采用方波(例如,C# 音符)并完全抑制一次谐波,则感知到的音符仍然是 C#,在同一个八度音程中。在某种程度上,当我们的大脑猜测一个音符时,它能够补偿一些谐波的缺失,即使是第一个。 因此,要使用频域技术检测音高,您应该考虑所有谐波(傅里叶变换幅度的局部最大值),并提取它们的某种“最大公约数”频率。音高检测根本不是一个小问题...
DAFX 有大约 30 页专门用于音高检测,包括示例和 Matlab 代码。
【讨论】:
自相关 - http://en.wikipedia.org/wiki/Autocorrelation
过零 - http://en.wikipedia.org/wiki/Zero_crossing(这种方法用于廉价吉他调音器)
【讨论】:
试试YAAPT pitch tracking,它可以检测时域和频域中的基频。您可以从链接下载 Matlab 源代码,并使用频谱处理部分在 FFT 输出中查找峰值。
Python 包http://bjbschmitt.github.io/AMFM_decompy/pYAAPT.html#
【讨论】:
你试过Wikipedia's article on pitch detection吗?它包含一些您可能会感兴趣的参考资料。
另外,这里有一个list of DSP applications and libraries,你可以在那里四处逛逛。列表中只提到了 Linux 软件包,但其中很多都是跨平台的,而且有很多源代码你可以看看。
仅供参考,大多数精通 DSP 的人都可以检测单声道录音中的音符音高。检测所有音符的音高,包括和弦等,要困难得多。
【讨论】:
只是一个想法 - 但您是否需要处理数字音频流作为输入?
如果不是,请考虑使用音乐的符号表示(例如 MIDI)。音符的音高会被明确地表述出来,您可以非常轻松地合成与音高、节奏和许多其他音乐参数相对应的声音(和动作)。
如果您需要分析数字音频流(mp3、wav、实时输入等),请记住,虽然简单单声道声音的音高检测非常先进,但复音音高检测是一个未解决的问题。在这种情况下,您可能会发现我对this question 的回答很有帮助。
【讨论】:
要从复音音乐中提取旋律的基频,您可以尝试使用 MELODIA 插件:http://mtg.upf.edu/technologies/melodia
提取歌曲中所有乐器的 F0(多 F0 跟踪)或将它们转录成音符是一项更难的任务。旋律提取和音乐转录仍然是开放的研究问题,因此无论您使用哪种算法/工具,都不要期望获得完美的结果。
【讨论】:
如果您尝试检测和弦录音的音符(同时有多个音符),祝您好运。这是一个非常棘手的问题。我不知道有什么方法可以听,比如说,弦乐四重奏的录音,并有一个算法将四个声音分开。 (也许是小波?)如果一次只有一个音符,那么有几种音高跟踪算法,其中许多在其他 cmets 中提到。
您要使用的算法取决于您收听的音乐类型。如果你想让它拾起人们唱歌,那么有很多专门为语音设计的优秀算法。 (大部分研究都在那儿。)如果你想选择特定的乐器,你就必须更有创意。语音算法可以很简单,因为人类歌声的范围通常被限制在 100-2000 Hz 左右。 (说话范围要窄得多)。然而,钢琴的基本频率从大约 27 Hz 开始。到 4200 Hz,因此您正在处理通常被音高检测算法忽略的更宽范围。
大多数仪器的波形会相当复杂,包含大量谐波,因此计数零或仅采用自相关等简单方法将行不通。如果您大致知道要查看的频率范围,则可以进行低通滤波,然后进行零计数。我认为您最好使用更复杂的算法,例如另一个用户提到的谐波产品频谱,或 YAAPT(“另一个音高跟踪算法”)或类似的东西。
最后一个问题:某些乐器,尤其是钢琴,会存在缺少基本音和不和谐的问题。缺少的基本原理可以通过音高跟踪算法来处理……事实上它们必须如此,因为在电子传输中经常会切断基本原理……尽管你可能仍然会遇到一些八度音阶错误。然而,如果有人在钢琴的最低八度音阶中弹奏一个音符,不和谐会给你带来麻烦。正常的音高跟踪算法不是为处理不和谐而设计的,因为人声并没有明显的不和谐。
【讨论】:
您基本上需要一个频谱分析仪。您可能能够对模拟输入的录音进行 FFT,但这在很大程度上取决于录音的分辨率。
【讨论】:
我立刻想到了什么:
我不确定这是否适用于非常复音的声音 - 可能在谷歌上搜索“FFT、分析、旋律等”。将返回有关可能出现的问题的更多信息。
问候
【讨论】: