[UE4] MIDIシーケンスをSequencerにトレースする

# 前段

UE4は Sequencer（以下、シーケンサー）が素敵です。

## リアルタイムと非リアルタイム

UE4のシーケンサーは、

* リアルタイム（ランタイム）でインタラクティブ要素と混在しながらライブ映像を出力する目的
* 非リアルタイム（オフライン）で高品質なレンダリングをする目的

の2つの異なる目的を達成できるようになっており、ときにはその良いところを両立することができます。また Blueprint の関数を連続・非連続で呼びだすことができるために本質的な拡張性が高いです。

バーチャルプロダクションなどの領域で仕事をさせていただくときに、ハイクオリティなレンダリングはしたいけれど、リアルタイムにフィジカルコントローラーでライブ制御したり演者の音や映像を高解像度で取り込みたいといったトレードオフとなるようなニーズが混在しています。

UE4では、これに答えるかたちで

* 撮影段階ではリアルタイム入力・出力して確認をクイックに行いつつ、
* 撮影素材を持ち帰って品質を高めて（解像度をあげたり、RayTracingを使ったりして）オフラインレンダリングをする

というようなワークフローを一つのプロジェクトで完結できるようになっています。

とはいえ、扱われるデータは高解像度な映像に加えて、センサーやトラッカー、フィジカルコントローラーなどのリアルタイム情報が多くあり、これらも同時にレコーディングして、**シーケンサーにマッピング**してあげる必要があります。今回はこのあたりの具体例がテーマです。

# やること

本記事でやることは、

**DAWのMIDI再生によってアクターを制御し、かつシーケンサーで再現可能にする**

です。DMX、OSC、LiveLinkなど別のIOにも横展開する念頭で今回は、外部ソフト上でのMIDIトラック連携を扱います。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">アドカレのネタ、外部のMIDIシーケンスをシーケンサーに焼く、というやつです <a href="https://t.co/ehp0GsLwAy">pic.twitter.com/ehp0GsLwAy</a></p>&mdash; Ayumu Nagamatsu (@ayumu_naga) <a href="https://twitter.com/ayumu_naga/status/1466854217222877186?ref_src=twsrc%5Etfw">December 3, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 1. MIDI送受信の環境をつくる

ローカル内のDAWソフトのMIDIアウトをUnrealEngineにルーティングするために、MIDIの仮想デバイスを用意する必要があります。macOSではデフォルトでルーティングができるのに対し、Windowsでは[LoopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html)などをインストールして起動する必要があります。

今回はAbletonLiveを再生環境としました。MIDI InstrumentのトラックにExternal Instrumentを設定し、MIDIの送信対象にLoopMIDIを設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/4ddbcd28-2bcd-56f6-54af-161d67498920.png)

次にUnrealEngineのMIDI受け口としては、ブループリントをかきます。まず`MIDI Device Support`プラグインを有効化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/a91fa0f9-06c1-b01b-0ad9-3e5f0d7a2a2e.png)

MIDIデバイスを見つけて監視するブループリントをレベルなどに記述します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/36cd8cdc-4114-8eac-f763-96eeb6188e54.png)

MIDIのアタックの際にノート番号に応じて処理をかいてあげるとランタイムで動くようになります。`BP_MidiHandler`というアクターがパーティクルやライティングの制御をラップしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/ccc89b8a-29d0-765a-a59e-52c1d894fb83.png)

2つの音を使って、片方でライティング制御、もう片方でパーティクルスポーンを割り当ててみました。

![Animation_5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/78723229-b881-361c-a14b-eae7b3ada50b.gif)




## 2. MIDIで任意のアクターのパラメータを動かし、レックする

ランタイムやエディター上のアニメーションをシーケンスとしてレコーティングしたい場合、[**テイクレコーダー**](https://docs.unrealengine.com/4.26/ja/AnimatingObjects/Sequencer/Workflow/TakeRecorder/UsingTR/)という便利な機能があります。代表的なアクターのパラメータ制御情報やLiveLinkの情報をシーケンサーで使えるテイクとしてレコーディングするものです。

しかし残念ながら、テイクレコーダーはすべてのコンポーネントのすべての挙動をレコーディングすることができず、代表的なコンポーネントの値しかレコーディングすることができません。StaticMeshのVisibilitiyやTransformはレックできても、自前のブループリントアクターの変数や関数コールをレックできるわけではありません。

今回は、MIDIによって

* Materialのパラメータ
* LightのIntensity
* Niagara Systemのスポーン

を制御したいのですが、LightのIntensity以外はテイクレコーダーの対応がありません。コードを読み解いて改造することも手ですが、実際のスコープに対して現実的ではないので、ワークアラウンドがないかを検討しました。

MIDIをつかって目的の動作を達成するために、ここでは任意のアクターのパラメータ操作をレックして、それをあとからコピペして別のシーケンサートラックに持ってくる、というワークアラウンドを思いつきました。

例えば、2つのMIDIノートのアタックをとりたい場合、2つの任意のアクターを用意します。ここではキューブのStaticMeshを用意しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/2b6d331d-d0c5-49fb-31dd-25bd37098197.png)

先程の用意したBlueprintのNoteOnのイベント監視で、この2つのStaticMeshをアタック毎に可視性をトグルします。これをランタイムでレコーディングします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/bd05d57d-f169-67ca-79ed-e92ab747afdd.png)

テイクレコーダーでのレコーディングの手順は以下です。

* Windowメニューから Cinematics > Take Recorder を選択してパネルを表示
* 先程のキューブをレコーディング対象に追加（`+ Source`からLevel内のアクターを選択）
* ランタイムに入ったのち、レックボタンを押す

![Animation_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/4353800c-0a43-9661-2e1f-18f7a9e72c9b.gif)

ただ四角がピコピコするだけの絵ができただけですが、録画したシーケンサーを見てあげると、Visibilityのレーンが入っていることが確認できます。

## 3. レックしたアタックをEventトリガーに使う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/89305e7f-e2f9-4391-8a61-2fd28134eb58.png)

ここが今回の一番の重要なポイントなのです。できたVisibility変化はEventレーンに**コピペ**ができます。つまり、MIDIのアタックをレックして、シーケンサー上のトリガーEventを置くことができるわけです。

![Animation_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/d5c048b0-fc23-5655-9a18-c70baf3a8be1.gif)

バインドする関数をそれぞれのキーフレームに登録しないといけないところがめんどくさいですが、それぞれ登録せず（個数増えたら辛いので）、うまくコピペしてあげます。一つのキーフレームに関数をバインドし、もとのキーフレームの同一タイミングにグリッドする形でペーストしてあげます。

![Animation_4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76966/7b1c1cf1-3e73-52c3-27c0-7fa917aad7ab.gif)

これで任意の関数を使えるようになりました。勝利です✌
イベントレーンはブループリント含む任意なアクターの関数やイベントに対して有効になります。ランタイムで使っていたBP_MidiHandlerの関数をそのままシーケンサー上でバインドします。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">アドカレのネタ、外部のMIDIシーケンスをシーケンサーに焼く、というやつです <a href="https://t.co/ehp0GsLwAy">pic.twitter.com/ehp0GsLwAy</a></p>&mdash; Ayumu Nagamatsu (@ayumu_naga) <a href="https://twitter.com/ayumu_naga/status/1466854217222877186?ref_src=twsrc%5Etfw">December 3, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


利用シーン： [Neonify by Sertac TASDEMIR](https://www.unrealengine.com/marketplace/ja/product/neonify)