Wwise SDK 2023.1.8
|
警告: Object Processorは、Effect Plug-Inの上位集合のようなもので、Effect Plug-Inが実行できることは全てできるうえ、追加機能もあります。ただし、書く内容がもっと複雑になります。一度に複数のAudio Objectを処理する必要がなく、処理するオブジェクトについてオーディオ信号以外のことを知る必要がなければ、Effect Plug-Inを書いてください。 Effect Plug-inインターフェースを実装する を参照してください。 |
Object Processorは、どのWwise ObjectでもEffectタブの欄に挿入されるという点で、Effect Plug-Inと似ています( Effect Plug-inインターフェースを実装する 参照)。Effect Plug-Inとの違いは、Audio Objectと一緒に使ったときに判明します。一言で言うと、Effect Plug-InはAudio Object (AkAudioObject) に左右されずにオーディオ信号を処理するだけなのに対し、Object Processorはバスを通る全てのAudio Objectを認識し、一度に処理し、それらのメタデータにアクセスすることができます。
Effectプラグインが1つの AkAudioBuffer を受信するのに対し、Object Processorは以下を提供するAkAudioObjectのインスタンスを受信します:
これらのコンセプトを、次のセクションで説明します。
Audio Objectの中には、モノラルまたはマルチチャンネルのオーディオ信号が入っています。WwiseでAudio Objectを一番観察しやすいのは、バスのコンフィギュレーションが Audio Objects に設定されているときです。そのようなバスを、 Audio Objectバスと呼びます。マルチチャンネルであってもなくても、 Audio Objectバスはインプットを1つのバッファにミキシングするのではなく、Audio Objectを集めて、そのメタデータを維持します。Audio ObjectバスがサポートするAudio Object数はダイナミックなのに対し、非 Audio Objectバスは、一度に1つのAudio Objectしかサポートしないと考えることができます。
Audio Objectのメタデータは主にポジショニング情報で構成され、それ以外にもカスタムメタデータのアレイがあり、カスタムメタデータはそれ自体がプラグインであり、Object Processorプラグインに使われることがあります。詳細は Audio Object Metadata を参照してください。
Effect Plug-Inは、 Audio Objectバスに乗せると、Audio Objectの数だけインスタンス化され、各インスタンスのライフタイムは、それがアサインされているAudio Objectのライフタイムに対応しています。実際、1つのインスタンスを再利用しながら各Audio Objectを順番に処理することはできず、理由は、オーディオが次のフレームでも継続することを保障するために必要な状態を、そのEffectが維持しているかもしれないからです。
一方、Object ProcessorはAudio Objectの数に関わらず1度だけインスタンス化され、これら全てのオブジェクトを同時に処理します。
Object Processorは、処理がIn-placeかOut-of-placeかにより、 AK::IAkInPlaceObjectPlugin または AK::IAkOutOfPlaceObjectPlugin を実装します。プラグインは、 AK::IAkPlugin::GetPluginInfo から、trueに設定された AkPluginInfo::bCanProcessObjects を返すことで、Object Processorであることを宣言します。自身がIn-placeなのか、Out-of-placeなのかを、 AkPluginInfo::bIsInPlace を設定することで宣言します。
警告: Out-of-placeのObject Processorは、バスでしかサポートされません。バスのEffect Plug-Inの場合と同様に、データを消費したり生産したりするrate(速度)を、変更できません( AkPluginInfo::bCanChangeRate をtrueにできません)。ただし、アウトプットオブジェクトや、そのチャンネルコンフィギュレーションを変更できます。 |
ここでは、これらのインターフェース特有の関数だけに触れています。ほかのプラグインタイプと共通のインターフェースコンポーネント( AK::IAkPlugin インターフェース)の情報については Sound Engineプラグインの作成 を参照し、Effect Plug-Inと共通の機能、例えば初期化、バイパス、モニタリングなどの情報については Effect Plug-inインターフェースを実装する を参照してください。
In-place Object Processorは、 AK::IAkInPlaceObjectPlugin::Execute で、Audio Objectのバッファ( AkAudioBuffer )やメタデータ( AkAudioObject )のアレイを受け取ります。全てのAudio Objectのオーディオ信号やメタデータを読んだり修正したりできますが、Audio Objectの作成や削除、チャンネルコンフィギュレーションの変更などはできません。
なお、In-place Object ProcessorがEffectとして、バスに挿入されるのではなくActor-Mixer HierarchyやInteractive Music Hierarchyのオブジェクトに挿入されると、Execute中のObject Metadataは無効となり、Metadataに対する変更は、一切保存されないので、注意してください。これを確認するためにObject Processorは、Object Keyが AK_INVALID_AUDIO_OBJECT_ID と等しいかどうかを判断し、このシナリオに効率よく対処するか、エラーとしてフラグを立てます。
Compressorは、In-place Object Processorの一例です。アルゴリズムが、全てのAudio Objectのオーディオ信号を一度に知ることに依存しているので、これはObject Processorである必要がありますが、Audio Objectのリストは変更しません。ここを通るオブジェクトのオーディオ信号を変更するだけです。
もちろんCompressorは、単一のオブジェクトを処理することができ、言い換えれば、従来のチャンネルベースのバスに対応できます。つまり、以前のEffect Plug-Inの実現より優先します。
Effectプラグインと同じく、In-place Object Processorもテールを扱うことができ、対象フレーム数分だけ、 AkAudioBuffer::eState フィールドを AK_NoMoreData から AK_DataReady に変更します。詳細は Implementing エフェクトプラグイン テール を参照してください。ここで重要なのは、Object Processorが、全てのAudio Objectのテールを個別に扱う必要があるということです。そこで、各オブジェクトをトラッキングする必要があります。
注意: Executeに送られるオーディオオブジェクトのアドレスを保存しないでください。フレーム毎に変わることがあります。オブジェクトの識別には、 AkAudioObject::key field を使うことが望ましいです。 |
Out-of-place Object Processorは、インプット側とアウトプット側で、異なるAudio Objectセットを取り扱います。インプットされるAudio Objectがホストバスで決まるのに対し、アウトプットされるAudio Objectは、以下のセクションの2メソッドのうちの1つを使い、プラグインが意図的に作成します。全てのオブジェクトが、フレーム毎に AK::IAkOutOfPlaceObjectPlugin::Execute 経由でプラグインに送られます。
アウトプットされるAudio Objectのチャンネルコンフィギュレーションは、プラグインが決めます。
また、非 Audio Objectバス(つまりシングルオブジェクトのバス)は、基本的に、普通の Audio Objectバスの特例であり、Audio Objectが1つしかないだけです。Object ProcessorはAudio Objectを数に関係なく受けとり、出せるので、シングルオブジェクトのバスから、動的に変化する数のAudio Objectをアウプットすることができるだけでなく、逆に従来のミキシングバスのように、 Audio ObjectバスがAudio Objectを1つだけ出すようにすることもできます。
注釈: Object Processorは、非 Audio Objectバスにインサートすると、そのバスの実際のチャンネルコンフィギュレーションを AK::IAkEffectPlugin::Init で受信します。Object Processorsは、Effect Plug-Inの上位集合なので、インサート先が Audio Objectバスでも非 Audio Objectバスでもシームレスに機能するよう、努めてください。ただし、ユーザーエラーで非 Audio Objectバスにインサートされた場合を除きます。例えば、ユーザーが ソフトウェアBinauralizer プラグインを非 Audio Objectバスにインサートしても、ダウンミックスされたオーディオには使えるポジショニング情報がないので、あまり意味がありません。このような場合は、おそらく間違いであることをユーザーに伝えた方がいいでしょう。 |
サウンドエンジンは各フレームの最初に、インプットとアウトプットの全てのAudio Objectの AkAudioBuffer::eState を、 AK_NoMoreData にリセットします。処理後にAudio Objectの AkAudioBuffer::eState が AK_NoMoreData に設定されたままであれば、それは破壊されます。Object Processorは、インプットとアウトプットの全てのオブジェクトが破壊されないと、破壊されません。そこで、Out-of-place Object ProcessorにインプットAudio Objectがなくても、そのままオーディオを出し続けるようにするには、1つまたは複数のアウトプットAudio Objectが消えないように、そのステートを AK_DataReady に設定すれば良いだけです。
注意: あなたのObject Processor内のオブジェクトをトラッキングする場合は、注意が必要です。オブジェクトがサウンドエンジンによって破壊されてから、そのオブジェクトを参照するようなことがないようにしてください。 |
注釈: インプットオブジェクトは、 AkAudioBuffer::eState を AK_DataReady に設定すれば消えませんが、テールが不要なので、これは避けてください。 |
注釈: 0個のAudio ObjectをアウトプットするようなOut-of-place Object Processorは、無音をアウトプットします。 |
Out-of-place Object Processingについて、次の3つのカノニカル事例を通してさらに探ります。
ソフトウェアのbinauralizerをOut-of-place Object Processorとして実装し、複数のAudio Objectを受けて、1つのステレオチャンネルコンフィギュレーションのAudio Objectとしてアウトプットすることができます。このようなプラグインは Audio Objectバスに乗せるべきですが、結果的に、このバスのアウトプットは単一のステレオ信号となります。
唯一となるステレオアウトプットオブジェクトを作成するのに便利なのは、 AK::IAkEffectPlugin::Init の、ハンドシェイクメソッド経由の方法です。
次にExecuteで:
実装方法によっては、3D Pannerを、前述の ソフトウェアBinauralizer のように機能させることができます。ところが、スペーシャリゼーションを施したバーチャルマイクにそれぞれが対応するような、アウトプットAudio Objectのセットをインスタンス化した方が、より美しく実装できます。これらのAudio Objectの信号を下流のバスやデバイスによってパンニングすることになるので、バーチャルマイクのポジショニングメタデータを最大限に活用できます。
AK::IAkEffectPlugin::Init で、非オブジェクトのコンフィギュレーションを返す代わりに、意図的に AK::IAkEffectPluginContext::CreateOutputObjects を使ってアウトプットオブジェクトを作成します。
上記の例を見て、なぜ (-0.707f, 0.f, 0.707f) がフロントレフトを表すのか、疑問に思われたかもしれません。詳細は 3D Transformationについて を参照してください。
Particle Generatorは、インプットされた1つのAudio Objectに対してN個のアウトプットAudio Objectを作成し、該当オブジェクトのポジションの周りに、ランダムに配置します。この種のObject ProcessorはInitでオブジェクトを作成することができず、オブジェクトをExecuteでダイナミックに作成して、トラッキングして、インプットオブジェクトのトラッキングをします。もしインプットオブジェクトのステートが AK_NoMoreData であれば、対応するアウトプットオブジェクトのステートも、 AK_NoMoreData に設定する必要があります。そうすれば、サウンドエンジンが、ガベージを確実に収集します。
注意: Out-of-place Object Processorが AK::IAkEffectPluginContext::CreateOutputObjects をExecute内からコールしても、 out_objects で渡されるアウトプットオブジェクトを確実にアクセスできるとは限りません。その場合は、 AK::IAkEffectPluginContext::GetOutputObjects を使う必要があります。 |
オーサリングツールのAudio Object Profilerでは、Audio Objectの名前に、元となったWwise Objectの名前が付けられます。このため、Out-of-place Object Processorのアウトプットオブジェクトの名前は、どれもホストバスの名前が付きます。プロファイリングをしやすくするために、適切であれば、アウトプットオブジェクトの名前を AkAudioObject::SetName を使って付けることを推奨します。
例えば、前述の 3D Panner でオブジェクトを作成するときに、名前を以下のように付けることができます:
AkAudioObject struct は、オブジェクトパイプライン全体にあるAudio Objectのオーディオバッファに沿って流れる、全てのAudio Objectメタデータを網羅しています。以下の3つのカテゴリに分けることができます:
Audio Objectの AkAudioObject::positioning には、発生元となったサウンドのポジショニングデータが入っています。 AkAudioObject::positioning.behavioral
が、Wwise Objectにある全ての該当ポジショニング設定を保持しています。例えば、スピーカーパンニングを使うサウンドであれば、 AkAudioObject::positioning.behavioral.panType
にパンナータイプが1つ設定され、 panLR
、 panBF
、 panDU
がパンナーのポジションとなります。
もしスペーシャリゼーションモードが3Dであれば( AK_SpatializationMode_PositionOnly
または AK_SpatializationMode_PositionAndOrientation
)、AkAudioObject::positioning.threeD
に、3Dポジションに関連する全てのデータが含まれます:
AkAudioObject::positioning.threeD.xform
は基本的に関連ゲームオブジェクトのポジションを継承しますが、3Dオートメーションなど、各サウンドの3Dポジション設定によっては、それを変更したりオーバーライドしたりできます。AkAudioObject::positioning.threeD.spread
と AkAudioObject::positioning.threeD.focus
は、一般的にAttenuation Curveから算出されます。Audio Objectには、ソースのVolumeや、バスからのゲインの変化や、バス間の接続の変化など、上流で適用された累積ゲインが伴います。EffectやObject Processorのないシンプルなシナリオでは、Audio Objectのゲインは、最終的にスピーカーベッドにミックスダウンされるまで、またはAudio Objectとしてシステム出力に送られるまで、オーディオ信号に適用されないことを意味します。これにより、Audio Objectのオーディオ信号に対し、1フレームに何度もゲインを追加するようなことを回避でき、特にGame Objectのポジションが追加されたり削除されたりすることでAudio Objectが作成され破壊される場合などでも、滑らかに変化するオーディオミックスが生まれます。
このメタデータの対応はObject Processorで任意であり、有効にするには IAkPlugin::GetPluginInfo
のObject Processorの実装で、 IAkPluginInfo::bUsesGainAttribute
をtrueに設定します。 bUsesGainAttribute をfalseのままにすると、Executeに渡す全てのオーディオバッファに、実行前に適用されたAudio Objectの累積ゲインが伴い、Object Processorに渡されるゲインは中立的となります。しかし bUsesGainAttribute がtrueに設定されると、オーディオバッファは修正されることなく、累積ゲインは非ユニット値になる可能性があります。これにより、Object Processorがゲインを必要に応じて認識することができ、必要に応じてAudio Objectの累積ゲインを変更することもできます。
Audio Objectの累積ゲインを変更する場合は、値が AkRamp
であり、あるフレームのfNext値と次のフレームのfPrev値の連続性が、サウンドエンジンによって自動的に処理されないのことに注意してください。つまり、Object Processorが、あるフレームでfNextを変更しようとした場合、次のフレームのfPrevにも同じ変更を適用する必要があります。これを適切にに管理しないと、オーディオパイプラインのほかの部分でAudio Objectのゲインを消費する必要があるときに、オーディオのグリッチや、オーディオ信号の途切れが発生する可能性があります。
スペーシャリゼーションモード AkAudioObject::positioning.behavioral.spatMode
が3Dであれば( AK_SpatializationMode_PositionOnly
または AK_SpatializationMode_PositionAndOrientation
)、3Dポジションは、それが所属するバスに関連付けられているゲームオブジェクト(リスナー)に相対するように、トランスフォーム(変換と回転)されます。例えば、サウンドのポジションが (2, 0, 0) であれば、 (10, 0, 0) のポジションにあるリスナーと関連付けられた Audio Objectバスでそのサウンドを処理すると、出てくるAudio Objectのポジションは、 (-8, 0, 0) となります。このバスにあるObject Processorは、そのAudio Objectが (-8, 0, 0) に配置されているものとして、とらえます。
Wwiseの座標システムは、左手系で、 AkCommonDefs.h で定義した通り、デフォルトのオリエンテーションのフロントベクトルはZ方向を指し、トップベクトルはY方向を指します。
例えば、 ソフトウェアBinauralizer では、インプットオブジェクトがプラグインに到達する前に回転されるので、正の数Zはリスナーのフロント、正の数Xはリスナーの右となります。この例でサービス AK::IAkMixerPluginContext::ComputePositioning がリスナーのオリエンテーションを使わないのも同じ理由で、デフォルトのオリエンテーションをとります。
そうすると、上の 3D Panner の例で、 (-0.707, 0, 0.707) は、ホストバスに関連付けられたゲームオブジェクトの、フロントレフト方向45度を指します。
Object Processorは、Audio Objectにアタッチされているカスタムメタデータをアクセスできます。
カスタムメタデータは、パラメータのセットだけで成立するプラグインの一種です。オーサリング側で、メタデータプラグインを好きなWwise Objectに追加でき、ShareSetがサポートされます。サウンドエンジンで、 AK::IAkPluginParam インターフェースを実装します。
フレームごとにAudio Objectは、該当があれば、その発生元となったサウンドにアタッチされているメタデータプラグインを全て収集し、それを自身の AkAudioObject::arCustomMetadata アレイに追加します。次に、訪問する全てのバスにアタッチされている、全てのメタデータプラグインを収集します。Object Processorは、In-placeでもOut-of-placeでも、このアレイを読むことができます。もちろん、プラグインの内容を解釈するには、そのプラグインを認識している必要があります。
Object Processorの実装者が、コンパニオン(仲間)のメタデータプラグインを1つ以上書いて、それをユーザーがWwise Objectに追加することができます。
例えば、前述のSoftware Binauralizer( ソフトウェアBinauralizer 参照)で、Passthrough(通過)モードを設定し、特定のサウンドにHRTFフィルタを適用させない場合を考えます。その場合はコンパニオンとなるメタデータプラグインとして ObjectBinauralizerMetadata を作成し、Passthroughという名前のブール型プロパティを付けます。ユーザーは、HRTFの適用を外したいWwise Objectに、このプラグインを追加します。次に、あなたのObject Processorの、 Execute() で:
注釈: Audio Objectは、訪問した全てのWwise Objectからメタデータプラグインを収集するので、同じプラグインタイプの、複数のインスタンスが、1つのAudio Objectで見つかることがあります。これが発生したときの方針は、あなたが判断し、ユーザーに通知してください。 |