今日は、ゲーム世界内に盗聴器を設置するという、盗聴システム付き「極秘スパイ」ゲームの開発を考えてみます。オーディオを盗聴器、つまりバーチャルマイクで現場でキャプチャーして、張り込み車両まで無線で送信します。張り込み車両のワゴン車で待機するプレイヤーは、盗聴器を設置した部屋の様子をリアルタイムで聞くことができます。マイクでキャプチャーしたオーディオは、ワゴン車内にあるバーチャルラウドスピーカーで再生されます。このラウドスピーカー自体も仮想空間にある、スペーシャリゼーションしたサウンドエミッターで、その音源は、たまたま同じレベルの別の場所で発生中のサウンドのミックス、というわけです。このミックスにfutzエフェクトを適用して信号のlo-fi送信やスピーカーを通る時のディストーションを真似る、という凝りようも見せましょう。
Wwise 2017.1で初めて、複数の3D音源の入力をミックスした後に、オーディオ信号に3Dスペーシャリゼーションを実行できるようになりました。このスペーシャリゼーションされたサブミックスを、「3D-Bus」と呼びます。今回は、Wwise 2017.1の3Dバスを活用して上記のゲーム動作をシミュレーションする方法を説明します。このシナリオを通して、Wwise 2017.1のオーサリングツールとサウンドエンジンの両方の新機能や変更点をいくつか、紹介します。記事を読めば、ここで紹介したコンセプトを他のオーディオルーティングのシナリオに適用できるようになり、最後に記載する例題も試せるでしょう。
ゲームオブジェクト
今回の例では、最低4つのゲームオブジェクトを登録します。Wwise 2017.1ではリスナーもゲームオブジェクトとなり、ゲームオブジェクトはリスナーにもエミッタ―にもなれます
- Player Listener: このゲームオブジェクトは、ゲーム内でオーディオを聞いているキャラクターの「耳」を表します。今回の例では、張り込み車両の中でリアルタイムに収録に耳を傾けるキャラクターのことです。
- Environmental Sound Emitter: サウンドを発信するゲーム内のオブジェクト。敵のキャラクターかもしれないし、張り込み中のスパイチームが関心を示すような他の音を発信するオブジェクトかもしれません。実際にはゲーム内にこのようなオブジェクトを豊富に用意してリッチな環境を作り上げますが、今回の例ではシンプルに1つだけとします。
- Microphone: このオブジェクトは、隠されたマイク、つまり盗聴器を表しています。このオブジェクトの位置が重要ですが、マイクが集音する音は、一定の範囲内にある、音を発信するゲームオブジェクトに限られ、これはActor-Mixer Hierarchyの減衰カーブで決まります。
- Loundspeaker: マイクが集音した音のミックスをスペーシャリゼーションしたものを発信する、サウンドエミッタ―のゲームオブジェクト。スピーカーの位置が、音の再送信の位置を表します。この例ではスピーカーが音源からかなり離れた張り込み車両の中にあります。もしスピーカーが音源に充分近ければ、Player Listenerに、スピーカーの音と元の音源の両方がミックスされて同時に聞こえるはずです。
リスナーとエミッタ―の関係
ListenerとEmitterの関係は、コードでSetListener APIとSetGameObjectAuxSendValues APIを使って定義します。これらのAPIでゲームオブジェクト間の関係が定義され、どのゲームオブジェクトが、どのゲームオブジェクトのリスナー(聞き役)なのかが決まります。Wwiseでゲームオブジェクトがエミッタ―なのかリスナーなのかを区別するのは、APIを使って定義されたリスナー・エミッタ―の関係だけです。
今回の例では、以下のような関係とします:
- Environmental Sound EmitterとLoudspeakerのListenerは、Player Listenerです。
- MicrophoneのListenerは、Loudspeakerです。
- Environmental Sound EmitterのListenerがMicrophoneとなっていて、アサインするのに使われたのが、SetGameObjectAuxSendValues APIです。‘aux send’のリスナーとして設定してWwiseプロジェクトの特定バスを指定することで、Wwiseオーサリングツールでマイクの動作を模倣します。
エミッタ―とリスナーの関係が正しく設定されたか確認するには、Advanced ProfilerのEmitter-Listenerタブを開きます。Environmetal_Sound_Emitterの内容を見ると、Listenerに設定されているのがMicrophone で、送信先のBusはMicrophone、そしてRouting Typeが“Game-defined”となっています。Routing Typeが "game-defined" なので、エミッター・リスナーの関係や出力バスなどがgame-defined sends APIを使って確定されたことが分かります。一方、Routing Typeが“user-defined”であれば、出力バスを定義するのはWwiseプロジェクトです(Master-Mixer Hierarchyの出力バスは親バスであり、Actor-Mixer Hierarchyの出力バスはGeneral Settingsタブに表示されます)。Routing Typeが"user-defined"の時はBus列は空欄となり、これはゲームオブジェクトのボイスやバスの数が不明であり、それぞれのボイスやバスに独自の出力バスがプロジェクト側(つまりユーザー側)で定義されるからです。Listenerゲームオブジェクトを関連付けるのは、Routing Typeが"user-defined"の場合はSetListeners APIで、EmitterとListenerの関係性をWwiseプロジェクト内で確立する方法はありません。
Wwiseプロジェクトを設定する
WwiseプロジェクトのActor-Mixer HierarchyやMaster-Mixer Hierarchyが、ランタイムに作成されるボイスパイプラインのテンプレートとなります。Wwise 2017.1では、サウンドエンジン内のバスインスタンスは必ずゲームオブジェクトに関連付けられていますが、プロジェクト内で定義したルーティングは、そのまま認識されます。Enable Positioningのチェックボックスは特に注目すべきで、親バスや出力バスのインスタンスをスポーンする対象が同ゲームオブジェクトなのか、アサインされたリスナーの定義に基づく別のゲームオブジェクトなのかが、これで決まります。
- まず最初にLoudspeaker用バスを作成して、その設定でEnable Positioningを有効にします。これでLoudspeakerバスのこのインスタンスが3D空間内で固有の位置を持てるようになり、その位置はLoudspeakerゲームオブジェクトの位置で決まります。さらにEnable Positioningにチェックが入っていれば、リスナー毎にバスを親バスの別のインスタンスに接続すべきだと、サウンドエンジンに伝わります。今回の例ではLoudspeaker ゲームオブジェクトに対応するListenerはPlayer Listenerだけで、Loudspeakerバスの親バスは、Master Audio Busです。ランタイムに、Loudspeakerゲームオブジェクト上でスポーンしたLoudspeakerバスのインスタンスが、Player ListenerゲームオブジェクトのMaster Audio Busのインスタンスと、接続します。
- Loudspeakerバスのポジションタイプは、3Dにします。これを受けてWwiseは、Loudspeakerバスと下流のゲームオブジェクト(Player Listener)との相対関係に基づいて、Loudspeakerバスの出力をスペーシャリゼーションします。減衰としてLoudspeaker Attenuationを作成してアサインして、Loudspeakerの音がどれくらいの距離まで伝わるかを定義します。LoudspeakerバスのPositioningタブは、このようになります:
- それらしく聞こえるようにマイクやラウドスピーカーからくる伝送ロスやディストーションの様子をシミュレーションして、LoudspeakerバスにWwise Guitar Distortionエフェクトを加えてもいいでしょう。このエフェクトの具体的な設定は、読者の練習用に、または読者の知り合いの優れたサウンドデザイナー向けの練習用に残すとして、ここでは省略します。
- マイクのシミュレーションには、Loudspeakerバスの子になるAuxiliaryバスを作成します。Auxiliaryバスにした理由は、マイクが集音するかもしれない全てのゲームオブジェクトのGame-defined sendの対象としてアサインできるようにするためで、前述のEnvironmental Sound Emitterもその1つで、これに含まれます。 バス階層は、大体以下のようになります:
- MicrophoneのAuxiliaryバスでもEnable Positioning チェックボックスにチェックを入れますが、ポジショニングは2Dを選択します。Enable Positioningをチェックする理由は、Microphoneバスのインスタンスをあるゲームオブジェクト(別名Microphone)に対してスポーンさせ、その位置は3D空間内として、下流のゲームオブジェクトであるLoudspeakerと異なる位置とするからです。この小さなEnable Positioningチェックボックスは、重要です!下流バスのLoudspeakerを、別のゲームオブジェクト(別名Loudspeaker)に対してスポーンすべきだと、Wwiseに伝えるからです。
- ポジションタイプを2Dとしたのは、Microphoneバスの出力をLoudspeakerとの位置関係でスペーシャリゼーションしたくないからです。ここでシミュレーションするのはマイクとラウドスピーカーの間の電子信号であって、物理的な振動ではないからであり、マイクとラウドスピーカーの相対的な位置の物理的な距離が、音のパンニングや減衰に影響しないでほしいからです。このバスに減衰は使われていません。
- Actor-Mixer Hierarchyで、マイクが集音してラウドスピーカーに再送信できる再生音が少なくとも1つ、必要です。Actor-Mixerオブジェクトを1つ作成して、その下の複数の子が同じプロパティを共有できるようにします:
- ここで唯一気を付けないといけないのは、‘Use game-defined auxiliary sends’チェックボックスにチェックを入れることです。そうすれば、マイクのゲームオブジェクトやAuxiliaryバスへのルーティングを、auxiliary sends APIを使ってゲームコードで定義できます
- ‘Environmental Sound’オブジェクトのPositioningタブを開いて、Enable Positioningにチェックが入っていてポジションタイプが3Dであることを確認します。これで、音がゲームオブジェクトの位置を使ってワールド内に配置され、出力がリスナーの位置との相対関係に基づいてスペーシャリゼーションされます。今回の例では、Eventが Environmental Sound Emitterのゲームオブジェクトに送信され、そのリスナーはAuxiliaryセンド経由のマイクと、出力バス経由のPlayer Listenerの両方です。.
イベントを設定してSoundBanksをビルドしてゲームでイベントを送信したあとに、Voice Graphを見れば、ルーティングが正しいかを確認できます。
Wwise 2017.1のVoice Graphは、ルーティング関連の問題をトラブルシューティングできるパワフルなツールです。相互関係を強調するために、ゲームオブジェクトは、グループサウンドやバスオブジェクトを一緒にまとめたボックス内に表示されます。例えば上図では、サウンド‘Environmental_Sound’が“Environmental_Sound_Emitter”ゲームオブジェクトで再生中です。また、Auxiliaryバス“Microphone”が同名のゲームオブジェクトで再生され、バスの“Loudspeaker”も、やはり同名のゲームオブジェクトで再生されています。そして連鎖の最後で、“Player_Listener”ゲームオブジェクトにあるのはMaster Audio Busの単一のインスタンスです。
最終的なゲームオーディオは、この4つのゲームオブジェクトの位置と、ゲームオブジェクトで再生されたりミキシングされたりする様々な音に対して定義される減衰によって左右されます。実際、シナリオの結果は直感的に予想されるものと一致して、もしPlayer ListenerがLoudspeakerの近くにあれば、Microphone内にミキシングされたサウンドが聞こえ、もしPlayer ListenerがEnvironmental Sound Emitterに近ければ、直接音が聞こえるだろうし、最後にMicrophoneは、Environmental Sound Emitterの音を拾えるように、充分近くなければなりません。
最後に、Wwise 2017.1の新3Dバスアーキテクチャの使いこなし方として、他の用例を紹介します。今回の記事で学んだことを元に、このようなシナリオをあなたのゲームでも作成してみてください。
音響ポータル
スペーシャルオーディオに重点を置いたバーチャルリアリティゲームを作成していると仮定します。音響現象をリアルにシミュレーションして、その感覚を維持する必要があります。隣の部屋から聞こえてくるリバーブサウンドを、リスナーに聞こえるようにしたいとします。室内の全てのサウンドがミックスされ、リバーブユニットに入力され、そしてエフェクトの出力をスペーシャリゼーションして位置を決めることで、まるでドアから聞こえてくるようにできます。新しいWwiseの3Dバスアーキテクチャを使えば、これが可能なのです。
アーリーリフレクションや、その他のエフェクト
時々、ボイス毎にエフェクトを適用するのは重すぎるけれど、共通のバスにセンドエフェクトとして適用すると大雑把過ぎる、ということがあります。そこで、サウンドエミッタのゲームオブジェクト毎にバスのインスタンスを作成して、それに対してエフェクトを適用します。スペーシャリゼーションはサブミックスの下流で行うか、場合によってプラグインでまかなえるかもしれません。Wwise Reflectはこの方式を採用してWwiseの3Dバスアーキテクチャを利用して、サウンドエミッタ毎に、固有のアーリーリフレクションのセットを生成します。アーリーリフレクションは、Reflectプラグイン内で、リスナーのポジションに相対的な位置でスペーシャリゼーションします。
サウンドをクラスターに集めて無駄を省く
複雑なRTPCシステムによって1つ1つが変化するような多数のサウンドで構成された、ビークル(車両)サウンドがあったとします。構成サウンドはそれぞれ、ビークルの物理的に異なる場所で発生するサウンドなので、サウンドエミッタに個別のゲームオブジェクトを使います。ただ、各エミッタで別々のエフェクトやスペーシャリゼーションを適用するのは負荷が高いので、できればリスナーが近場にいる時だけ実行したいとものです。もしリスナーとの距離が充分にあり、微妙な角度の変化が聞き取れないような状況であれば、まず最初に全てのサウンドをミックスしてから、サウンドのグループに対して処理したりスペーシャリゼーションしたりします。Wwiseの3Dバスアーキテクチャのおかげで、このような柔軟な対応ができます。
コメント