ドップラー効果は、波源に対して相対的に移動する観測者が観測する、周波数の変化です。これはどのような波の伝播でも発生する物理現象で、音波も例外ではありません。ゲームオーディオ業界の発展に伴い、多くのゲームエンジンが独自のドップラーソリューションを実装するようになりました。UnityやUEも、ドップラー効果をつくり出すオーディオ機能を導入しています。ところが、このような機能はゲームエンジン内でしか利用できず、Wwiseとのやり取りがないので、Wwiseを使ってゲームオーディオを開発中に利用できません。
最近、Wwiseでドップラー効果をつくる方法を調べ、UE4とWwiseを組み合わせて、調査内容を検証するためのデモプロジェクトを作成し、その過程で両者のドップラー効果を比較しました。では、その成果を見て、聞いてください!
Wwiseで作成するドップラー効果
デモで、ドップラー効果なしの場合、UEのドップラー効果を適用した場合、そしてWwiseのドップラー効果を適用した場合を確認してください。
ご覧の通り、音の表現力が大きく違います。ドップラー効果がないと、動きの速ささえも感じ取ることができません。一方、UEとWwiseのドップラー効果を比較しても、音色はほとんど変わりません。ただし、UEではリスナーの位置をカメラの上ではなくプレイヤーキャラクターの上にしたので、パンニングの幅が狭くなっています。これは、UEとWwiseでプレイヤーの位置の計算を統一して、カメラの動きがドップラー効果に影響しないようにするためです。
さて、どのような仕組みになっているのか?UEとWwiseのオーディオ設定を説明します。
図1.1 UEでドップラー効果を設定
UEでは、Dopplerノードを追加するだけでドップラー効果を作成できます。
図1.2 Wwiseでドップラー効果を設定
Wwiseでは、RTPCを作成して、対象音がすべて、Dopplerノードと同じドップラー効果となるようにするだけです。続いて、RTPCの作成方法と仕組みを説明します。
2. RTPCでドップラー効果を駆動
ドップラーカーブを設定する前に、ドップラー効果を物理的に理解する必要があります。ここでまず、誤解や曖昧さを避けるために1つだけ確認しておきますが、以下で「波」とは「音波」を指しています。完全に静止した空気の中で、音波は秒速340mで伝わります。どのエミッターやリスナーも、(空中の)移動は音よりも遅いです(ドップラー効果に対する光の影響やローレンツ変換については、ここでは触れません)。この条件下で、エミッターやリスナーの移動から生まれるドップラー効果は、次の式で表されます。
f'はリスナーに聞こえる音の周波数、fは音源から発せられる音の周波数、vは音速、v0は空気に対するリスナーの移動速度、v8は空気に対するエミッターの移動速度です。
状況として、 (1) エミッターが停止してリスナーが動く場合、 (2) リスナーが停止してエミッターが動く場合、の2種類があります。これら2つの状況では、ドップラー効果が大きく異なります。最初の場合は v8 = 0 であり、2つ目の場合は v0 = 0 です。では、式の結果とグラフをみていきます。
図2.1 f’-v0 曲線、v8 = 0 のとき
図2.2 f’-v8 曲線、v0 = 0 のとき
次に、両者のドップラー効果を聞いてください。
2つを比較すると、大きく違うことが分かります。また、どちらかを無視したり、単純に平均値を計算したりできません。それでは、うまくいきません。納得できるドップラー効果を入手するには、どちらのケースも考慮する必要があります。ただし同時に2つのRTPCを使うというのは、将来のメンテナンス上、良い選択とは言えません。2つのベロシティ値を使わずに、f’/f値をRTPC値とすることができます。そうすれば、Wwiseで作成するRTPCカーブが1つで済みます。維持管理も編集も、その方がずっと簡単です。ピッチや周波数は、「1オクターブ高くすると、周波数は倍になる」という基本ルールに従います。簡素化した関数で表すと、y = 2x です。ただしWwiseではy軸に使えるのはピッチだけなので、そのような曲線を作成できません。yとxの場所を入れ替えると、新たに x = log2y という関数の曲線ができます。すでに音速が340 m/sと分かっていて、Wwiseで1200 cents(ピッチ値)は1オクターブに等しいです。以上の情報で、ピッチと速度のカーブをWwiseで作成します。
図2.3 Wwiseのピッチと速度のカーブ
Wwiseでドップラー効果を作成する概要が分かりました。次に、プログラマーに明確に要件を伝える必要があります。具体的には「プレイヤーとエミッターの間の相対速度を計算するのを手伝ってほしい。それを f’/f の式に入れ、さらに、RTPCとしてWwiseに送れるようにしてほしい」とお願いします。
こちらの動画で、その様子を見てください。
もちろん、プロのプログラマーに手伝ってもらいました。でも、プログラマーがいない、または単に自分でやりたいとしたら?
では、RTPC値の設定方法を見てみます。
3. 必要なRTPC変数をゲームエンジンから取得
こちらのワークフローを見てください:
図3.1 必要なRTPC変数を取得するワークフロー
私はC++について詳しくないので、コードはここでお見せしません。代わりに、私が作成したUnrealブループリントを見てください。エフェクトの実装方法と、必要となる操作パラメータの取得方法を表しています。理論的に完璧でく、参考程度に見てください。上記ワークフローに従い、このようなブループリントを作成しました:
図3.2 必要なRTPC変数を取得するためのブループリント
さて、ここで小さな問題がありました。Get Component Velocityノードは、既にVelocityを設定したコンポーネントでしか使えません。例えば、UE 4のサードパーソンのデモゲームには、デフォルトのプレイヤーキャラクターが入っています。
図3.3 UE4のサードパーソンデモのキャラクターの、Velocity設定
Velocity設定のないコンポーネントでは、Get Component Velocityノードを読み込めません。その場合、自分でVelocityを計算するしかありません。私は、こちらのブループリントを作成しました:
図3.4 移動スピードを計算してRTPC値を取得するブループリント (1)
そして、もう一つ:
図3.5 移動スピードを計算してRTPC値を取得するブループリント (2)
この2つのブループリントは、どちらも、各フレームでプレイヤーとエミッターのポジションを読み込み、直前のフレームのVelocityベクトルを取得し、プレイヤーとエミッターを結ぶ線上にこのベクトルを投影して相対速度を取得し、最終的に計算式でRTPC値を導き出します。ただし、前者がエミッター位置とリスナー位置の座標をフレームごとに計算して相対Velocityを取得するのに対し、後者はエミッターとリスナーの間の相対的な距離を計算して相対Velocityを取得します。2つの方式で取得する値の差分は、ほとんどありません。
4. ドップラーレベルの調整
ここで記載したRTPCのシステムプラットフォームへの計算負荷は、どれもわずかなものです。これらの浮動小数点演算は、画像処理と比べれば些細なものです。とはいえ、ここまで精度が高いドップラー効果は、かえって望ましくない場合も考えられます。そのときはシステムロードを緩和するために値を下げ、計算回数を減らすことができます。ブループリントで、RTPC計算を駆動するためにTick Eventを使っています。各フレームで値を取得するイベントです。精度の高いドップラー効果が不要であれば、RTPC計算を駆動するために、追加のLoop Eventを作成します。ループ間隔は自由に設定できます。こちらの値を、Tick Eventが提供するDelta Seconds値の代わりに使います。値の範囲は比較的狭くしてください。そうしないと、移動速度の移り変わりが激しい場合に、唐突な変化が生じてしまいます。
今回のデモプロジェクトで、ドップラー効果を調整する方法を色々と試しました。ここではシンプルにするために、紹介しません。周波数の変化が理解しやすいように、Helicopterを"UFO engine"に設定しました。
ドップラー効果を調整する方法は2つあり、Wwiseでカーブの曲率を変えるか、RTPC値を修正します。ドップラーレベルは、算出されたVelocity値に希望する係数を掛けることで、自由に制御できます。なお、ドップラーレベルとVelocityは反比例の関係にあります。UEのやり方と多少違います(同じ値ではありません)。
さて、ドップラーレベルを調整する理由は?理論上、実際のドップラーレベルは固定値なので、ゲームでも同じにするべきです。伝播媒体の種類や、密度を変えたい場合は、話は別ですが。今後、それをゲームで求められるかもしれません。また、同じレベル内でも、異なる距離の単位を使い分けることができるのも、大きな利点です。例えば、プレイヤーキャラクターが膨張したり、縮んだりするとします。プレイヤーが小さくなったときは動きがとても遅くなり、プレイヤーとのインタラクションがあるオブジェクトも速度が遅くなるとします。その場合、サウンドの表現力が低下します。ここで距離値を変えるより、ドップラーレベルを調整した方が、はるかに楽です。
5. インタラクティブなドップラー効果
ゲームエンジンは、優れたインタラクティブドップラー効果を提供しますが、ゲーム開発やオーディオデザインの内容に合わせて、一部のシーンでしか適用できません。
インタラクティブなドップラー効果は、主に亜音速のエミッターで、長時間存在して継続的に音を発するものに適用され、例えば車、ヘリコプター、ジェットコースター、RPGの発射物などに使われます。
遷音速や超音速のオブジェクトでは、自動的に作用しません。エミッターが音速に近づくと音のパターンが変わり、放出される音のほとんどがオブジェクト自体が発する音ではなくなり、空気の摩擦や衝撃波に由来するものになります。そうなると、もっと複雑な音響理論が必要となり、ドップラー効果では対応しきれなくなります。リスナーが、音速を超えた場合、後方からの音が聞こえなくなり、リスナー自身がエミッターになります。つまり、ドップラー効果で、超音速物体の動作を完全に表すことはできません。
ゲーム内の超音速オブジェクトについては、従来のアセット作成方式がふさわしいと考えられ、サウンドアセット自身にドップラー効果をもたせ、その動作をシミュレーションするタイミングを調整すればいいのです。代表的な例は、ゲーム内の銃弾です。弾丸が飛び過ぎる度に、風切り音があります。弾丸の速度は非常に速く、タイミングや強さに多少のズレがあっても、プレイヤーは通常、その誤差に気づきません。
また、長さやタイミングが固定のサウンドもあります。その場合、リアルタイムに計算する代わりに、特定アセットをトリガーさせることができます。例えば、1Pプレイヤーが矢を放ったときは、リアルタイムにドップラー効果を計算するのではなく、シューティングサンプルに、風切り音をベイクできます。より良い結果を得るには、実際の状況に合わせて設定を変えることも必要です。
6. Wwiseにドップラー効果を組み込む
Wwiseでゲーム内のドップラー効果を作成するには、エミッターとリスナーの相対Velocityを取得し、RTPC値に変換して、その値でピッチを制御すればいいだけです。RTPC値を変換するために、エミッターとリスナーの座標情報を継続的に取得する必要があります。幸運にもゲームプレイ中にWwiseは、減衰や、スペーシャルオーディオ情報などを計算するために、これらのデータをモニタリングしてキャプチャしています。実は、Wwiseはドップラー効果を実行する準備ができています。各エミッターの距離を計算するのと、とてもよく似ているのですが、もう少し複雑な浮動小数点の演算を行います。プロジェクトに合わせて調整するには、ドップラーレベルを変えるだけで済みます。例えば、UEの基本的な測定単位は「センチメートル」ですが、ほかのゲームエンジンでは「メートル」かもしれません。その場合は「音速(つ34,000)」を「340」に換えて、RTPCを計算すればいいだけです。では、ゲーム内の距離単位と、本物の距離単位が、1:1の関係でない場合は?とても簡単です。Scaleファクターを利用するだけです。ドップラーレベルの調整とよく似ています。
Wwiseでドップラーエフェクトを作成するにあたり、このようなモジュールの要件が既にエンジンに備わっていたので、驚きました。これから、Wwiseとカスタマイズしたドップラーツールを使っていきたいと思います。
コメント