第3章 ステートとその操作

大多数であるOpenALオブジェクトのステートデータはalGet【オブジェクトの種類】で取得、al【オブジェクトの種類】で設定します。現在のエラー状態、ドップラー効果のパラメータ、距離モデルのようなOpenALコンテキストでグローバスなステート情報もあります。

第1節 ステートの取得

第1項 シンプルな取得

グローバルなステートを取得する時、OpenGLのように、OpenALはシンプルなインタフェースを用います。下記の関数は列挙子のセットを受けとります。

void alGetBooleanv(ALenum paramName, ALboolean *dest);
void alGetIntegerv(ALenum paramName, ALint *dest);
void alGetFloatv(ALenum paramName, ALfloat *dest);
void alGetDoublev(ALenum paramName, ALdouble *dest);
ALboolean alGetBoolean(ALenum paramName);
ALint alGetInteger(ALenum paramName);
ALfloat alGetFloat(ALenum paramName);
ALdouble alGetDouble(ALenum paramName);

AL_DOPPLER_FACTOR、AL_SPEED_OF_SOUND、AL_DISTANCE_MODELが正当な値です。destがNULLの時、暗黙のうちに無視されます。paramNameの設定に誤りがあった場合、AL_INVALID_ENUMが返されます。destに必要なメモリの総量は実際のステートの要求に依存します。

表3–1 数値クエリの定義
名前説明
AL_DOPPLER_FACTORドップラー効果における誇張因数(訳注:どの程度効果を掛けるかの係数です)
AL_SPEED_OF_SOUND速度の単位と同じ単位による音速
AL_DISTANCE_MODEL現在の距離モデル

第2項 文字列の取得

アプリケーションは現在のOpenALコンテキストのグローバルステート情報を取得する事が出来ます。alGetString関数は定数文字列へのポインタを返すでしょう。妥当なparamNameはAL_VERSION、AL_RENDERER、AL_VENDORおよびAL_EXTENSIONS、OpenALで定義されたエラーコードです。もし妥当でない値であった場合、AL_INVALID_ENUMがセットされNULLが返されるでしょう。

const ALchar * alGetString(ALenum paramName);
表3–2 文字列クエリの定義(エラーコードを除く)
名前説明
AL_VERSION『【仕様のメジャーバージョン】.【仕様のマイナーバージョン】 【追加のベンダのバージョン情報】』というフォーマットのバージョン文字列
AL_RENDERERレンダラ固有の情報
AL_EXTENSIONS有効なエクステンションをスペース区切りしたもの

第2節 時間と周波数について

既定ではOpenALはそれぞれ時間の単位に[秒]、周波数の単位に[Hz](ヘルツ)を用います。持続時間、待ち時間、遅延時間やその他時間のパラメータを決める変数に使う浮動小数点数および整数の1は1秒とされます。周波数について、基本単位は[1/秒]あるいは[Hz]です。換言するとサンプリング周波数とカットオフ周波数やフィルタの周波数パラメータはヘルツで表現されます。

第3節 空間と距離について

OpenALは距離の計測の単位を定義しません。アプリケーションはメートル、インチ、パーセクなど自由に各自の単位を用いる事が出来ます。OpenALは距離による音声の自然減衰のシミュレーションおよびこの効果の誇張/縮小手段を提供します。しかしながらエフェクトの結果はアプリケーションがソースおよびリスナの設定に使った距離の単位に依存しません。OpenALの計算は縮尺不変です。

仕様書は距離をユークリッド計算、およびもし二つのソースがユークリッド距離に考慮して並んでいる場合、実装で使われる距離の計算はその順番を保つようになっていると仮定します。

第4節 距離による減衰

サンプルは普通、選ばれた形式や圧縮法のダイナミックレンジ全体を使い、現実世界の強度とは独立です。例えばジェットエンジンと時計仕掛けはともに最大の幅のサンプルとなるでしょう。そして、アプリケーションは相対的な違いを考慮してソースゲインを調整しなければならないでしょう。

そしてソースゲインは距離により減衰します。ソースの減衰効果は多くの要素に依存し、距離減衰の総量とソースおよびリスナのゲインは関与する要素の一つに過ぎません。

たとえもしソースおよびリスナのゲインが1.0を越えたとしても(保証されたダイナミックレンジを越えた増幅)、距離やその他の減衰は結果的に総ゲインが1.0を下回る値に制限されるかもしれません。

OpenALは現在、距離減衰に関して、疑似IASIG I3DL2モデルを含んだ3つの動作モードをサポートしています。アプリケーションはコンテキスト毎に、それらのモデルから1つを選ぶか、あるいは距離依存減衰を無効にする事が出来ます。

void alDistanceModel(ALenum modelName);

AL_NONE、AL_INVERSE_DISTANCE、AL_INVERSE_DISTANCE_CLAMPED、AL_LINEAR_DISTANCE、AL_LINEAR_DISTANCE_CLAMPED、AL_EXPONENT_DISTANCEおよびAL_EXPONENT_DISTANCE_CLAMPEDが正当な引数です。

AL_NONEは全てのソースについて、全ての距離減衰計算を無視します。実装はこの状況に最適化されている事が望まれます。

AL_INVERSE_DISTANCE_CLAMPEDはAL_REFERENCE_DISTANCEがリファレンスの距離でそれがゲインが固定される距離を下回っているIASIG I3DL2モデルです。AL_INVERSE_DISTANCEはAL_REFERENCE_DISTANCEがどんなゲイン固定をも伴わないことを除き、IASIG I3DL2と等価です。

線形モデルは物理的に正確ではありませんが、規定距離を超えたソースについて完全な減衰をさせる事が出来ます。

OpenALの実装はまだ、必要に応じてどんな範囲のゲイン固定も適応出来ます。現在の距離モデル選択はalGetInteger{v}関数とAL_DISTANCE_MODELで取得出来ます。

全ての距離モデルについて、公式で計算する事ができない時はソースは減衰されません。例えば、AL_REFERENCE_DISTANCEをAL_MAX_DISTANCEにして線形モデルを使用した場合、ゲインの方程式はゼロ除算エラーとなります。このとき、そのソースについて減衰はありません。

既定の減衰モデルはAL_INVERSE_DISTANCE_CLAMPEDです。

第1項 反比例距離ロールオフモデル

下記の公式は反比例距離減衰モデルで定義された距離減衰を示します。

gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE + AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE));

ここで使われているAL_REFERENCE_DISTANCEパラメータはソース毎にAL_REFERENCE_DISTANCEとして設定/取得できる属性です。AL_REFERENCE_DISTANCEは実装が有効なダイナミックレンジにする為にAL_GAINを固定しない限り、リスナがAL_GAINを感じるだろう距離です。AL_ROLLOFF_FACTORはソース毎のパラメータで、アプリケーションは減衰を増減させる事により、ソースそれぞれの範囲を増減することができます。既定値は1です。

第2項 反比例距離固定モデル

これはAL_REFERENCE_DISTANCEを下回る距離であった場合ゲインを固定する事を保証するよう拡張した反比例距離ロールオフモデルです。このモードはIASIG I3DL2距離モデルと等価です

distance = max(distance,AL_REFERENCE_DISTANCE);
distance = min(distance,AL_MAX_DISTANCE);
gain = AL_REFERENCE_DISTANCE / (AL_REFERENCE_DISTANCE + AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE));

反比例距離固定モデルのグラフ

第3項 線形距離ロールオフモデル

このモデルはソース–リスナ間距離が増加するに伴い、線形にゲインが衰えるものです。

distance = min(distance, AL_MAX_DISTANCE) // avoid negative gain
gain = (1 - AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE) / (AL_MAX_DISTANCE – AL_REFERENCE_DISTANCE))

第4項 線形距離固定モデル

これはAL_REFERENCE_DISTANCEを下回る距離であった場合ゲインを固定する事を保証するよう拡張した線形モデルです。

distance = max(distance, AL_REFERENCE_DISTANCE)
distance = min(distance, AL_MAX_DISTANCE)
gain = (1 – AL_ROLLOFF_FACTOR * (distance - AL_REFERENCE_DISTANCE) / (AL_MAX_DISTANCE – AL_REFERENCE_DISTANCE))

線形距離固定モデルのグラフ

第5項 指数距離ロールオフモデル

このモデルはソース–リスナ間距離が増加するに伴い、指数的にゲインが衰えるものです。

gain = (distance / AL_REFERENCE_DISTANCE) ^ (-AL_ROLLOFF_FACTOR)

^は指数を意味し、左側を右側の値だけ乗じる事となります。

第6項 指数距離固定モデル

これはAL_REFERENCE_DISTANCEを下回る距離であった場合ゲインを固定する事を保証するよう拡張した指数モデルです。

distance = max(distance, AL_REFERENCE_DISTANCE)
distance = min(distance, AL_MAX_DISTANCE)
gain = (distance / AL_REFERENCE_DISTANCE) ^ (-AL_ROLLOFF_FACTOR)

指数距離固定モデルのグラフ

第5節 増幅・減衰に関係するステート

増幅/減衰は縮尺因数の乗算を取り替えますが、固定演算には為されません。様々な、ゲインに関係する操作が適用される順序は、

  1. 最小(AL_REFERENCE_DISTANCE)および最大(AL_MAX_DISTANCE)のしきい値を含む距離減衰が最初に計算されます。
  2. 結果はその後、ソースのゲイン(AL_GAIN)が乗算されます。
  3. もしソースが指向性である(AL_CONE_INNER_ANGLEがAL_CONE_OUTER_ANGLEより少ない)とき、角度依存減衰がAL_CONE_OUTER_GAINにより計算され、距離依存減衰と掛け算されます。結果のリスナ–ソース間の角度・距離による減衰因数にはソースのAL_GAINが乗算されます。
  4. この方法で計算された実際のゲインはAL_MIN_GAINおよびAL_MAX_GAINのしきい値に反しているかを比較されます。
  5. 結果は[AL_MIN_GAIN, AL_MAX_GAIN]になるよう保証され、そしてその後、全体的なボリューム調整として与えられたリスナのゲインが乗算されます。実装はハードウェアや実装の制約による必要があれば、リスナゲインを固定する事が出来ます。

第1項 距離によるソースの選択について

DirectSound3Dと互換な反比例固定距離モデルとともに、OpenALはソース毎に、距離的にさらに減衰する事が無いだろう間隔を定義するのに使用出来るAL_MAX_DISTANCE属性を提供しています。

DS3Dの距離減衰モデルおよびそのボリュームの固定は、さらに距離を基準とした、処理によるソース選択(ミュート)メカニズムにより拡張されています。しかしながら、OpenALは距離しきい値を基準とした、処理によるソースの選択をサポートしません。

このとき、OpenALは全てについて選択をサポートしません。距離による選択や束縛されたボリューム、その他評価基準はアプリケーションにまかされます。例えば、アプリケーションがソースが聴こえるかどうかを決定するための洗練された手法を利用しているかもしれません。

特にルールによる選択は必然的に音響人工物(acoustic artifacts)を持ち出します。例えば、もしリスナ–ソース距離が選択しきい値にほぼ等しいが上下にそれている時、ヒステリシスの欠如により飛び出す人工物があるでしょう。

第2項 速度依存のドップラー効果

ドップラー効果は媒体に関するソースおよびリスナの速度、その媒体における音の伝播速度に依存します。物理的に正確な計算がアプリケーションの望み通りの結果にならないかもしれないとき、アプリケーションはドップラー効果を強めたり弱めたりしたいかもしれません。周波数シフト(ピッチの変化)の総量はリスナとソースの視線にそった、それらのスピードに比例します。

OpenALに実装されたドップラー効果は下の公式により説明されます。リスナとソースを考慮した媒体(空気、水)の動きの効果は無視されます。

SS: AL_SPEED_OF_SOUND = 音速(既定値は343.3)
DF: AL_DOPPLER_FACTOR = ドップラー因数(既定値は1.0)
vls: リスナの速度のスカラ(ソースからリスナへ向かうベクタへの投射によるスカラ)
vss: ソースの速度のスカラ(ソースからリスナへ向かうベクタへの投射によるスカラ)
f: 対象のサンプルの周波数
f': ドップラー効果によりシフトした周波数

vlsとvssの図的表現を示します。

vlsとvssを図示したもの

vlsとvssの三次元数学的表現を示します。

Mag(vector) = sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z)
DotProduct(v1, v2) = (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z)
SL = ソースからリスナへ向かうベクトル
SV = ソースの速度ベクトル
LV = リスナの速度ベクトル

(訳注:Magは引数vectorのノルム、DotProductは引数v1、v2の内積を求める関数です。)

vls = DotProduct(SL, LV) / Mag(SL)
vss = DotProduct(SL, SV) / Mag(SL)

ドップラー効果の計算は、

vss = min(vss, SS/DF)
vls = min(vls, SS/DF)
f' = f * (SS - DF*vls) / (SS - DF*vss)

音速とドップラー因数のコントロールを提供する、現在のコンテキストでグローバルな2つのAPI呼び出しがあります。AL_DOPPLER_FACTORは計算結果によるドップラー効果のピッチシフトを強めたり弱めたりする、ソースおよびリスナの速度の単純な縮尺です。

void alDopplerFactor(ALfloat dopplerFactor);

負数はAL_INVALID_VALUEエラーを生むでしょうし、コマンドは無視されます。既定値は1です。現在の設定はalGetFloat{v}とAL_DOPPLER_FACTORを用いて取得する事が出来ます。実装はAL_DOPPLER_FACTORに0が設定された時、実質的に効果を無効にするように最適化しても良いです。

AL_SPEED_OF_SOUNDはアプリケーションにドップラー効果計算に使う基準(比例)速度を変更する事を許可します。ソースおよびリスナの速度は音速と同じ単位で表現されるべきです。

void alSpeedOfSound(ALfloat speed);

負数やゼロはAL_INVALID_VALUEエラーを生むでしょうし、コマンドは無視されます。既定値は343.3です(速度単位としてメートルを採用した、空気中の媒体伝播です)。現在の設定はalGetFloat{v}とAL_SPEED_OF_SOUNDを用いて取得する事が出来ます。

距離と速度の単位は完全に、互いに独立しています。なので望むならばそれぞれに違う単位を使う事も可能です。

OpenAL 1.0に関するOpenAL実装者のためのメモ

OpenAL 1.1のドップラー効果実装はOpenAL 1.0のそれと違います。何故ならば古い実装は混乱していたり、安定して実装されていないためです。新たな『音速』プロパティは1.1の実装を、古い実装に比べより直感的にしました。もしあなたの実装がAL_DOPPLER_VELOCITYパラメータをサポートしたい場合(alDopplerVelocity呼び出しは1.0のアプリケーションが1.1のライブラリとリンク出来るようにする為のエントリポイントとして残るでしょう)、上の公式は、次のように変化させる事が出来ます。

vss = min(vss, (SS * DV)/DF)
vls = min(vls, (SS * DV)/DF)
f' = f * (SS * DV - DF*vls) / (SS * DV - DF*vss)

OpenAL 1.1のプログラマは(既定で1となっている)AL_DOPPLER_VELOCITYを今後使うべきではありません。