ゲームの状況に合わせてサウンドエフェクトのかかり具合を変える


この記事は「ゲームの銃撃音バリエーションを増やしつつコード量を減らす」https://qiita.com/Takaaki_Ichijo/items/fced234c2aca996f9fd5
の続編です。

また、本記事はADX2及びAtom Craftの触り方をある程度理解している方向けの解説です。
初めてADX2を使う、という方は各エンジンへの導入の記事を先に参照ください。

Unity: Unityのサウンド機能をADX2で強化する
https://qiita.com/Takaaki_Ichijo/items/16e6501fc07f5b3b3377

UE4: ADX2 for UE4の導入で、一歩上のサウンド表現を(導入編)
https://qiita.com/SigRem/items/4250925f6d66a4fd287a

音にゲームの場面に沿ったエフェクトをかける with ADX2

たとえば映像作品の劇伴や効果音を考えてみたとき、それらの音に対して残響などのサウンドエフェクトをかける場合は、エフェクトを掛ける箇所を決めておいて静的に処理、波形ファイルに出力します。

しかしながら、「ゲーム」は常に状況が変わっていくコンテンツです。プレイヤーの入力に合わせてキャラクターなどが自在に空間を移動し、演出として使いたい音のエフェクトもどんなタイミングで必要になるか決まっていません。

通常、UnityやUE4などのゲームエンジンやネイティブ開発において、「ゲーム内の状況に合わせてエフェクトを変えよう」と思ったとき、ゲーム側にゲームの環境を示すパラメータを持っておき、その数値を参照しつつ「この音素材を再生、このエフェクトをオンにする」といったようなコーディングになります。
そうした処理を作る過程は厄介ですし、音がどんな鳴り方をするかテストを行うことも難しいです。

そこで本記事では、ゲーム開発向けサウンドミドルウェア「ADX2」の機能を使って、こうした「場面に沿ってエフェクトのかかり具合が変わる」ゲームの効果音を構築してみます。

ADX2 LE
https://game.criware.jp/products/adx2-le/

ADX2における通常のエフェクト設定手順

状況に合わせてエフェクトを変化させる。。。の前に、鳴らすたびに毎回一定のエフェクトがかかる音をADX2で作っていきます。

エフェクトの掛かり具合が固定の音は、波形編集ソフトなどで元素材にそのままエフェクトをかけてしまって単純に鳴らしても構いませんが、ここでは後々リアルタイムにエフェクトの掛かり具合を切り替えるので、ランタイムで処理をさせる手順を説明します。

ゲームエンジンやサウンドミドルウェアで使用できるサウンドエフェクトには、ゲーム機やスマホの上で動かすには処理が重いものが多いです。リバーブ、エコーなどは、音ひとつひとつに適用することはCPUを食いすぎて現実的ではありません。そこで、重いエフェクトについては複数の音を一括して処理する方法をとります。

エフェクトをかける/かけないでルーティング(信号処理の経路)を分け、そのルートへどのくらいのレベルで信号を通すかによってエフェクトの掛かり具合を調整します。
Unityの標準機能であればAudio Mixer Groupによるエフェクト処理、UE4であればSound MixのSound Mix Moditierなどで処理する箇所です。

ADX2の場合は、「DSPバス」という機能で一括したエフェクト処理を行います。ADX2のツール「CRI Atom Craft」で、リバーブの処理を行うバスを用意していきます。

Atom Craftでリバーブの「バス」を用意する

Atom Craftを立ち上げ、「ミキサー(DSPバス設定)」ウィンドウを開きます。
なにもないところで右クリックをすると、「DSPバスを追加」右クリックメニューが開きますので、コレを選択して「バス」を作ります。

「BUS1」という名前のバスができました。ここを通った音はリバーブがかかるようにします。「エフェクト+」の+をクリックして、表示されたエフェクトの中から「リバーブ」を選びます。

このままでは最終出力音声に反映されません。下の「センド +」で、このバスで処理した信号が次にどこのバスにつながるかを指定します。
この場合はMasterOut、つまり最終出力にそのまま流したいので、「+」をクリックして「MasterOut」を選択します。

続いてキュー(ADX2のサウンド再生単位)がルーティング先として選択できるバスの一覧である「バスマップ」を設定します。

バスマップは複数作成できますが、とりあえずデフォルトで存在するBusMap_Defaultに今作ったリバーブ用のバス「BUS1」をバス名1に設定します。
これでリバーブ処理の前準備ができました。

キューの信号が「バス」を通るように設定する

各キューでエフェクトを適用するには、まずキューのインスペクターで「バスセンド」タブを選択します。

ここで、先程設定したバスマップ「BusMap_Default」を選択し、BUS1のチェックボックスを入れます。F5キーを押してプレビュー再生を行うと、このキューにリバーブ処理がかかっていることが確認できます。
リバーブのかかり具合(どのくらいリバーブ用のバスに信号を送るか)は、スライダーで設定できます。

これで、音に対して決め打ちのエフェクトを設定できるようになりました。

音の設定を切り替える「ラベル」を設定し、ゲーム側から状況によって切り替える

さて、本題です。ADX2では、音に対して再生設定を複数持ってラベルを貼っておき、音の再生時にラベルを指定することでパラメータを切り替える機能があります。これを「セレクタラベル」と呼びます。
プログラムから直接バスセンドの量を変更してエフェクトのかかり具合を変えることももちろん可能です。単に「リバーブをオン・オフする」だけならばスクリプトから直接指定したほうが早そうです。

しかし、セレクタラベルの真価は「複数パラメータの組み合わせに名前付けできる」点にあります。
異なる音素材・エフェクトなどの組み合わせをラベルひとつで指定できるわけです。これにより、「このゲーム状況の場合はこの音にこのエフェクトを掛けて、ボリュームはこれで、ピッチはこれで...」というパラメータ情報をゲームスクリプト側に持つ必要がなくなります。

セレクタとセレクタラベルの設定

まずは、切り替え用の「セレクタラベル」をAtom Craftのプロジェクト内で定義します。
プロジェクトツリー最下部の「セレクタフォルダ」を右クリックし、「セレクタの作成」を選択してください。
今回はリバーブを切り替えるためのラベルを定義するので、「Reverb」という名前にします。

作成したセレクタを右クリックし、「セレクタラベルの作成」を選択します。リバーブの音とオフを示す「On」ラベルと「Off」ラベルを作ります。

ラベルによって設定が切り替わるキューを作る

次に、キュー側の準備をします。エフェクトの掛かり具合を二種類用意するため、同じキューをコピーしてリバーブ有りとなしのキューとします。リバーブ有りの方だけ、バスセンドでリバーブを設定した「BUS1」に信号を送る設定をしておきます。

これら2つのキューを内包したキューを作成します。空のキューを作って、先ほど作成したリバーブありとなしのキューをドラッグアンドドロップします。
そのまま2つのキューを内容したキューを鳴らすと、当然ながら2つ同時に再生されます。

このキューに先ほど作成したセレクタラベルを適用して、プログラムから鳴らすトラックを選べるようにします。
キュー内のトラック下部をクリックし、セレクタ「Reverb」を選択します。

リバーブ適用トラックに「On」、非適用トラックに「Off」を選びます。この設定はインスペクターの「セレクタ」タブからも確認できます。

セレクタ設定を行ったキューの動作確認をする

F5キーによるプレビュー再生では「セレクタ」の設定を確認できないため、セッションウィンドウを立ち上げて挙動を確認します。メニューの「表示」からセッションウィンドウを開き、作成他キューを下部の「Player1」枠にドラッグアンドドロップします。

ここで中央の「セレクタ」タブを選択します。すると、キューに設定しているセレクタが表示されますので、チェックボックスをオンにして、ラベルを選びながらプレビュー再生をします。

このとき、F5キーではなく「トランスポート」欄の再生ボタンをクリックするか、自動的に割り当てられたショートカットキー(最初のキューは「1」キー)を押してプレビュー再生します。
On,Offを切り替えるたびにエフェクトがオン・オフされます。

プログラムからセレクタラベルを指定して再生する

ゲーム側で「ラベル」を指定して再生します。

Unityの場合

CriAtomSourceクラスメンバのCriAtomExPlayerクラスにああるSetSelectorLabelメソッドで切り替えます。

PlayGunShot.cs

public class PlayGunShot: MonoBehaviour 
{
    public CriAtomSource atomSource;
    public CriAtomExAcb acb; //再生するキューが入ったキューシート

    public PlaySniperRifleShot(string isEnableReverb)
    {
         atomSource.player.SetCue(acb, "SniperRifle_Shot");

         var label = isEnableReverb ? "On":"Off";
         atomSource.player.SetSelectorLabel ("Reverb",label);
         atomSource.Play();
    }
}

UE4の場合

ブループリントAPI「Atom Component」の「Set Selector Label」ノードを使います。

セレクタラベルの活用場面

  • キュー「足音」を用意しておき、「木の上を歩く足の音」と「草の上を歩く足の音」など材質に応じて音声を切り替える、
  • キュー「被弾時のダメージボイス」を用意しておき、プレイヤーの残りHPに応じて再生する音声を切り替える
  • キュー「武器を振る音」を用意しておき、「地上」と「水中」のラベルをつけて、後者にはフィルタがかかる設定にする

セレクタラベルを活用することで、スクリプト側で管理しなくてはならない再生パラメータを大幅に減らすことができます。
より複雑なパラメータの組み合わせの変化をスクリプティングの負担を変えずに導入できます。いろいろなところで活用してみましょう。