Shun40の日々のあれこれをまとめるやつ

DTMとかプログラミングとかその他諸々の話をするブログです。

Pythonで楽器音の比較をしようとした話

とある事情で2つの楽器音波形の比較をやりたくなったので、Pythonで色々試してみたメモです。

やりたいこと

  • 2つの楽器音波形を比較する。目標は楽器音のエフェクトオン・オフによる違いの識別で、やりたいこととしては以下のような感じ。
    • バーブオフのピアノ音とバーブオフのピアノ音 → 同じと判断
    • バーブオフのピアノ音とバーブオンのピアノ音 → 違うと判断

使ったもの

  • Python 3.7.0
    • numpy:数値計算の機能を提供するPythonパッケージ
    • librosa:オーディオ信号の様々な分析機能を提供するPythonパッケージ
  • Studio One 3(DAW

比較方法

2つの波形から特徴量を抽出し、特徴量同士の差分(距離)を計算、差分が小さければ「同じ」、大きければ「違う」とみなします。
今回試した特徴量は以下の3つです。

  1. 振幅スペクトル
    • 波形にSTFT(短時間フーリエ変換)を適用し、各フレームの振幅スペクトル列を比較する
    • 波形同士の周波数特性を比較することを意味する
    • [時間フレーム数] × [FFTサイズ / 2 + 1] の二次元配列になる
  2. 振幅スペクトル(セントロイド)
    • 意味合いとしては1.と同じだけど、こっちは各フレームの振幅スペクトルのセントロイド(重心)を比較する
    • librosaのリファレンスを見てたら振幅スペクトルのセントロイド抽出ができるとわかったので使ってみた(てきとう)
    • [時間フレーム数] の一次元配列になり、1.と比べて比較数が少ないので計算量で優位
  3. MFCC(メル周波数ケプストラム係数)
    • 波形からMFCCを抽出し、各フレームのMFCC列を比較する
    • MFCCは音声認識でよく使われる特徴量で、ここでは波形同士の音色の特性を比較するみたいな意味合いになると思う(よくわかってない)
    • [時間フレーム数] × [MFCC次元数] の二次元配列になる

比較する波形同士はフレーム数が互いに異なる場合が多いです。したがって、系列長が異なるデータ同士の比較が可能なDTW(動的時間短縮)という手法を用いて波形を比較します。少し詳しい話をすると、特徴量のユークリッド距離を各点のコストとし、累積距離を0.0〜1.0に正規化してこれを波形同士の類似度とします。

プログラム

wavファイルからそれぞれの特徴量を抽出し、DTWで類似度を計算するスクリプトを作りました。
github.com

実験

Studio One 3でピアノのサンプル音をいくつか録音し、比較をおこないます。録音したサンプルは以下の5つです。

  1. 音高C3、4分音符の長さで鳴らしたピアノ音(比較基準)
  2. 1.と同じ条件で、1.とは別に録音
  3. 1.と同じ条件で、発音時刻を1秒遅らせた
  4. 1.の条件の長さのみ2分音符に変更して鳴らしたもの
  5. 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は神。