🎼

個人開発で爆速な音楽再生サイトを作った

2023/03/13に公開

個人開発で爆速な音楽再生サイトを作ったので、遊んでみてください。

ちなみに少し前に 古の MIDI を集めた検索サイトを作った という記事を書いたのですが、その改良版です。つまり MIDI だからこそできるお話。そのとき作った Free MIDI というサイトに限らず、音楽サービスはネットワーク通信量がネックとなりがちです。その問題に対して、ついカッとなって本気で再実装したところ、これまでにないほど爆速な音楽再生を実現したサイトが完成しました。技術的にも興味深かったので紹介します。

https://marmooo.github.io/free-midi/

ポイントとなる技術は 2つあります。

1. AudioWorklet + Wasm = js-synthesizer

これまで MIDI の再生には Magenta.js を使っていたのですが、その中ではメインスレッドで音階と楽器ごとの MP3 を演奏していました。特にメインスレッドの部分は再生負荷の影響が大きく、同時に再生する音符が増えるとかなりの負荷が掛かっていました。これを AudioWorklet と Wasm を利用した再生に変えることで、メインスレッドとは別のスレッドで再生するようにしました。真面目にやると実装がとても大変と思うのですが、js-synthesizer という素敵なライブラリのおかげで簡単に実現できました。js-synthesizer は libfluidsynth を Wasm 化して使いやすくした凄いライブラリです。メインスレッドを専有しないおかげで、ラグはほぼ発生しなくなりました。今や Web 上でサウンドフォントを読み込んで MIDI を低遅延で再生できる時代になったのです。

2. サウンドフォントの分割読み込み

とはいえサウンドフォントは楽器と音階のデータをすべて含むので、ファイルサイズが 1GB を軽く超えてしまうこともあります。そのため Web 上ではなかなか使いにくいです。そこでサウンドフォントを sf3 圧縮し、さらに演奏する楽器だけを読み込むように実装してみました。その結果、現在デフォルトに採用しているサウンドフォントなら、1つの MIDI ファイルを再生する場合、192kbps でエンコードした MP3 と同等のネットワーク通信量で MIDI を再生できるとわかりました。

2つ以上の MIDI ファイルを再生する場合は、MP3 とは比較にならないほど効率良く再生できます。ゲーム音楽をもとに 100曲ほど再生した場合どうなるか試算してみたところ、最低25倍は効率が良くなるとわかりました。現実的にはロードする楽器はそれほど多くないので、50倍くらいの差になると思います。さらに楽器が少なければメモリ使用量も非常に少なく抑えられ、爆速な上に超軽量です。しかもエンコードで劣化させずに再生するので音質も綺麗です。これらの特徴は、音楽サイト開発者として技術的にとても興奮します。

MIDI の新時代が来る?

以上、割と MIDI がすごいかもと思ったのですが、いかがでしょうか。もしかすると MIDI の時代が再来するのではないかと勝手に思っています。Free MIDI では Dev Tools などで通信量を確認すると凄さが感じられると思うので、確認してみてください。以前書いた記事 から劇的に通信量が下がっていることがわかると思います。再生負荷の低さを感じたい場合には、音ゲーの Tip Tap RhythmTip Tap Notes、もしくはビジュアライザの Waterfall Piano で確認してみてください。メインスレッドで音楽を再生すると自前のしょぼ開発 PC では複雑な楽曲でラグが発生していましたが、今はほとんどの楽曲でスムーズにプレイできるようになりました。メモリ不足でラグやノイズが発生することはありますが、メモリにさえ注意すれば問題はまったく発生しない印象です。

https://marmooo.github.io/tip-tap-rhythm/
https://marmooo.github.io/tip-tap-notes/
https://marmooo.github.io/waterfall-piano/

まとめ

爆速な MIDI 再生サイトができたので、遊んでみてください。技術面は真面目に書くとあまりにも長い記事になるので、ブログにより深い内容をまとめました。興味のある方はご覧ください。

Discussion