Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What are the problem?

posted at

updated at

Organization

ADX2 for UE4で作る、インタラクティブミュージック中のクォンタイズ機能

はじめに

アンリアルエンジン4とサウンドミドルウェア「ADX2 for UE4」を連携させ、インタラクティブミュージックの要素である「クォンタイズ」を実装してみます。
自分で音楽を奏でられる遊びや、ゲーム内の演出や音をBGMのタイミングに合わせたりといった演出を作ることができます。

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

記事執筆時点のADX2 for UE4のSDKバージョンはv1_29です。

前提

ADX2 for UE4の導入や基本的な使い方は以下の記事にあります。必要に応じて参照してください。
ADX2 for UE4の導入で、一歩上のサウンド表現を(導入編)
https://qiita.com/SigRem/items/4250925f6d66a4fd287a
ADX2 for UE4の導入で、一歩上のサウンド表現を(実践編)
https://qiita.com/SigRem/items/c089b71c42e898980a46

クォンタイズとは

楽曲制作において、クォンタイズはばらばらに配置された音符(ノート)を楽曲に合わせたテンポに配置する機能のことです。
本来無段階に鳴らすことのできるサウンドに最小単位を設け、それに沿って再生することで音楽として成立させます。

ImageA.png

インタラクティブミュージックにおいてもクォンタイズは有効です。
ゲーム中に再生するサウンドを保留しキューに入れておき、BGMのテンポに合わせて実際に再生を開始することで両者を統一させ、まるで最初からひとつのサウンドだったかのように聞かせることが可能です。

ImageB.png

今回の記事の実装を試したいけど手頃な音声素材がない……という方のために、1フレーズではありますが素材を用意しましたのでご利用ください。
https://github.com/SigRem221/adx2forue4-booksample/tree/master/ADX_QuantizeSample

実装

AtomCraftでサウンドをセットアップする

マテリアルのインポート

AtomCraftにサウンド素材となるマテリアルをインポートします。
扱うファイルが多くなるため、用途に合わせてフォルダ分けしておくと便利です。
「マテリアルルートフォルダー」を右クリックし、「新規オブジェクト」→「マテリアルフォルダーの作成」でフォルダが作成できます。
A00.png
画像ではドラムループ、ピアノパート、リード、ストリングスに分けてあります。

A01.png
フォルダごとに素材を振り分けてインポートしました。
A02.png
ループする素材についてループ情報の上書きを行います。
マテリアルを選択し、インスペクターにてループ情報の上書きを「True」に、ループタイプを「ループ」にします。
A03.png
これでドラムループが自動的にループ再生されるようになります。

ドラムループパートの作成

楽器パートごとにキューを作成します。
まずはドラムループです。
キューシートのワークユニットを右クリックし、「新規オブジェクト」→「キュー『ポリフォニック』の作成」を選択します。
A04.png
オーソドックスなキューが作られるので、ドラムループ素材をキューに入れます。

次にビートのタイミングをUE側で取得できるよう、ビート同期情報を設定します。
トラックリストの空欄で右クリックし、「新規オブジェクト」→「ビート同期情報の作成」を選択します。
A05.png
「BeatSync」という表示が追加されました。
A06.png
ビートの情報を設定するには、楽曲のBPMの値が必要です。
BPMが分からない場合、対象のマテリアルを右クリックして「BPM解析」を選択します。
A07.png
ログに「BPM "142"」という表示がされ、楽曲のBPMが142であることが分かりました。
A08.png
キューの「BeatSync」を選択し、インスペクターにてBPMに「142」を入力します。
A09.png

必須ではありませんが、分かりやすいようタイムラインの表示単位も変えておくと役立ちます。
トラックリストの上にある時計の右の逆三角をクリックし、「タイムベースの編集」を開きます。
A10.png
ここのBPMにも「142」を設定しておきます。
A11.png
タイムライン表示が楽曲のテンポに合わせられました。
次の画像ではちょうどいい場所で曲がループしているのが分かります。
A12.png

クォンタイズする楽器パートの作成

次にピアノやリードなどの楽曲パートのキューを作成します。
キューシートを右クリックし、「新規オブジェクト」→「キュー『ランダム』の作成」か「キュー『ランダムノーリピート』の作成」を選択します。
これらの違いは何度もランダムなトラックを再生した際に、「同じトラック」を続けて再生するかどうかです。
A13.png
作成されたキューに対して、1トラックにひとつずつマテリアルから対応する素材を入れていきます。
A14.png
試しに再生してみましょう。毎回違うトラックがランダムで再生されるはずです。
A15.png
リード、ストリングパートに対しても同じようにキューを作成します。
A16.png
これらもマテリアルの数だけトラックを持つことになります。
A17.png

キューシートのビルド

ここまででひとまずAtomCraftでの作業は完了です。
ツールバーからキューシートをビルドします。
A18.png
複数のキューシートを作成した場合、すべてのキューシートにチェックがついていることを確認してください。
チェックがついていないキューシートはビルドされません。
A19.png

UE4でクォンタイズを実装する

キューシートのインポート

AtomCraftでビルドしたacf、acbファイルをUE4のコンテンツブラウザにドラッグアンドドロップし、インポートします。
ワークユニットやキューシートが複数ある場合、acbファイルも複数出力されています。すべてインポートしてください。
B01.png
B02.png
ツールバーの「Edit」→「Project Settings」からプロジェクト設定を開きます。
B03.png
「CriWare」タブにて、「AtomConfig」に先ほどインポートしたacfファイルを指定します。
B04.png

サウンドの配置

ドラムループのキューをレベル上にドラッグアンドドロップして配置します。
B05.png
配置したキューを選択しておき、「Blueprint」→「Open Level Blueprint」でレベルブループリントを開きます。
B06.png

ブループリントからビート情報を取得する

イベントグラフ上で右クリックして「Create a Reference to (キュー名)」を選択し、リファレンスノードを作成します。
B07.png
リファレンスノードから線を伸ばし、Get Atom Componentを選択して配置します。
B08.png
Get Atom Componentからさらに線を伸ばし、「beat」と検索して出てくるAssign On Atom Beat Sync Callbackを選択すると、ふたつのノードが配置されます。
B09.png
自動的に作られたカスタムイベントに適当に名前をつけておきます。
B10.png
Event Begin PlayノードからBind event to On Atom Beatに線をつなげます。
B11.png
これでビートごとにイベントが走るようになりました。
テスト用に文字を表示してみます。
カスタムイベントから線を伸ばし、Print Stringノードでデバッグメッセージを出します。
B12.png
実行してみると、ウィンドウ左上にドラムのテンポに合わせてメッセージが表示されます。
B13.png
合わせてサウンドも鳴らしてみましょう。
「atom 2d」と検索し、出てきたSpawn Sound 2Dノードを配置します。
Spawn Sound 2DノードはUE4標準のものとADX2 for UE4によって追加されたノードの2種があるので、取り違えないようにしましょう。
B14.png
ピアノ用のキューを指定して、ゲームを再生するとドラムに合わせて絶え間なくピアノの音が鳴ります。
B15.png

サウンドのクォンタイズ

各楽曲パートをゲーム中にクォンタイズし、再生する処理を作っていきます。
パートごとに入力を受け取れるよう、変数を追加しましょう。
今回はシンプルな例として、Bool型変数をパートごとに作成しています。
B16.png
Input Keyイベントノードで1,2,3キーが押されたことを感知し、対応する変数をTrueにします。
B17.png
カスタムイベントから線を伸ばし、入力によって変数がTrueになっていた場合、サウンドを再生して変数をFalseに戻す処理を書きます。
これでビートごとに楽器キーの入力判定と再生が行われることになります。
B18.png
パートごとに同じ処理を作ります。Sequenceノードを使うと処理を順番に書けるため、グラフが分かりやすくなるのでおすすめです。
B19.png

さて、ここで一度テストプレイしてみましょう。1,2,3キーを押すと次のビートタイミングで楽器が演奏されるはずです。
しかし、サンプルのストリングスパートは少し尺が長いため、連続で押すと重なって演奏されてしまい、不自然に感じます。

演奏タイミングをパートごとに設定する

解決方法は簡単です。
カスタムイベントの「Beat Sync Info」から線を伸ばし、Breakノードをつなげるとビート同期情報の分解ができ、必要な情報を取り出すことができます。
B20.png
Break Atom Beat Sync Infoノードの「Beat Cnt」からは小節内で現在何ビート目のタイミングかを受け取れます。
試しに「Beat Cnt」をPrint Stringノードにつなぎ、メッセージとして出力してみます。
B21.png
ビートのカウントは0から始まり、4つめのタイミングでまた0に戻ります。小節内のビート数が正しく取得できているのが分かります。
B22.png
これを踏まえて、ストリングスの再生処理にBranchノードを噛ませます。
条件を「Beat Cnt == 0」とすると、各小節の始めのみにストリングスの演奏判定が行われることになります。
B23.png
この状態でテストプレイすると、ストリングスの音は重ならずに演奏されるようになっているはずです。

さらに演出を追加する場合や、ユーザーの入力体験を高める方法もまとめていますのでこちらの記事も参照してください。
ADX2 for UE4でつくるクォンタイズ(テクニック補完編)
https://qiita.com/SigRem/items/207ef9c8b70c1cc798b0

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What are the problem?