ただいまカバーソング検出という課題に当たるため、オーディオからメロディー抽出するアルゴリズムを調べております。
ここで言うメロディー抽出の対象は、メロディー以外にも伴奏などいろんな音高が同時に鳴っている多音音楽(polyphonic audio)の音源です。抽出されるメロディーというのはつまり基本周波数の序列です(基本周波数とピッチは単純に対応すると思ってはいけないらしい)。
メロディーしか鳴らない単旋律モノの基本周波数の検出は、「YINアルゴリズム」など有効な方法がすでにあり、ほぼ解決していると見ていいのですが、多音はいまだパーフェクトな方法が確立されていません。
オーディオ信号をDFTすると周波数エネルギーのピークはスペクトグラムのあちこちにありますので、そのうちどれが基本周波数なのか、ましてやメロディーの基本周波数なのか判断するのは至難の業です。
そもそも「メロディーはどれか」というのは、結構主観的なところがあります。メロディーについてMIRコミュニティーが定義を出したことがあるんですが、
“. . . the melody is the single (monophonic) pitch sequence that a listener might reproduce if asked to whistle or hum a piece of polyphonic music, and that a listener would recognize as being the ‘essence’ of that music when heard in comparison”.
というものです。「リスナーにある音楽を口ずさむよう求めたときに、彼が口ずさむもの」って感じですね。このような人間的な判断をどうやってコンピューターで再現させるのでしょうか。
今回は数ある研究の中で比較的成果がいいといわれてるアルゴリズムに目をつけてます。Justin Salamon氏が2012年に発表したものです。
詳しい紹介と、もっと詳しい論文はここから見れます。
http://www.justinsalamon.com/melody-extraction.html
おおまかな流れは、以下の感じです。
- 前処理:フィルタを通してメロディーがありそうな周波数域を強調する。
- DFTしてスペクトグラムからピークを検出
- 周波数を一定間隔にFrequency binsに分割して、各binごとにSalience Functionを計算。あるbinのsalienceは、相応の周波数と倍音のエネルギーの重み付き和を計算したもの。これでこの周波数が「どれくらい顕著に聞こえるか」をあらわす。これがメロディーピッチの選択の根拠の一つになる。
- 一方検出されたピークは、隣接するものをつなぎ合わせてひとつひとつの「Contour(輪郭線)」になる。これらのなかから、メロディーラインを選ぶことになる。
- 各Contourからは、音高の平均値や分散、salienceの平均値と総和、ビブラートの有無(特に歌ものに関しては、ビブラートがあるContourはメロディーである可能性が非常に高い)などの情報を求めることができる。これらの情報を使い、いくつかのルールをもとにメロディーラインである可能性が低いContourを排除していく。
- 同じ時間に二つのContourがかさばらない状態になった時点で終了。
Salience functionというのが大活躍しているのですが、論文のまとめが語るようにsalience functionを求めること自体はメロディー抽出でよく使われるアプローチで、別に新しい試みではありません。Contourを構築するのも割とスタンダードです。
この手法の貢献は主にそのあとで、論文タイトルでも示したようにContourの特徴(characteristics)を使って、メロディーであるものとそうでないものをどう区別するかという方法を提示したところにあります。
このアルゴリズム、つい最近まで論文をもとに自力でPython書いて実装してみてたんですが、Salience functionを計算した時点で計算時間が長すぎて(10秒の音の分析に10分以上かかるという)ドン詰まりしてました。どうしたものかと悩んでたところで、Essentiaというオープンソースのアルゴリズム集の中にちゃんとあることに気づき、今までのは何だったんだァーってなっています。
Essentiaにはオーディオ分析に関する基本的なアルゴリズムが提供されてるので、今後有効活用していきたいですね。
自分の実装はどこが問題だったのか見てみたいです。