Version: Unity 6.0 (6000.0)
言語 : 日本語
SDK に含まれるネイティブオーディオプラグインの例
オーディオプレイリストのランダム化

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

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

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

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

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

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

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

人間の被験者から取得したデータセットを確認する場合は、IRCAM のデータセットを参照してください。

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

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

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

definition.flags |= UnityAudioEffectDefinitionFlags_IsSpatializer;

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

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

スペーシャライザープラグインセレクター
スペーシャライザープラグインセレクター

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

オーディオソースの Spatializer チェックボックス
オーディオソースの Spatializer チェックボックス

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

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

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

definition.flags |= UnityAudioEffectDefinitionFlags_NeedsSpatializerData;

プラグインが UnityAudioEffectDefinitionFlags_NeedsSpatializerData フラグで初期化された場合、プラグインは UnityAudioSpatializerData 構造体を受け取りますが、listenermatrix フィールドのみが有効になっています。UnityAudioSpatializerData の詳細については、Spatializer (立体化) エフェクトのメタデータのセクションを参照してください。

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

definition.flags |= UnityAudioEffectDefinitionFlags_AppliesDistanceAttenuation;

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

Spatializer (立体化) エフェクトのメタデータ

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

struct UnityAudioSpatializerData
{
    float listenermatrix[16];   // Matrix that transforms sourcepos into the local space of the listener
    float sourcematrix[16];     // Transform matrix of the Audio Source
    float spatialblend;         // Distance-controlled spatial blend
    float reverbzonemix;        // Reverb zone mix level parameter (and curve) on 
                                // the Audio Source
    float spread;               // Spread parameter of the Audio Source (0..360 degrees)
    float stereopan;            // Stereo panning parameter of the Audio Source (-1: fully left, 1: fully right)
                                // The spatializer plugin may override the distance attenuation to
                                // influence the voice prioritization (leave this callback as NULL 
                                // to use the built-in Audio Source attenuation curve)
    UnityAudioEffect_DistanceAttenuationCallback distanceattenuationcallback;
    float minDistance;          // The minimum distance of the Audio Source. 
                                // This value may be useful for determining when to apply near-field effects. 
    float maxDistance;          // The maximum distance of the Audio Source, or the 
                                // distance where the audio becomes inaudible to the listener. 
    
};

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

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

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

行列規則

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

listenermatrix フィールドには、AudioListener の Transform 行列の逆数が含まれています。

オーディオリスナーからオーディオソースへの方向ベクトルは以下のように決定できます。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 行を参照してください。

減衰カーブと可聴度

Unity オーディオスペーシャライザーの初期化セクションで指定されているように、UnityAudioEffectDefinitionFlags_AppliesDistanceAttenuation フラグを指定しない限り、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; // Similar to the one in the Audio Project Settings
    *attenuationOut = 1.0f / max(1.0f, rollOffScale * distanceIn);
    return UNITY_AUDIODSP_OK;
}

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

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

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

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

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

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

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

SDK に含まれるネイティブオーディオプラグインの例
オーディオプレイリストのランダム化