Pythonで楽器音の比較をしようとした話
とある事情で2つの楽器音波形の比較をやりたくなったので、Pythonで色々試してみたメモです。
やりたいこと
使ったもの
比較方法
2つの波形から特徴量を抽出し、特徴量同士の差分(距離)を計算、差分が小さければ「同じ」、大きければ「違う」とみなします。
今回試した特徴量は以下の3つです。
- 振幅スペクトル
- 振幅スペクトル(セントロイド)
- 意味合いとしては1.と同じだけど、こっちは各フレームの振幅スペクトルのセントロイド(重心)を比較する
- librosaのリファレンスを見てたら振幅スペクトルのセントロイド抽出ができるとわかったので使ってみた(てきとう)
- [時間フレーム数] の一次元配列になり、1.と比べて比較数が少ないので計算量で優位
- MFCC(メル周波数ケプストラム係数)
- 波形からMFCCを抽出し、各フレームのMFCC列を比較する
- MFCCは音声認識でよく使われる特徴量で、ここでは波形同士の音色の特性を比較するみたいな意味合いになると思う(よくわかってない)
- [時間フレーム数] × [MFCC次元数] の二次元配列になる
比較する波形同士はフレーム数が互いに異なる場合が多いです。したがって、系列長が異なるデータ同士の比較が可能なDTW(動的時間短縮)という手法を用いて波形を比較します。少し詳しい話をすると、特徴量のユークリッド距離を各点のコストとし、累積距離を0.0〜1.0に正規化してこれを波形同士の類似度とします。
プログラム
wavファイルからそれぞれの特徴量を抽出し、DTWで類似度を計算するスクリプトを作りました。
github.com
実験
Studio One 3でピアノのサンプル音をいくつか録音し、比較をおこないます。録音したサンプルは以下の5つです。
- 音高C3、4分音符の長さで鳴らしたピアノ音(比較基準)
- 1.と同じ条件で、1.とは別に録音
- 1.と同じ条件で、発音時刻を1秒遅らせた
- 1.の条件の長さのみ2分音符に変更して鳴らしたもの
- 1.と同じ条件で、リバーブをかけた
期待する結果としては、1.〜4.で類似度が高くなり、5.で類似度が低くなってくれればOKです。
結果
各ペアの類似度を示します。
比較ペア | 振幅スペクトル |
振幅スペクトル (セントロイド) |
MFCC |
---|---|---|---|
1 , 1 |
1.000 |
1.000 |
1.000 |
1 , 2 |
1.000 |
0.986 |
1.000 |
1 , 3 |
0.795 |
0.949 |
0.832 |
1 , 4 |
0.995 |
0.905 |
0.983 |
1 , 5 |
0.973 |
0.784 |
0.917 |
総合的に見ると振幅スペクトル(セントロイド)が強そうです。5.との比較で類似度が下がっているので、期待した結果と言えます。一方で、長さが異なる音との比較では振幅スペクトルとMFCCが割とロバストなのかなあとも思われます。あとは閾値をうまいこと設定してやれば、ひとまずは識別ができそうな感じです。
最後に
超簡単に信号処理やオーディオ分析ができるlibrosaは神。