目次
Sound API
Platform | API |
---|---|
Android NDK | OpenSL ES / OpenMAX |
iOS | OpenAL |
WindowsPhone | XAudio2 |
Windows | DirectSound / DirectShow / XAudio2 |
Mac OS X | OpenAL (Core Audio) |
Linux | ALSA |
API | PCM (on memory) | Audio Stream | 3D sound |
---|---|---|---|
Android NDK OpenSL ES | Y | Y | |
Android NDK OpenMAX AL | |||
iOS / OSX OpenAL | Y | N | Y |
Windows DirectSound 8 | Y | N | Y |
Windows DirectShow | Y |
- ↑空欄は未確認。実装により機能差があります。
- PCM はストレートのみ。OpenSL ES は再生可能な周波数固定。
Game と Sound API
レガシーなゲームに必要なサウンド機能は大きく分けて 2種類あります。
- 効果音
- できるだけ低レイテンシで再生可能なこと
- ワンショット
- 多重再生
- BGM
- MIDI かストリームによりメモリ消費を抑える
- Loop 再生が可能。できれば Loop ポイントを指定できることが望ましい
多くの場合効果音はオンメモリのシンプルな PCM で、同じデータを多重に再生可能です。 BGM は手軽かつリソース管理が簡単なストリーム再生が用いられます。
現在はハードウエアの高機能化、ゲーム内容の多様化により、必ずしもこの通りではありません。
API 構成
多くの API は下記の構造を持っています。
- Engine
- Player Object
- Buffer Object
- Stream API
Engine
Application 毎の Context のようなものです。 リソース管理、各種 Object 管理を行います。
Player
データを再生するチャンネルに相当します。 多重再生を行う場合は、Player を複数用意します。 ハードウエアや API 仕様により、ミックス可能なプレイヤー(チャンネル)数には上限があります。
Buffer
実際に再生を行う PCM データです。 ハードウエアがサポートしているフォーマットに制限されます。
動的に Buffer に書き込みを行うストリーム再生を行う場合は、複数の Buffer を Queue として扱います。 Buffer 毎に再生完了 Event が発生するので、そのタイミングで次の Buffer を Player に渡します。
Stream API
ストリーム再生をサポートする API が用意されている場合があります。 Queue の管理を行ってくれるものから、ファイル名や URL を指定するだけで全部自動で再生してくれるものまでさまざまです。
どの程度の機能を持っているのかは API に依存します。
OpenSL ES
Windows の COM Object によく似た API 構造を持っています。 そのため名称とは裏腹に使い方は OpenGL よりも DirectX (DirectShow) に似ています。
COM と異なるのは、Object と Interface が完全に分かれていること。 インスタンスを持っているのは Object だけで、Interface は Release (Destroy) する必要がありません。
Interface は C言語から呼び出せる構造になっています。 lpVtbl を経由しないので実装に依存しませんが、C++ からの呼び出しでも第一引数が必要となっています。
再生するデータが Buffer Object を持たない構造です。 PCM などのサウンドデータは自分でメモリ管理します。
その代わり再生可能なフォーマットに制限があり、Android NDK 版では対応する周波数が 9種類程度に固定されています。 おそらくバッファオブジェクトを持つ他のフォーマットと違い、ロード時にハードウエアが対応しているフォーマットに変換できないためと思われます。
再生には Player が必要です。 再生するデータのパラメータが異なる場合は、新たな Player が必要になります。
Android NDK の OpenSL ES ではすべての API が使えるわけではなく、Caps 等対応していない Interface も多数あります。 反対に Android 向けに単純化した、専用の API も用意されています。 Android 4.0 からは OpenMAX に対応しており、OpenSL ES は事実上 OpenMAX の一部として動作しています。
Android 版の対応フォーマット
- unsigned 8bit / signed 16bit
- mono / stereo
- 8KHz, 11.025KHz, 12KHz, 16KHz, 22.05KHz, 24KHz, 32KHz, 44.1KHz, 48KHz
なお Locator の指定によりデータ配置の自由度が非常に高く、ファイル名や URI 指定でメモリ以外のデータ再生も可能です。
Object | Create Object | Interface | QueryInterface | ||
---|---|---|---|---|---|
Buffer Object | 無し | – | – | – | – |
Player Object | あり | SLObjectItf | EngineObject→CreateAudioPlayer() | SLPlayItf | PlayerObject→GetInterface( SL_IID_PLAYER ) |
OpenAL
名称通り OpenGL によく似ています。
操作対象(つまり this 相当)は第一引数で渡すので、OpenGL のようにいちいち Bind する必要がありません。 その分、OpenGL よりも明確でより扱いやすい構造となっています。
Buffer を作り、Player (Source) 経由で再生を行います。 非常にわかりやすい API です。 上位 API として Linux, Windows でも利用可能。
Object | Create Object | Interface | QueryInterface | ||
---|---|---|---|---|---|
Buffer Object | あり | ALuint | alGenBuffers() | ||
Player Object | あり | ALuint | alGenSources() |
DirectSound 8
あくまで Buffer が主であって Player Object がありません。 再生機能は Buffer のメソッドのひとつです。
DirectX7 以前の Direct3D レンダリングが、Surface に対するメソッドとして実装されていたことによく似ています。
そのため同じ Buffer のデータを多重で鳴らすことができず、 ゲームでは必要に応じて Buffer を複製することになります。
Object | Create Object | Interface | QueryInterface | ||
---|---|---|---|---|---|
Buffer Object | あり | IDirectSoundBuffer | DS→CreateSoundBuffer() | ||
Player Object | 無し | – | – |
OpenMAX
OpenSL に対するちょうど DirectShow のような位置づけです。 オーディオだけでなく Video を含めた Multi media API となっています。
API 構造は OpenSL と同一で、COM のように Object から必要な Interface を取り出して呼び出します。 オーディオ部分は OpenSL と重複しますが、名前が違うだけで API の使い方も命令も同一です。 内部構造的にも OpenMAX と OpenSL の実装は、部分的に共有されているようです。
OpenSL ES 同様、Android NDK では Android 独自の API があります。