| ログイン | ご入会 |
ADC連絡先
|
|
3DMixer Audio Unit v2.0 には、サウンドを立体空間の中で定位する機能、すなわち、複数の音源を距離、仰角、および方位角によってリスナーの周囲に配置する機能があります。3DMixer は複数チャネルのレイアウト(「スピーカー設定」セクションで後述)を対象にレンダリングを行うことができます。さらに、再生中にレンダリングされるサウンドの品質は、CPU のパフォーマンス要求に合わせて調節することができます。 3DMixer 用の AUGraph の作成![]() 図 1: 3D Mixer 3DMixers はデータフローの管理を支援するために、通常、Audio Unit Graph ( グラフの先頭は必ず出力ユニットであり、処理したオーディオストリームをディスクやメモリに、またはサウンド出力として保存することができます。グラフを開始すると、先頭オーディオユニット(データはここからグラフを出ます)が「プル」され、先頭オーディオユニットはグラフ内の接続されているオーディオユニットからデータをプルします。このテクニカルノートでは、グラフの先頭としてデフォルト出力オーディオユニットを使用します。デフォルト出力ユニットは、Audio MIDI 設定アプリケーションまたはシステム環境設定の出力パネルでユーザが選択した出力装置(多くの場合はスピーカー)になります。Audio Unit Graph の使い方の詳細については、「Using the Audio Toolbox」を参照してください。 グラフの設定を開始するには、 リスト 1: AUGraph の作成とノードの追加
void MyCreateAUGraph( AUGraph mAUGraph,AudioUnit mOutputUnit,
AudioUnit mMixerUnit)
{
AUNode mMixerNode, mOutputNode;
NewAUGraph(&mAUGraph);
ComponentDescription mixerCD;
mixerCD.componentFlags = 0;
mixerCD.componentFlagsMask = 0;
mixerCD.componentType = kAudioUnitType_Mixer;
mixerCD.componentSubType = kAudioUnitSubType_3DMixer;
mixerCD.componentManufacturer = kAudioUnitManufacturer_Apple;
AUGraphNewNode (mAUGraph, &mixerCD, 0, NULL, &mMixerNode);
ComponentDescription cd;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_DefaultOutput;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
AUGraphNewNode (mAUGraph, &cd, 0, NULL, &mOutputNode);
//グラフを開く
AUGraphOpen (mAUGraph);
//グラフから Audio Unit を取得する
AUGraphGetNodeInfo (mAUGraph, mMixerNode, 0, 0, 0, &mMixerUnit);
AUGraphGetNodeInfo (mAUGraph, mOutputNode, 0, 0, 0, &mOutputUnit);
}
グラフが作成されたら、グラフを初期化して開始する前に、3DMixer を適切に設定する必要があります。 バスカウントの設定3Dmixer の入力数(すなわち、バス数)は設定可能なプロパティです。デフォルトでは、3DMixer には 64 のバスがあります。バスはメモリを使用するため、バスカウントはアプリケーションに必要な値よりも高く設定しないようにします。このプロパティの設定は、ミキサーユニットを初期化する前に行う必要があります。 リスト 2: ミキサーバスカウントの設定
OSStatus SetMixerBusCount (UInt32 inBusCount)
{
UInt32 size = sizeof(UInt32);
UInt32 busCount = inBusCount;
return (AudioUnitSetProperty ( mMixerUnit,
kAudioUnitProperty_BusCount,
kAudioUnitScope_Input,
0,
&busCount,
size));
}
内部リバーブの使い方3Dmixer には、リバーブ機能が組み込まれています。オンにすると、(後述のように)入力バスごとにリバーブが適用されます。リバーブはデフォルトではオフになっており、グラフを初期化する前に、 リスト 3: 内部リバーブの有効化
UInt32 reverbSetting = 1 // リバーブをオンにする
result = AudioUnitSetProperty(mMixerUnit,
kAudioUnitProperty_UsesInternalReverb,
kAudioUnitScope_Global,
0,
&reverbSetting,
sizeof(reverbSetting));
3DMixer のリバーブをオンにしたら、 リスト 4: バスのリバーブをオンにする
UInt32 render_flags_3d;
UInt32 outSize = sizeof(render_flags_3d);
// このバスの現在のレンダーフラグを取得する
result = AudioUnitGetProperty (mMixerUnit,
kAudioUnitProperty_3DMixerRenderingFlags,
kAudioUnitScope_Input,
busIndex,
&render_flags_3d,
&outSize);
// このレンダーフラグをオンにしてからバスを設定する
render_flags_3d |= k3DMixerRenderingFlags_DistanceDiffusion;
result = AudioUnitSetProperty( mMixerUnit,
kAudioUnitProperty_3DMixerRenderingFlags,
kAudioUnitScope_Input, busIndex,
&render_flags_3d,
sizeof(render_flags_3d));
スピーカー設定3DMixer v2.0 はオーディオをステレオ、4 チャネル、5.0 チャネルレイアウトにレンダリングすることが可能です。3DMixer v2.0 は、出力ストリームフォーマットが設定されたときに、チャネルレイアウトを適切に設定しますが、チャネルレイアウトは明示的に設定することをお勧めします。そうすれば、同じチャネル数(すなわち、5.1 と 6.0)を使用するマルチチャネルレイアウトをサポートするミキサーが将来リリースされても、コードを変更する必要がなくなります。チャネルレイアウトを明示的に設定する際には、ストリームフォーマットのチャネルカウントに一致するレイアウトを必ず選んでください。さもなければエラーが返されます(たとえば、5 つのチャネルのあるストリームフォーマットに対して、4 チャネル用のチャネルレイアウトを設定するとエラーが返されます)。複数チャネルのレイアウトにレンダリングできるミキサーの機能をフル活用するためには、カレントデバイスの出力チャネルレイアウトを問い合わせて、Audio MIDI 設定アプリケーションでスピーカー設定にユーザが何を設定しているかを調べる必要があります(次の例を参照)。 次のコードは、グラフの出力ユニットに問い合わせを行うことで、ミキサーのストリームフォーマット(出力範囲)を設定するときに使用する適切なチャネルカウントを調べます。 注意: Audio MIDI 設定で、ユーザがマルチチャネルハードウェア装置用のスピーカー設定(チャネルレイアウト)を設定している可能性があることを頭に入れておいてください。ただし、すべてのハードウェアチャネルにスピーカーが接続されていない可能性もあります(つまり、8 チャネルの装置に 2 つのスピーカーが接続されている場合など)。この場合は、スピーカーが接続されていないデバイスチャネルにオーディオデータがレンダリングされないように、ユーザにステレオレンダリングを指定させ、アプリケーションをステレオに固定するのが適切かもしれません。 リスト 5: レンダリング対象の正しいチャネル数の調査
UInt32 GetDesiredRenderChannelCount ()
{
OSStatus result = noErr;
// 出力 AU から HAL デバイス ID を取得する
AudioDeviceID deviceID;
UInt32 returnValue = 2; // デフォルトの場合は、ステレオを返す
UInt32 outSize = sizeof(deviceID);
// カレントデバイスを取得する
AudioUnitGetProperty(mOutputUnit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Output,
1,
&deviceID,
&outSize);
//ユーザのスピーカー設定を取得する
result = AudioDeviceGetPropertyInfo(deviceID,
0,
false,
kAudioDevicePropertyPreferredChannelLayout,
&outSize,
NULL);
if (result != noErr)
return (returnValue); // デフォルト(ステレオ)を返す
AudioChannelLayout *layout = NULL;
layout = (AudioChannelLayout *) calloc(1, outSize);
if (layout != NULL)
{
result = AudioDeviceGetProperty(deviceID,
0,
false,
kAudioDevicePropertyPreferredChannelLayout,
&outSize,
layout);
if (layout->mChannelLayoutTag
== kAudioChannelLayoutTag_UseChannelDescriptions)
{
// チャネルレイアウトタグが返されない場合は、
//チャネル記述をウォークスルーし、
// スピーカーの接続されているチャネルをカウントする
if (layout->mNumberChannelDescriptions == 2)
{
returnValue = 2; // ステレオのチャネル情報がない
}
else
{
returnValue = 0;
for (UInt32 i = 0; i < layout->mNumberChannelDescriptions; i++)
{
if (layout->mChannelDescriptions[i].mChannelLabel !=
kAudioChannelLabel_Unknown)
returnValue++;
}
}
}
else
{
switch (layout->mChannelLayoutTag)
{
case kAudioChannelLayoutTag_AudioUnit_5_0:
case kAudioChannelLayoutTag_AudioUnit_5_1:
case kAudioChannelLayoutTag_AudioUnit_6:
returnValue = 5;
break;
case kAudioChannelLayoutTag_AudioUnit_4:
returnValue = 4;
default:
returnValue = 2;
}
}
free(layout);
}
return returnValue;
}
重要: ミキサーの出力ストリームフォーマットは、出力ユニットに接続する前に設定する必要があります。ミキサーを出力ユニットに接続した後は、出力ユニットの入力範囲レイアウトに一致するように、チャネルレイアウトを明示的に設定しなければなりません。 リスト 6: AUGraph のチャネルレイアウトを設定する
void ConfigureGraphForChannelLayout()
{
OSStatus result = noErr;
// ミキサーの出力ストリームフォーマットに
// 設定するチャネルレイアウトを取得する
mCurrentMixerChannelCount = GetDesiredRenderChannelCount();
// ストリームフォーマットを設定する
CAStreamBasicDescription format; //CoreAudio SDK クラス
UInt32 outSize = sizeof(format);
result = AudioUnitGetProperty(mOutputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
0,
&format,
&outSize);
// インターリーブされていない
format.SetCanonical (mCurrentMixerChannelCount, false);
format.mSampleRate = mMixerOutputRate;
outSize = sizeof(format);
result = AudioUnitSetProperty (mOutputUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&format,
outSize);
result = AudioUnitSetProperty (mMixerUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
0,
&format,
outSize);
return;
}
立体空間でのサウンドの定位バスの距離、仰角、および方位角を設定すると、リスナーは立体空間の特定のポイントから音が聞こえます。 オーディオソースのピッチと増幅率は、3DMixer 内でバスごとに変更することができます。ピッチを変えるには、 注意: ここでいう増幅率とは、実オーディオデータのボリュームをスケーリングするためのものです。オーディオの空間的な減衰はすべて、ミキサーバスで距離パラメータを設定することによって実現します。 表 1: 3D パラメータ(位置)
表 2: 3D パラメータ(ボリュームとピッチ)
リスト 7: 距離と方位角の設定
void SetObjectCoordinates(UInt32 inMixerInputBus, Float32,
inAzimuth, Float32 inDistance)
{
AudioUnitSetParameter(mMixerUnit,
k3DMixerParam_Azimuth,
kAudioUnitScope_Input,
inMixerInputBus,
inAzimuth,
0);
AudioUnitSetParameter(mMixerUnit,
k3DMixerParam_Distance,
kAudioUnitScope_Input,
inMixerInputBus,
inDistance,
0);
}
3DMixer v2.0 からは、指定した ReferenceDistance、MaximumDistance、および Attenuation 設定にバスボリュームを固定するのに必要なすべての作業をミキサーにさせることができます。この機能により、アプリケーションは立体空間のオブジェクトが実際にリスナーからどの程度離れられるかを指定することができます。以下の方法は、 リスト 8: AudioUnitProperties.h に定義されているミキサーの距離パラメータ構造体
typedef struct MixerDistanceParams {
Float32 mReferenceDistance;
Float32 mMaxDistance;
Float32 mMaxAttenuation; // デシベル単位
} MixerDistanceParams;
![]() 図 2: 距離パラメータのグラフ リスト 9: バスの距離パラメータの設定
void SetDistanceParamsForBus (UInt32 inMixerInputBus)
{
MixerDistanceParams distanceParams;
// オブジェクトがリスナーに近づける
// 最短距離の希望値を取得する(メートル単位の浮動小数点数値)
// ミキサーは、0.0 とこの基準距離の間にある
// すべての距離座標に対して、0db の減衰(減衰なし)で
// オーディオを バス上で再生します。
// この値は最大距離の設定値未満でなければなりません。
distanceParams.mReferenceDistance = GetMyMinimumDistance();
// オブジェクトがリスナーから遠ざかることのできる
// 最大距離の希望値を取得する(メートル単位の浮動少数値)
// ミキサーは、この最大距離以上の
// すべての距離座標に対して、
// バス上のオーディオの減衰を止めます。
// この値は基準距離の設定より大きくなければなりません。
distanceParams.mMaxDistance = GetMyMaximumDistance();
// オブジェクトの座標が最大距離
// (dB 単位の正の浮動小数点数値)であるときの
// オブジェクトの減衰(db 単位)の希望値を取得します。
// 距離座標が最大距離設定を超えている場合、
// ミキサーはこの db 設定以上には
// オーディオを減衰しません。
distanceParams.mMaxAttenuation = GetMyMinimumAttenuation();
OSStatus result = AudioUnitSetProperty(mMixerUnit,
kAudioUnitProperty_3DMixerDistanceParams,
kAudioUnitScope_Input,
inMixerInputBus,
&distanceParams,
sizeof(distanceParams));
}
空間化レンダリングのアルゴリズム空間化設定は、バス(ミキサー入力)ごとに、 表 3: ステレオ出力に適した空間化アルゴリズム(AudioUnitProperies.h で定義)
リスト 10: 3DMixer への空間化アルゴリズムの設定
SetSpatializationAlgorithm( UInt32 BusNumber)
{
UInt32 spatialSetting = GetMySpatializationSetting();
result = AudioUnitSetProperty(mMixerUnit,
kAudioUnitProperty_SpatializationAlgorithm,
kAudioUnitScope_Input,
BusNumber,
&spatialSetting,
sizeof(spatialSetting));
}
ボリュームの設定ボリュームは、3DMixer の入力範囲にある各バスに明示的に設定することができ、サウンドをミックスする前に増幅します。各ミキサーバス(入力範囲)のボリュームを設定するには、 リスト 11: 入力時のボリューム設定
// busGain は 0.0 〜 1.0(フルボリューム)の範囲
SetInputBusGain(UInt32 mCurrentPlayBus, Float32 busGain)
{
Float32 db = 20.0 * log10(busGain); // db に変換
if (db < -120.0)
db = -120.0; // 最低可聴レベルを -120db に固定
AudioUnitSetParameter(mMixerUnit,
k3DMixerParam_Gain,
kAudioUnitScope_Input,
mCurrentPlayBus,
db,
0);
}
バスストリームフォーマットと FormatConverterAU
注意: ミキサーのバスのストリームフォーマットを設定する場合は、ミキサーはステレオデータをインターリーブされていないものとして受け取ることを想定しています。 AUGraph の接続、初期化、開始設定が完了すれば、3DMixer をデフォルトの出力オーディオユニットに接続することができます。すべての接続が行われ、ノードが正しく設定されたら、 リスト 12: AUGraph の接続、初期化、開始
AUGraphConnectNodeInput (mAUGraph, mMixerNode, 0, mOutputNode, 0);
AUGraphInitialize (mAUGraph);
AUGraphStart(mAUGraph);
AUGraph の破棄
リスト 13: グラフの停止と破棄
AUGraphStop (mAUGraph);
DisposeAUGraph (mAUGraph);
mAUGraph = 0;
まとめCoreAudio の 3DMixer は大変役に立つオーディオツールです。複数のソースのオーディオを処理し、サウンドを立体空間に定位するミキサーの機能は、ゲームには不可欠なものであり、他の無数のアプリケーションでも驚くべき効果をもたらす可能性があります。 参考資料と注意ドキュメントの改訂履歴
掲載日: 2004-06-14 | |||||||||||||||||||||||||||||||||||||||||||||||||||