UE5+サウンドミドルウェアADXで、BGMに動的なドラムパートを（再生編）

# はじめに
アンリアルエンジンとサウンドミドルウェア「ADX for UE」を連携させ、パーカッションのないメロディラインに動的にドラムパートを追加する実装のチュートリアルです。

https://twitter.com/sleepyslowsheep/status/1605430553586458627?s=20&t=zOqb5VhKJcewl5Ke7lz6-A

ゲーム内のシチュエーションに合わせてパートを追加するだけでなく、細かな状況に合わせて使用する打楽器を変えてみたり、はたまたユーザーがドラムパターンを作れてしまう、といった活用も可能です。

当記事は過去記事「ADX2 for UE4で、BGMのテンポに合わせた演出を実装する」の実装法を活用して別アプローチをするものですが、この記事だけでも実装が可能かと思います。

https://qiita.com/SigRem/items/f0b633513eafd7a2e61d


# 前提

当記事ではUE5.0を使用しています。基本的にブループリントのみでの実装を想定します。
ADXはインディー向けの「LE版」であれば、無料で使用できます。
https://game.criware.jp/products/adx-le/

なお、ADX2は「ADX」へ名称が変更になりましたが、ツール構成は変更ありません（2がないから古いほう、というわけではありません）。

記事執筆時点のADX for UEのSDKバージョンはADX LE UE SDK(1.31.00.01)です。

ADX for UEの導入や基本的な使い方は以下の記事にあります。必要に応じて参照してください。
**ADX for UEの導入で、一歩上のサウンド表現を（導入編）**

https://qiita.com/SigRem/items/4250925f6d66a4fd287a

**ADX for UEの導入で、一歩上のサウンド表現を（実践編）**

https://qiita.com/SigRem/items/c089b71c42e898980a46


# 実装

## AtomCraftでサウンドを構成する

まずはサウンドオーサリングツール「AtomCraft」で、実装に使用するためのメロディとパーカッションを構成していきます。


### マテリアルの用意

プロジェクトを作成し、マテリアル（音源ファイル）をインポートします。
画像では分かりやすいようサブフォルダにメロディとドラムを分別しています。
![A01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4a7a0811-3ce5-7ace-6f6b-9dc786dd2541.png)
メロディパートについては、インスペクターにてループ情報の上書きを「True」、ループタイプを「ループ」にしループ再生されるよう設定します。
![A02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/a5f2c6bf-e64f-5fe4-f09c-e9be2a109500.png)


### メロディ用キューの作成

新規にキューを作成します。
キューシートを右クリックし「新規オブジェクト」→「キュー『ポリフォニック』の作成」です。
![A03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/80e58a7c-a3e2-acd5-5f47-08f7f9c7eaaf.png)
作成したキューへ、メロディとなるマテリアルをひとつだけ配置します。
![A04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/ae459a41-11f8-2e25-1e90-5145dbd82e42.png)

メロディのビートタイミングを取得できるようマーカーを作成します。
トラックリストの空欄で右クリックし、「新規オブジェクト」→「ビート同期情報の作成」を選択します。
![A05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/422ec22a-507f-9863-edef-1608196907bc.png)
BeatSyncマーカーが作られました。
![A06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/bb49262a-7277-4061-f8cd-a9f50dd0cfd7.png)
マーカーをクリックして選択しておき、インスペクターにてメロディのBPMを入力します。
![A07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e42353b4-b0e3-c625-b760-1005a4fe71b0.png)
今回は仮に2小節分のドラムパターンを演奏すると仮定し、分子を「8」と設定します。
![A08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/f17c94d6-ca4c-6547-924c-32d8e4c8a2b1.png)
インスペクターの「BeatSync」にてビートパターンをいじれたりするのですが、ここはUEで同じようなことをやっていくので触らずに置いておきます。
![A09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/44f666af-8b6d-1ce3-e3bc-6306a3fe8c65.png)
同じようにメロディひとつにつきひとつのキューを構成します。
![A10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/adace1fb-65cf-a71c-8f14-d45e0955894f.png)


### ドラム用キューの作成

ドラム用にも同じく「ポリフォニック」のキューを作成します。
![A11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/994e0095-1f12-12b1-32b9-53472930eee3.png)
こちらもキック、ハイハット、スネアなどのキューを作成し対応するマテリアルを入れていきます。
![A12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/5eb9abdc-23f0-3650-8f86-f5edd4feffa8.png)

ちょっとした余談ですが、キューのタイプを「ランダム」にするとひとつの打楽器からランダムな音を鳴らすことができます。少し変わった演出にも使えそうですし、微妙に異なるパターンのマテリアルをランダムで鳴らすことで「マシンガン効果」の軽減にも役立ちます。
![A16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/2a3ee3a4-0ca5-1331-f325-7e398aec50a1.png)
![A17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/27739bb8-e0bd-0d56-f5e4-018fea5c7d3a.png)
（この例ではキック、ハイハット2種、スネアが再生のたびにランダムに鳴ります）


### キューシートのビルド

ここまでできたらキューシートをビルドします。

![A14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/63afcbbc-6751-c024-dc90-1d1c73ed340d.png)
![A15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/6b67215a-90b1-fb52-8248-98e6ff015bfd.png)


## UEでの実装

ここからはUE5を起動して実装していきます。

### キューシートのインポート、サウンド確認

ビルドしたキューシートをインポートします。
生成されたacf、acbファイルをUEのコンテンツブラウザにドラッグアンドドロップするとインポートメニューが表示されます。
基本的にはそのままでOKです。
![B01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3ea57c35-508e-0ba6-beed-eebb5512ba96.png)
インポートしたキューがコンテンツブラウザに表示されました。
![B02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/94813a08-5146-969f-cdf2-434f88380383.png)
プロジェクト設定を開きます。
![B03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/533d84d7-81c4-c3f4-cfab-f8db8362dda2.png)
CriWareタブ内、「AtomConfig」でビルドしたacfファイルを指定します。
![B04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/9b54f301-a008-88d4-40e5-9ce7ecb1cd9a.png)
音声が再生されるかテストしてみましょう。
レベル上にメロディ用キューをドラッグアンドドロップします。
![B05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/224f33b6-64de-b583-de9d-e68239aa56a9.png)
ゲームを再生します。メロディが単体で再生され、ループするようになっているでしょうか？
![B06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/77520c77-af4a-0182-900b-d5c91d2c8f37.png)
確認が終わったら配置したキューを削除するか、「Auto Activate」のチェックを外して自動的に再生されないようにします。
![B07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/861ecfb5-aa74-a60c-f603-047fa5c567cd.png)


### BGM再生用のキューを作成する

メロディとドラムパートを再生するための専用のブループリントを作っていきましょう。
コンテンツブラウザの適当な場所で右クリックし、「Blueprint Class」を選択して新しいアクターを作成します。
![C01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/4b2d6cff-e4fe-bfcd-d97c-ce5b373e3346.png)
親クラスは「Actor」です。
![C02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/c3563481-a85a-912f-e952-d5ee00de34d7.png)
作成できたらダブルクリックして開き、「Atom Component」を追加します。
![C03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/95c9e422-2348-0483-c605-44b98983ae5d.png)
追加したコンポーネントを選択し、Detailsパネルにて初期値となるサウンドを指定しておきます。
うっかりサウンドを指定し忘れたときにエラーが出るのを防ぐためです。
![C04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/cb248dd9-7876-b650-f836-bf219cfd099c.png)
レベル上でサウンドを指定できるようにするため、Construction Scriptに移動します。
タブをクリックして切り替えます。
![C05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e1ed6dc8-2ef1-58fe-e5d2-90ab884673b6.png)
コンポーネントを**Get**し、**Set Sound**ノードでサウンドを指定します。再生するサウンドは変数から指定するので、空欄にしておきます。
![C06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/0e5308a6-253b-9f1d-b3b8-e67ac24e86e6.png)
**SetSound**ノードのアウトプットピン「New Sound」を右クリックして「Promote to Variable」で変数化します。
![C07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/124bb833-09f5-39fb-8fa7-910a8c037953.png)
新しく変数が作られます。「MelodySound」とでも名前をつけておきましょう。
![C08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/c3ec5fd3-07c7-4bfc-db1d-461e017a5edd.png)
My Blueprintパネルにて、作成された変数の目のボタンを押し外部からアクセス可能にしておきます。
![C09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/a63a0580-8b60-cded-381c-7f0e283c87f7.png)
アクターをレベルに配置すると、Detailパネルから「Melody Sound」が指定できるようになりました。
![C10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/3c6251e6-b682-9e82-503d-9da31199e454.png)



### bpmに合わせてドラムを鳴らす

静かなメロディにドラムパートを動的に追加していきます。
コンポーネントを**Get**し、
![D01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/52e66751-6044-4748-032b-78d5c8840da4.png)
線を引き出して**Assign On Beat Sync Callback**を選択します。
![D02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/a4007740-b9ce-9523-1d55-acdfe4f1c0ef.png)
ノードとイベントノードが配置されました。
これらはそれぞれ「bpmのタイミングに合わせてイベントを呼び出す」ノードと「呼び出される」イベントノードになります。
![D03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/1e2b4ec4-a369-c8bf-d326-f8ccc4224db3.png)
線をつなぎ、分かりやすい位置に並べ直します。
![D04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/eed0d03c-2795-5618-a5fe-5763194b61cb.png)
ドラムを鳴らすため、**Spawn Atom Sound 2D**ノードを置きます。「Sound」にはキック音を指定します。
![D05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/55bc353b-5999-dfaa-8ef9-50acf16dbaf1.png)
**Spawn Atom Sound 2D**ノードは「Params」ピンに再生情報が必要なので、線を引き出し**Make AtomComponentParams**を配置します。
![D06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/ef10f716-5400-8f75-4658-0f002e06338f.png)

ゲームを再生してみましょう。メロディのテンポに合わせてキック音が再生されているのが分かるでしょうか？




### 裏拍を追加する

キックを鳴らすのと平行して、裏拍にハイハットの音を鳴らしリズム感を追加していきます。

まずはイベントノードの「Beat Sync Info」アウトプットピンからビートの同期情報を取り出します。
線を引き出し、**Break Atom Beat Sync Info**ノードを作ります。
![D08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/0a33ca75-c88a-482a-74a2-7a2d3967d278.png)
現在何拍目か、bpmなどの情報が取得できます。
ビートタイミングから裏拍までの時間は**60÷bpm÷2**で求めることができます。
![E01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/fc348492-3cee-139a-d8fd-7f677594f4da.png)
**Delay**ノードで裏拍までの時間を待機し、ふたたび**Spawn Atom Sound 2D**ノードを使いハイハットを鳴らします。
![E02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/31684699-a305-5cc4-cbb8-40d55661ee2b.png)




### 任意で再生を開始する

現状ではゲームの再生と同時にメロディの再生が開始されますが、これを任意のタイミングで開始できるようにしてみましょう。
アクター内のAtomコンポーネントを選択し、Detailsパネルで「Auto Activate」のチェックを外します。
これでAtomコンポーネントのメロディキューが自動的に再生されなくなりました。
![F01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/7fed146a-8ae2-dad0-28c9-521bc76b639a.png)
カスタムイベントを作成し、コンポーネントを**Play**ノードを使って再生します。
![F02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/ec6fe5cf-f3c5-308a-eb63-4c702b878894.png)
**Bind Event to On Atom Beat Sync Callback**を使ってのビートタイミングとイベントの紐づけは、メロディの再生開始時に行われるようつなぎ直します。
![F03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/00314539-b629-f90a-ff63-50f1d79a761f.png)

**レベル上でこのアクターを選択しておき**、レベルブループリントを開きます。
![F04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e139a5e0-5c48-b371-8a80-deb0b1b80ab5.png)
イベントグラフの空欄で「Create a Reference to （アクター名）」を選択し、リファレンスノードを作ります。
![F05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/e71b9ce7-21ee-ab1a-f3a5-67ce642b0b9a.png)
**Input Key 1**イベントからカスタムイベントを呼び出せば、キー入力により再生が開始されます。
![F06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154452/ca11e472-f39c-1dfd-794d-474d850cf7b1.png)


これで基本的な動的ドラムが実装できました！
効果的なタイミングでドラムパートを徐々に追加していく、変化していくなどの演出を使いゲームを盛り上げてみましょう！

この記事をベースに、ドラムパターンをプログラムしたり打楽器の差し替えを行う実装についての記事を公開しました。

https://qiita.com/SigRem/items/53dad491f0430f4a3e9f

より柔軟なインタラクティブ要素が追加できるようになるかと思いますので、よろしければ参照してみてください。