目次

Wwise SDK 2018.1.11
統合の詳細 - イベント

イントロダクション

イベント(Events)は、Wwise オブジェクトに適用するアクションを特定するもので、Wwise ユーザーにより作成されます。例えば、1つ目のイベントに、Bird1(鳥の声1) サウンドに対する「再生(Play)」アクションと Bird2(鳥の声2) サウンドに対する「停止(Stop)」アクションを入れることができ。2つ目のイベントには、CarEngine(車のエンジン) サウンドに対して相対的なボリュームオフセット-2を設定する「ボリューム設定( Set Volume)」アクションと、Ground_Material(地面素材) スイッチグループを Tiles(タイル) に変更する「ステート設定(Set State)」アクションを入れることができます。

引き続いて、ゲームへのロードが可能なサウンドバンク(SoundBanks)にイベントをパッケージ化すると、これらのイベントをゲームコードによってトリガーできるようになります。例えば、プレイヤーがキッチンに入るとき、 Ground_Material ステートを Tiles に設定するイベントをトリガーできます。

いったんイベントがゲームに統合されると、Wwise ユーザーは、イベントに入っているアクションあるいはイベントが参照するオブジェクトの取り替えや変更などの作業を続けることがことができます。ゲームは引き続き同じイベントをトリガーするので、Wwise ユーザーにより加えられた変更は、開発者による追加作業やコードの再コンパイルを必要とすることなくゲーム内に反映されます。

ゲームへのイベント統合

AK::SoundEngine::PostEvent() 関数は、処理対象のイベントをキューに入れ、ID または名前によりイベントを識別します。この関数は、イベントをトリガーする必要がある場合に、ゲームのコードによって呼び出される必要があります。

しかしながら、AK::SoundEngine::RenderAudio() 関数が呼び出されるまではイベントの処理が実行されません。ゲームフレームごとに AK::SoundEngine::RenderAudio() を一度呼び出すことをお勧めします。

AK::SoundEngine::RenderAudio() が呼び出されると:

イベントは、ゲームによってポストされた順序で処理されます。イベント内のアクションは、Wwise に表示される順序で処理されます。

同じフレーム内にポストされたイベントは、後で実行される、ディレイを含んだアクションを除いて、出来る限り同時に処理されます。

何らかの理由で、AK::SoundEngine::RenderAudio() 関数が長い期間(例えば、複数フレームなど)にわたって呼び出されない場合、ストリーミングサウンドは正常に再生を続行しますが、次回 AK::SoundEngine::RenderAudio() が呼び出されるまで、新しいイベントは起動されず、新しいポジショニングも適用されません。

ID使用の有効化

ID を使用して作業するには、Wwise の Generate SoundBanks ダイアログボックス内にある "Generate header file(ヘッダファイルを生成)" オプションでバンクを生成する必要があります。Wwise_IDs.h という名前の定義ファイルには、すべての必要な ID が含まれています。この定義ファイルは、バンクが生成されるたびに更新されます。

イベント通知

AK::SoundEngine::PostEvent() 関数は、マーカーに到達した時、または、イベントが終了した時に呼び出される AkEventCallbackFunc() 関数へのポインタを受け入れます。これは、イベントとサウンド再生を同期させるのに有用です。

すべてのイベントアクションが実行され、イベントにトリガーされたすべてのサウンドが再生を完了した時、このイベントは終了したものとみなされます。イベントの中には、自ら終了しないものがあることに注意してください。例えば、イベントに無限にループするサウンドが含まれている場合、このサウンドが別のイベントによって停止された後でのみコールバックがトリガーされます。

マーカーは、SoundForge® 、Adobe® Audition® など外部の波形編集ソフトで作成する必要があります。サウンドエンジンは、これらのキューポイントを認識し、AK::SoundEngine::PostEvent()呼び出し時にコールバック関数を指定した場合、このコールバック関数を通知します。

参照

イベントのポストと実際のサウンド再生の間のレイテンシ

プラットフォーム毎の、イベントがポストされてから、オーディオデータが再生開始するまでのレイテンシを推測することができます。

ゲームスレッドから、SDK 関数 PostEvent()を呼び出します。イベントをポストすると、何かを再生する要求をポストします。この要求は、ゲームがRenderAudio()関数を呼び出すまで処理されません; 実際にオーディオをレンダリングせず、最後のRenderAudio()の呼び出しからポストされた要求を処理するように通知のみを送ります。通常は、ゲームのフレーム毎に一度、ゲームがRenderAudio()を呼び出します。しかし、これは必須ではありません; 直近でポストされたイベントをできるだけすぐに強制的に実行するため、いつでも呼び出すことができます。

一度 RenderAudio() が呼び出されると、そのオーディオ (EventManager) のスレッドには、前にポストされたイベント/コマンドを消費する許可が与えられます。しかしこのスレッドは、プラットフォームのオーディオの消費レートと同期することに注意してください。オーディオ出力モジュールがバッファを消費すると「オーディオリフィル」パスだけが実行され、そのリングバッファのセクションが書き込みに利用できるようになります。

最終的には、出力モジュールのリングバッファのサイズを考慮します。Windowsでサウンドエンジンを初期化する時には、AkPlatformInitSettings::uNumRefillsInVoiceを利用して、プラットフォーム特定のパラメータでリングバッファサイズと指定できます。これによりボイスバッファでの「リフィルバッファ」の数を与え、2はダブルバッファリングとなり、デフォルトは4です。この数字をどう選ぶかは、レイテンシを減らす (小さなバッファ)と、システムがメモリ不足により耐えるようにする (大きなバッファ) の間のバランスを取ることです。

「リフィルバッファ」または一般的には「オーディオフレーム」と呼ばれますが、サンプルレートを周波数で割った値で決定されます。ですから、高品質モードのWindowsでは、これは通常: (1,024 サンプル) / (48,000 Hz) = 21.3 ms. AkInitSettings::uNumSamplesPerFrameを使用してサンプルをに512に設定する場合、オーディオフレームは次のようになります: (512 サンプル) / (48,000 Hz) = 10.6 ms

そして要約すると、次のようにして「サウンドエンジンの総レイテンシ」を決定します:

  1. PostEvent()の呼び出しとRenderAudio()の呼び出しの間の時間 (ゲームにより異なります)、これはフレーム毎に一度RenderAudio()を呼び出す毎秒ゲーム60フレームで、16msを意味します。
  2. RenderAudio() の呼び出しとオーディオフレーム境界間の時間: 現在のオーディオフレームの最後、もしくは最初でRenderAudio()が呼び出されるかによって、0 〜 21 ms
  3. 出力ステージのバッファリング。ダブルバッファリング出力のステージで: 2 * 21 ms = 42 ms のレイテンシ。
    1. オーディオフレームレート。オーディオフレームレートを減少させて、ダブルバッファリング出力のステージで: 2 * 11 ms = 22 ms のレイテンシ。

合計で、毎秒60フレームの更新システム:

  • 最良のケースで42 msのレイテンシ
  • 最悪のケースで79 msのレイテンシ

ストリーミング

先に説明したサウンドエンジンのレイテンシ算出に加えて、サウンドが100% ストリーミングされると (メモリには何も読み込まれない) 、継承したI/O レイテンシを追加する必要があります。I/O レイテンシを避けるため、Zero latency (ゼロレイテンシ) を指定して、サウンドを始めをメモリに読み込みます。このバッファのサイズは、Prefetch length (プリフェッチレングス)により決定し、これは通常デフォルトで安全な100msが設定されています。

イベント処理例

以下に有用な例をいくつか示します(擬似コード):

PostEvent( Play_Sound1, GameObj_X )
PostEvent( Stop_Sound1, GameObj_X)
Result: Nothing will play.
PostEvent( Stop_Sound1, GameObj_X )
PostEvent( Play_Sound1, GameObj_X )
Result: Sound1 will play
SetSwitch( Grass, GameObj_X )
PostEvent( Play_SwitchFootStep, GameObj_X )
SetSwitch( Concrete, GameObj_X )
PostEvent( Play_SwitchFootStep, GameObj_X )
Result: Grass and concrete sounds will both play
SetSwitch( Grass, GameObj_X )
SetSwitch( Concrete, GameObj_X )
PostEvent( Play_SwitchFootStep, GameObj_X )
PostEvent( Play_SwitchFootStep, GameObj_X )
Result: Concrete sounds will play twice

イベント組み込みの例については、クイックスタートサンプル統合 - イベント を参照してください。