【UE4】Procedural MIDIでMIDIファイルを元にオブジェクトを生成する
最初に
この記事はMozPacaさんの
mozpaca.hatenablog.com
こちらの記事を読み、触発されて書いたものです。
Procedural MIDIを掘り下げていく過程がわかりやすく書かれているので、
まずはその記事を読んでみてください。
ただし、現在のProcedural MIDIプラグインとはBPノードの見た目や項目数等が異なっていますので、それだけは注意してください。
Procedural MIDIとは
UE4でMIDI関連を取り扱えるようになるプラグインになります。
www.unrealengine.com
こちらからプラグインはダウンロードできますが、
必ず上記のサイトから飛べる「サンプルプロジェクト」もダウンロードするようにしてください!
サンプルプロジェクトは、機能を再確認したりする時にもとても役に立ちます。
まずはサンプルプロジェクトを見てみよう
まずは上記のサンプルプロジェクトを開いてみましょう。
「BP_Readme」の中に書かれているコメントを読んでおくと、今後の応用もやりやすくなると思います。
このサンプルプロジェクト内には、MIDIの初期化などを担当する「BP_Asset_Player」、それを継承し、MIDIメッセージから音を鳴らすのを担当する「BP_MIDI_Player」、
更にそれを継承し、MIDIメッセージを元に視覚オブジェクトを操作する「BP_Visual_MIDI_Player」という3つのオブジェクトがあります。
この構成を元にしてプロジェクトを作ってみましょう。
あと、できればサンプルプロジェクトを実行してみてください。MIDIの音が鳴ると同時に画面内のオブジェクトの色が変わるのがわかると思います。
一体何が起きているのか、自分で調べてみるのも良いと思います。
新しいプロジェクトでブループリントを作ってみる
新しいプロジェクトを立ち上げて、「編集」→「Plugin」を開き、
の「MIDI Plugin」の「Enabled」がチェックされているかを確認しましょう。
チェックされていなかったら、チェックして再起動します。
確認が終わったら、サンプルプロジェクトを参考にして3つのブループリントクラスを作ります。
「BP_Base」と、
それを継承してMIDIから音を鳴らしたりうんぬんする「BP_ObjBase」、
更にそれを継承して、オブジェ生成を担当する「BP_ObjFactory」です。
この上の「MIDIメッセージの中身表示」の部分は検証用に作ったものなので、ご自由にどうぞ。
MIDIメッセージとMIDIファイルの関係
MIDIファイル内にある譜面を再生している時の
「音符」とか「テンポチェンジ」とか「ピッチ変更」とかの指示がMIDIメッセージとして流されます。
つまり、MIDIファイル=譜面とすると、演奏者の「ここでこの音符を鳴らすぞ!」という脳からの命令がMIDIメッセージで、
それが身体に伝わって楽器(MIDI音源)を鳴らす、ということになります。
UE4でMIDIメッセージをゲームなどに利用する際、どんな種類のメッセージに対応して動作させるのかを決めるのは大事です。
どんな種類のメッセージでも受け付けてしまうと、「音符に合わせてオブジェクトを作りたい/動かしたい」と思って実装したものが、
ピッチの変更や楽器の変更などのメッセージで誤動作してしまうからです。
MIDIメッセージの種類はこのように列挙型でまとめられているので、
この中の「Note」でだけ動作するようにブランチを用意するといいと思います。
それではBP_ObjFactoryの「OnMidiEvent」イベントを見てみましょう。
この引数の意味ですが、
・Event Type:このメッセージはどの種類のメッセージか(前述の列挙型)
・Event Channel:何チャンネル目のメッセージか(MIDIはチャンネル数が16あります。つまり同時に16種類の楽器の音が出せるようになっています)0~15の間の値になります。
・Event Data 1:0~127の値になります。Noteメッセージの場合は音の高さになります。それぞれの数値が低い順に鍵盤に割り当てられていると考えてください。
・Event Data 2:0~127の値になります。Noteメッセージの場合は音の強さ(ベロシティ)になります。0の場合、無音になります。
となっています。
ですので今回、自分の場合では
このようにして、音の高さをY軸、音の強さをZ軸にして、さらにチャンネルごとに高さと生成するオブジェの種類を分けることにしました。
ここで大事なのは、「Noteメッセージは、MIDIの音符開始時と終了時の、合計2回流れる」ということです。
例えばベロシティ64の音が鳴る時、鳴り始めにベロシティ64のNoteメッセージが流れ、鳴り終わりにベロシティ0のNoteメッセージが流れます。
ですので、単にNoteメッセージを受け取るだけの実装にすると、予想だにしないタイミングでイベントが発生してしまうことがあります。
先ほどの画像の左上で「!=0」の判定を用意してブランチを挟んでいるのは、このためです。
MIDIファイルを用意して再生してみる
あとはMIDIファイルを用意して再生してみましょう。
Procedural MIDIの続編。弦楽4重奏でおなじみのカノンを元にオブジェクト生成。トラック番号に応じて生成するオブジェクトの種類を変えてみたので、わかりやすいかと。 #UE4 #UE4Study pic.twitter.com/a7iURXyELP
— D.Ohnuma@2月中にアプデ (@dfk_ohnuma) 2017年1月24日
こちらの動作デモではわかりやすいように、弦楽四重奏のカノンのMIDIファイルを使っています。
音を鳴らさずにMIDIファイルを再生する
さて、ここからがある意味本番です。
BP_ObjBaseの、赤く囲った部分の接続を外して、もう一度実行してみましょう。
すると、音は鳴らないのにMIDIファイルの通りにオブジェが生成されているのがわかると思います。
( ^ω^)これがとても美味しいのです。
つまりBGMを別に用意して、BGMと同じテンポでMIDIファイルを作り、同時に再生すれば、
BGMの音楽に合わせた演出やオブジェ生成のためだけのスクリプトファイルとして使うことが出来ます。
MIDIファイルはチャンネル数が16あるので、16チャンネル分の命令を1つのファイルで作ることが出来ます。
どのチャンネルのメッセージなのかをSwitchノードなどで分岐させて実装すれば、
1つのステージ内の敵出現、演出、その他もろもろを1つのMIDIファイルに集約することも可能になると思います。