音符起始點檢測介紹
音符起始點檢測(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='--')