结合Python代码介绍音符起始点检测 (onset detection)

本文由 meelo 原创,请务必以链接形式注明 本文地址

音符起始点检测介绍

音符起始点检测(onset detection)是音乐信号处理中非常重要的一个算法。节拍和速度(tempo)的检测都会基于音符起始点的检测。

音符起始点就是其字面意思,表示琴键🎹按下的那个时刻。

 

音符起始点检测仍然是一个非常活跃的研究方向,MIREX的年度音乐信号处理竞赛的一个题目便是音符起始点检测

本文里,我会结合代码,介绍一种简单的算法。

注:代码使用了Python的librosa库。

 

音符起始点的一个特征是,能量的突然增加,或是频谱能量分布的改变。

根据这一特征,我们可以设计如下算法。算法是在频域进行的。

算法

输入为音乐的离散时间信号,输出为所有音符起始点的时间。

1. 计算对数梅尔时频图幅度

mel = np.abs(librosa.feature.melspectrogram(y, fmax=11025))
amp_db = librosa.power_to_db(mel)

2. 计算对数梅尔时频图幅度的一阶时间差分,并计算每一帧所有频率点幅度的均值。

diff = np.maximum(amp_db[:,1:] - amp_db[:,:-1], 0.0)
onset_amp = np.mean(diff, axis=0)

3. 归一化到[0,1]之间,并进行峰值检测。

onset_my -= onset_my.min()
onset_my /= onset_my.max()
onset_peak = librosa.util.peak_pick(onset_my)

上图中蓝色实线表示算法中第二步所计算得到的结果,红色虚线是峰值检测后的结果。

库函数用法示例

Python的librosa库中已有音符起始点检测的函数,使用的算法便是上面介绍的算法。如果希望了解算法的一些细节以及参数的选择,可以阅读函数的源码。

下面是库函数的一个示例用法:

import librosa

y, sr = librosa.load('music.mp3')
onsets_frames = librosa.onset.onset_detect(y)
D = librosa.stft(y)
librosa.display.specshow(librosa.amplitude_to_db(D))
plt.vlines(onsets_frames, 0, sr, color='r', linestyle='--')

 

posted on 2017-11-15 16:03  meelo  阅读(8565)  评论(0编辑  收藏  举报