Version: 2022.1
言語: 日本語
ネイティブオーディオプラグイン SDK
Audio プロファイラー

オーディオスペーシャライザー SDK

オーディオスペーシャライザー SDK はコントロールを提供し、アプリケーションがオーディオソースから周囲の空間へオーディオを伝送する方法を変更します。これは、ネイティブオーディオプラグイン SDK の拡張機能です。

オーディオソースのビルトインのパンニングは、立体化の簡易な形態の 1 つです。これは、オーディオソースを受け取り、オーディオリスナーとオーディオソースの間の距離と角度に基づいて、左右の耳のバランスを調整します。これにより、プレイヤーは水平面上で簡単な方向を感じることができます。

Unity オーディオスペーシャライザー SDK とその実装例

オーディオの立体化を柔軟にサポートするために、Unity にはネイティブオーディオプラグイン SDK の上に拡張機能としてオーディオスペーシャライザー SDK というオープンインターフェースが提供されています。Unity の標準的なパン機能をより高度なものに置き換えて、計算に必要なソースとリスナーに関する重要なメタデータへのアクセスを与えることができます。

ネイティブスペーシャライザーオーディオプラグインの例は、ネイティブオーディオプラグイン SDK を参照してください。このプラグインは、直接的な頭部伝達関数 (Head-Related Transfer Function, HRTF) のみをサポートしており、サンプルとしての使用のみを目的としています。

プラグインに含まれているシンプルなリバーブを使って、オーディオデータをスペーシャライザープラグインからリバーブプラグインにルーティングすることができます。HRTFフィルタリングは、KEMARデータセットの修正版に基づいています。KEMARデータセットの詳細については、MIT Media Labのドキュメントと測定ファイル を参照してください。

人間の対象としたデータセットを確認したい場合は、IRCAM のデータセットsets を参照してください。

Unity オーディオスペーシャライザーの初期化

Unity は、オーディオソースがオーディオデータをデコードした後に、直接立体化効果を適用します。これにより、各ソースがそれぞれ個別の効果のインスタンスを持つオーディオデータのストリームが生成されます。Unity は、そのソースからのオーディオを、対応する効果インスタンスでのみ処理します。

プラグインをスペーシャライザーとして動作させるには、効果の説明ビットフィールドにフラグを設定する必要があります。

definition.flags |= UnityAudioEffectDefinitionFlags_IsSpatializer;

UnityAudioEffectDefinitionFlags_IsSpatializer フラグを設定すると、プラグインのスキャン段階で Unity はプラグインをスペーシャライザーとして認識します。Unity は、プラグインのインスタンスを作成すると、UnityAudioSpatializerData 構造体を UnityAudioEffectState 構造体の spatializerdata メンバーに割り当てます。

プロジェクトでスペーシャライザーを使用するには、プロジェクト設定でスペーシャライザーを選択します(メニュー: Edit > Project Settings > Audio)。

Spatializer Plugin の選択
Spatializer Plugin の選択

次に、スペーシャライザープラグインで使用するオーディオソースの Inspector ウィンドウで、Spatialize を有効にします。

Audio Source の Spatializer チェックボックス
Audio Source の Spatializer チェックボックス

また、AudioSource.spatialize プロパティを使用して、C# スクリプトを通してオーディオソースのスペーシャライザーを有効にすることもできます。

多数のサウンドを使用するアプリケーションでは、近くのサウンドにのみスペーシャライザーを有効にし、遠くのサウンドには従来のパンニングを使用することで、スペーシャライザー効果のためのミキシングスレッドの CPU 負荷を軽減することができます。

Unity が空間データをスペーシャライザーではないオーディオミキサープラグインに渡したい場合は、説明ビットフィールドに以下のフラグを使用します。

definition.flags |= UnityAudioEffectDefinitionFlags_NeedsSpatializerData;

プラグインが UnityAudioEffectDefinitionFlags_NeedsSpatializerData フラグを使って初期化すると、UnityAudioSpatializerData 構造体を得ますが、listenermatrix フィールドだけが有効です。UnityAudioSpatializerData の詳細は、スペーシャライザー効果メタデータのセクション を参照してください。

Unity がスペーシャライザープラグインに代わって距離減衰を適用しないようにするには、以下のフラグを使用します。

definition.flags |= UnityAudioEffectDefinitionFlags_AppliesDistanceAttenuation;

UnityAudioEffectDefinitionFlags_AppliesDistanceAttenuation フラグは、スペーシャライザーが距離減衰の適用を処理することを Unity に示します。距離減衰の詳細は、減衰カーブと可聴域 のセクションを参照してください。

スペーシャライザー効果のメタデータ

サウンドのミックスで動作する他の Unity オーディオ効果とは異なり、Unity はオーディオソースがオーディオデータをデコードした後に直接スペーシャライザーを適用します。スペーシャライザー効果の各インスタンスは、主にオーディオソースに関するデータに関連する UnityAudioSpatializerData のインスタンスを持ちます。

struct UnityAudioSpatializerData
{
    float listenermatrix[16];   // sourcepos をリスナーのローカル空間に変換する行列 
    float sourcematrix[16];     // オーディオソースの変換行列
    float spatialblend;         // 距離制御された空間ブレンド
    float reverbzonemix;        // オーディオソースのリバーブゾーンミックスレベルパラメーター 
                                // (およびカーブ)
    float spread;               // オーディオソースのスプレッドパラメーター (0..360 度)
    float stereopan;            // オーディオソースのステレオパンニングパラメーター (-1: 完全に左、1: 完全に右)
                                // スペーシャライザープラグインは、
                                // 距離の減衰をオーバーライドして音声の優先順位に影響を与える場合があります  
                                //(ビルトインのオーディオソースの減衰曲線を使用するには、このコールバックを NULL のままにします)
    UnityAudioEffect_DistanceAttenuationCallback distanceattenuationcallback;
    float minDistance;          // オーディオソースの最小距離。 
                                // この値は、ニアフィールド効果をいつ適用するかを決定するのに役立つ場合があります。 
    float maxDistance;          // オーディオソースの最大距離、または 
                                // オーディオがリスナーに聞こえなくなる距離。
    
};

この構造体には、Inspector の Audio Source コンポーネントのプロパティに対応するフィールドが含まれています。Spatial BlendReverb Zone MixSpreadStereo PanMinimum DistanceMaximum Distance などです。

UnityAudioSpatializerData 構造体には、オーディオリスナーとオーディオソースの完全な 4x4 変換行列が含まれています。リスナーの行列は反転しているので、2 つの行列を掛け合わせて相対的な方向ベクトルを得ることができます。リスナーの行列は常に直交しています。そのため、逆行列を素早く計算することができます。

Unity のオーディオシステムは、RAW ソースサウンドをステレオ信号としてのみ提供します。ソースがモノラルやマルチチャンネルであっても信号はステレオであり、Unity は必要に応じてアップミックスやダウンミックスを行います。

行列規則

sourcematrix フィールドには、オーディオソースの変換行列のコピーが保存されます。回転されていないゲームオブジェクトのデフォルトオーディオソースの場合、この行列は、位置が要素 12、13、14 にエンコードされる変換行列です。

listenermatrix フィールドには、オーディオリスナーの変換行列の逆数が含まれています。

オーディオリスナーからオーディオソースへの方向ベクトルは以下のように決めることができます。L は listenermatrix、S は sourcematrix です。

float dir_x = L[0] * S[12] + L[4] * S[13] + L[ 8] * S[14] + L[12];
float dir_y = L[1] * S[12] + L[5] * S[13] + L[ 9] * S[14] + L[13];
float dir_z = L[2] * S[12] + L[6] * S[13] + L[10] * S[14] + L[14];

(L[12], L[13], L[14]) の位置は、実際にはカメラ行列の Unity の Inspector ウィンドウに表示されるカメラ行列の負の値です。もしカメラも回転していたら、まず回転の影響を元に戻さなければなりません。変換-回転行列を反転させるには、L の左上の 3x3 回転行列を転置して、以下のように位置を計算します。

float listenerpos_x = -(L[0] * L[12] + L[ 1] * L[13] + L[ 2] * L[14]);
float listenerpos_y = -(L[4] * L[12] + L[ 5] * L[13] + L[ 6] * L[14]);
float listenerpos_z = -(L[8] * L[12] + L[ 9] * L[13] + L[10] * L[14]);

オーディオスペーシャライザープラグインのコードの例として、Plugin_Spatializer.cpp ファイルの 215 行 を参照してください。

減衰曲線と可聴性

UnityAudioEffectDefinitionFlags_AppliesDistanceAttenuation フラグを指定しない限り、Initializing the Unity オーディオスペーシャライザー セクションで指定されているように、Unity のオーディオシステムは依然として距離減衰を制御します。Unity は、サウンドが立体化の段階に入る前に距離減衰を適用し、オーディオシステムが音源のおおよその可聴性を検知できるようにします。オーディオシステムは、重要度に基づいてサウンドの動的な仮想化を行うためにおおよその可聴性を使用し、ユーザーが定義した Max Real Voices の範囲に合わせます。

Unity は、実際の信号レベル測定から可聴性情報を取得するのではなく、距離制御された減衰曲線、Volume プロパティ、およびミキサーに適用された減衰から読み取った値の組み合わせを使用します。

減衰カーブを直接オーバーライドしたり、オーディオソースのカーブで計算された値を変更のベースに使用こともできます。値をオーバーライドしたり修正したりするには、以下に示すように、UnityAudioSpatializerData 構造体のコールバックを使用します。

typedef UNITY_AUDIODSP_RESULT (UNITY_AUDIODSP_CALLBACK* UnityAudioEffect_DistanceAttenuationCallback)(
    UnityAudioEffectState* state,
    float distanceIn,
    float attenuationIn,
    float* attenuationOut);

下図のように、シンプルなカスタム対数カーブを使用することもできます。

UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK SimpleLogAttenuation(
    UnityAudioEffectState* state,
    float distanceIn,
    float attenuationIn,
    float* attenuationOut)
{
    const float rollOffScale = 1.0f; // Audio Project の設定にあるものと同様
    *attenuationOut = 1.0f / max(1.0f, rollOffScale * distanceIn);
    return UNITY_AUDIODSP_OK;
}

Unity API の C# スクリプトの使用

オーディオソースには、スペーシャライザー効果のパラメーターを設定したり取得するための 2 つのメソッドがあります。SetSpatializerFloatGetSpatializerFloat です。これらのメソッドは、ジェネリックなネイティブオーディオプラグインのインターフェースにある SetFloatParameterGetFloatParameter と同様に動作します。ただし、SetSpatializerFloatGetSpatializerFloat は、設定または読み込みが必要なパラメーターに対するインデックスを取りますが、SetFloatParameterGetFloatParameter は、パラメーターを名前で参照します。

ブーリアンプロパティ AudioSource.spatializer は、Unity のオーディオソースの Inspector ウィンドウにある Spatialize オプションに紐づけられています。このプロパティは、Audio Project Settings で選択されるプラグインに基づいて、Unity がどのようにしてスペーシャライザーの効果をインスタンス化したり割り当てを解除したりするかを制御します。

プロジェクトのメモリやその他のリソースの観点から、立体化効果のインスタンス化が非常に多くのリソースを必要とする場合、プリセットの “プール” から立体化効果を割り当てると効果的な場合があります。そのため、Unity は、使用する必要があるたびにスペーシャライザーの新しいインスタンスを作成する必要はありません。Unity プラグインのインターフェースバインディングを非常に軽量に保ち、オーディオ効果を動的に割り当てると、プロジェクトでフレーム落ちやその他のパフォーマンスの問題を回避できます。

サンプルのプラグインに関する既知の制限

高速なコンボリューションアルゴリズムを採用しているため、素早い動きがジッパーアーチファクトが発生する原因になりますが、オーバーラップセーブコンボリューション (overlap-save convolution) やクロスフェードバッファを使用することで取り除くことができます。

また、リスナーがプレイヤーキャラクターに直接アタッチされていても、どこかに配置されたカメラにアタッチされていても、コードはリスナーのヘッドを傾けることをサポートしていません。 

ネイティブオーディオプラグイン SDK
Audio プロファイラー