曲を聴かせると、コード進行を推定してギター TAB にしてくれる Web ツールを作りました(耳コピ ギター TAB メーカー)。サーバーでの計算はなく、音源分離のモデルまで含めて、全部ブラウザの中で動きます。
解析は 2 段階です(ツールの画面では「最初の解析」「詳しい解析」と呼んでいます)。
- 信号処理だけの解析(速い):曲をそのまま、拍の検出と 12 音の成分の照合で読む。数秒で出る
- 音源分離してからの解析(詳しい):深層学習のモデル(SCNet)で曲を歌・ドラム・ベース・ほかの楽器に分けてから、同じ信号処理で読み直す(パソコンのみ)
この記事では、フリー音楽素材の魔王魂「シャイニングスター」でやってみた結果と、分けることで何が良くなったかを書きます。
シャイニングスターでやってみました
曲は魔王魂のページで配布されている歌入りの版(約 4 分 37 秒)です。正解の譜面はないので、ChordWiki の投稿譜(どなたかの耳コピ)と、コードの並びを比べました。正解率ではなく「投稿譜にどれだけ近いか」です。
数値は、投稿譜のコードの変わり目を順にたどって、ツールの出したコードの並びの中に(ルートが同じものが)見つかった割合です。ツールの余分なコードは減点していません。
| 範囲 | 信号処理だけ(ルート) | 音源分離してから(ルート) |
|---|---|---|
| イントロ | 0.56(10/18) | 0.50(9/18) |
| 最初の歌の部分(A メロ〜1 回目のサビ) | 0.59(19/32) | 0.78(25/32) |
| 曲全体(ツールのコードの数が投稿譜の倍以上あるので甘め) | 0.86 | 0.87 |
キー(Db)とテンポ(158 BPM)は、投稿譜と同じでした。
目立つのは歌の部分です。音を聴いただけでコードがわかる人たちは、まずベースから当たりをつける、と聞いたことがあったので、このツールはどちらの解析でも、まずベースからルートを決めて、次に上の和音を読む作りにしています。ただ、曲全体の音のままだと、歌のメロディまで和音の一部として数えてしまいます。そこで、音源分離で歌とドラムを抜き、分けたベースとほかの楽器だけを聴かせて読み直してみたら、歌の部分は 0.59 から 0.78 まで上がり、うまくいきました。投稿譜との比べ方なので正解率ではありませんが、数値的にはそこまで悪くないのでは、と思っています。
一方、転回形や経過和音が続くイントロは、どちらも苦手なままでした。
分けると、弾くタイミングも良くなる
もう一つ良かったのが、ギターを弾くタイミングです。
ツールは、コードだけでなく、原曲に合わせて鳴らすストロークのタイミングも、曲の音から拾っています。信号処理だけの解析では、歌もドラムも一つの音として聴くので、歌の言葉の立ち上がりにも反応してしまい、どこで弾くのかが曖昧になりがちでした。
音源分離してからの解析では、タイミングをドラムとほかの楽器の音から取ります。歌が抜けるので、楽器が刻んでいるところで弾くようになります。実際、曲全体の音から拾ったタイミングと楽器から拾ったタイミングを比べると、歌のない曲ではほぼ同じでしたが、シャイニングスターでは 8 分音符の位置まで一致した小節が 181 小節中 28 小節だけでした。それだけ歌に引っぱられていたということです。コードに加えて、ここもうれしい改善でした。
また、歌だけになる小節(歌い出しやブレイクで楽器が止まる所)がわかるので、そこではギターを鳴らさないようにしています。シャイニングスターは歌の下で楽器が止まらない曲なので、今回は出番がありませんでした。
聴き比べのページ
Qiita では音声を再生できないので、分けた音は自分のサイトに載せています。
シャイニングスターの歌の入った 20 秒を、歌・ドラム・ベース・ギター鍵盤ほかに分けたものを、全部同時に流しながら、パートごとに音量を変えられます(魔王魂の楽曲を改変しています)。ベースだけにすると、ツールがまず何を聴いてルートを決めているかがわかると思います。
同じページで、ツールが弾くギター(信号処理だけのときと、音源分離してからのとき)も曲に重ねて流せます。コードとタイミングがどう変わるかを、耳で比べてみてください。
しくみ
音声(ファイル/タブの音/マイク)
└ Web Worker
├ 信号処理だけの解析:拍 → 小節 → 小節ごとの 12 音の成分 → まずベース、次に和音 → キー
└ 音源分離してからの解析:SCNet でパート分け → ベースとほかの楽器でコード、ドラムとほかの楽器でタイミングを読み直す
└ 画面:ストロークの TAB を合成音で鳴らし、原曲と重ねて再生
パート分けには、音源分離のモデル SCNet Small(Tong ほか)を使っています。実装は ZFTurbo/Music-Source-Separation-Training(コードは MIT)です。ブラウザで動かすのは一苦労でした。
- onnxruntime-web の WebGPU で動かすと、シャイニングスター 1 曲に 296 秒。遅いのは真ん中の LSTM でした
- その部分だけを WebGPU(WGSL)で自分で書き直して、102 秒に(M5 の MacBook Air)
- 今聴いている場所の近くから分けていき、分け終わった所から TAB を差し替えるので、最初の結果は 8 秒ほどで出ます
スマホでは、音源分離の途中でタブが落ちてしまいました。いろいろ削って、ページ(JS と WebAssembly)のメモリをスマホ向けの処理で 1,088 MB から 408 MB まで減らしましたが(GPU 側のメモリは測れていません)、実機ではまだ動かなかったので、音源分離はパソコンだけにしています。
まとめ
ブラウザだけでコードを推定するのは、正直そこまで期待していなかったのですが、シャイニングスターで試すと、キーとテンポは投稿譜どおりで、歌の部分では投稿譜の 32 個のコードのうち 25 個のルートが見つかりました。まあまあ良い方なんじゃないかと思っています。
一番の手応えは、音源を分けてから、ベースから読むやり方でした。歌を抜くだけで、歌の部分のコードが 0.59 から 0.78 に上がり、ギターを弾くタイミングも楽器の刻みに合わせられるようになります。歌だけの所でギターを黙らせられるのも、分けたからこそできることです(この曲では出番がありませんでしたが)。
凝ったコード進行のイントロはまだ苦手ですし、スマホで分離まで回すにはメモリの壁があります。このあたりは、モデルの工夫やアプリ化で、もう少し詰めたいと思っています。
結果は自動の推定で、間違いを含みます。他人の曲の TAB やコード譜を公開・配布するときは、権利者の許可が必要になる場合があるので気をつけてください。
- 音楽:魔王魂「シャイニングスター」(歌:詩歩、作詞・作曲:森田交一)https://maou.audio/14_shining_star/ 。聴き比べのページの音声は魔王魂の楽曲を改変したもの
- 比べた投稿譜:ChordWiki「シャイニングスター」 https://ja.chordwiki.org/wiki/%E3%82%B7%E3%83%A3%E3%82%A4%E3%83%8B%E3%83%B3%E3%82%B0%E3%82%B9%E3%82%BF%E3%83%BC
- 音源分離:SCNet(Tong ほか)、ZFTurbo/Music-Source-Separation-Training(コードは MIT)、学習済みの重みは starrytong 氏が公開したもの(MUSDB18 で学習。重みのライセンスは明記されていません)
- 推論:onnxruntime-web(MIT)と、自前の WebGPU の処理
- 時間はすべて MacBook Air(M5、24 GB)、Chrome での実測(102 秒は Mac が空いているときの値)
