UnityでMIDIを再生する
UnityでMIDI(Standard MIDI File)を再生する必要が生じたのでやってみました。 MIDIを再生して何がしたかったのかみたいなのもそのうち公開するかもしれません。 動く最小限のサンプルは以下のレポジトリに入っています。MacとiOSで動きました。 github.com
C# Synth ProjectというC#で書かれたMIDIのライブラリが"ほぼ"そのままUnityでも動きました、というだけの話ですが、以下に手順を書いておきます。以下の手順を行った結果が上のレポジトリです。
追記:もっと良い方法を求めている人は:このQiita記事とかNativeAudioPluginsとかhttps://github.com/keijiroとかを参照。
1. C# Synth Project のソースをインポート
色々直したい部分があるのでソースをそのまま突っ込みました。Source/AudioSynthesisフォルダだけでOKです。
2. .NET 3.5対応
Unityの.NET frameworkは古いので、エラーが出た部分を書き直します。
Workarounds for .NET compatibility. · n-yoda/unity-midi@1a54828 · GitHub
3. Synthesizerクラスの修正
音の波形を合成してくれるSynthesizerクラスは、丁寧にbyte配列にエンコードしてくれます。
が、Unityの場合floatで欲しいので書き換えます。
Reveal float buffer. · n-yoda/unity-midi@443c91f · GitHub
4. MidiFileSequencer -> Synthesizer -> OnAudioFilterRead
MidiFileSequencerでmidiイベントを処理して、Synthesizerで音を合成し、OnAudioFilterReadで渡す、というコードを書きます。 OnAudioFilterReadはAudioSource.clipがnullでも使えるみたいです。
unity-midi/MidiPlayer.cs at master · n-yoda/unity-midi · GitHub
現状ここにいくつか問題があって、
- 本当はAudioClip.Createが使いたいけどエディタがクラッシュする。
- ググると結構前から報告されているバグのようです・・・
- AudioSource.clipがnullの場合、OnAudioFilterReadのサンプリングレートが不明
- チャンネル数もOnAudioFilterReadが初めて呼ばれるときまでわからない。
- サンプリングレートはMac上では44100Hzと仮定したら上手く動いた。
動いたので満足してしまいましたが、Unityの中の方々に聞いたほうが良いかもしれません。
5. .bankと.midファイルを読み込んで再生
どちらもStreamingAssetsフォルダに入れて読み込むと良いと思います。
.bankファイルには音色データが入っているようです。バンクというのはMIDIの仕様にある概念みたいですが、フォーマットはC# Synth Project独自のものかも…?サンプルでは、C# Synth Projectに含まれるGMBank.bank(GMはGeneral MIDI)を使っています。
.midは上のサンプルでは、The Mutopia Projectでダウンロードした「悲愴 第2楽章」(ここさけで流れた曲!)を指定しました。
あとは興味があればソースを見て頂ければと思います。