ひさびさの新記事は、またOggVorbisネタです。ねぎしょ〜ぎのソースをコピペしただけって事は秘密です。
現在配布されているDirectX SDKではDirectMusicのコンポーネントが入っていません。
こんな状況になったのは結構古い話なのですが、DirectX Aug 2007 SDKまでしか対応していなかったようです。
また、Vistaでは事実上DirectSoundの切捨てを行ったので、これを後生大事に使い続けるのも面白くありません。
メンテされなくなったAPIを使い続けるのは気分の良いものではないので 、
ここいらで新しいSoundAPIに乗り換えるのが吉でしょう。
野村XXが乗り換えたのは、2008年夏だったのですが、実はその前からDirectMusicの代替物を探していました。
ところが、OpenAL、XACT、XAudioと次世代のAPIがいくつかつばぜり合いを繰り広げていて、
どれが標準になるのか分からない状況でした。
そんな中で、XAudio2が2008年3月にリリースされ、(個人的には)決着がついたと思っています。
機能的にはDirectSoundを置き換えるもので、DirectMusicのような高級なAPIではありません。
Wav形式を始めとする各種音楽ファイルの読み込みやMIDIの再生などはサポートされていません。
生のWaveデータがストリーミング再生できる機構にGPUのシェーダに近い、エフェクト機構がくっついたものです。
実にシンプルな設計で好感が持てます。
XPとVistaとXBoxのサウンド周りの違いをXAudio2が吸収し、その上にXACT3が乗っかっている形になります。
概要はこちらのサイト(英語)を見ると分かりやすいかと。
XAudio2はSourceVoiceとSubmixVoiceとMasteringVoiceから出来ています。
SourceVoiceはWaveデータが置いてあるメモリ領域+それに付随するデータ(音量やピッチ)と考えれば良いでしょう。
このSourceVoiceに対してエフェクトをかける機構がxAPOと呼ばれるものです。
複数のSourceVoiceをミックスするのが、SubmixVoiceです。
SourceVoiceの入力が生のWaveデータであるのに対し、
SubmixVoiceはSourceVoiceの出力が入力になるというだけの違いです。
MasteringVoiceは、複数のSourceVoiceとSubmixVoiceを一つにまとめて、スピーカーに送ります。
要は、これら3つの要素がツリー状に繋がっている訳です。
一番シンプルなプログラムは、以下の通りです。
1. XAudio2CreateでXAudio2オブジェクトを作る
2. XAudio2のメンバ関数のCreateMasteringVoiceでMasteringVoiceを作る
3. 同様にCreateSourceVoiceでSourceVoiceを作る
4. XAUDIO2_BUFFER型のバッファにPCMデータを書き込む
5. SourceVoiceのメンバ関数SubmitSourceBuffer、Startを使いサウンドを再生する
6. 同様にStop、DestroyVoiceを使ってサウンドを停止する
7. MasteringVoiceのメンバ関数DestroyVoiceでMasteringVoiceを破棄
8. XAudio2のメンバ関数ReleaseでXAudio2オブジェクトを破棄
簡単ですね。
4のPCMデータ書き込みの所で、Waveファイルから読み込むかOggVorbisから読み込むか、
はたまた別のファイルフォーマットを読み込むかは用途次第です。
今回はWaveフォーマットはXAudioWave::Loadの中で地道に解析しています。
OggVorbisについてはlibVorbis内のov_readを使っています。
OggVorbisを再生する場合、曲の全てをあらかじめov_readでPCMに変換してしまえば、
後の処理はWaveの再生と同じです。
実際には、変換時間やメモリの使用量を考えるとストリーミング再生させるのが現実的でしょう。
XAudio2はストリーミング再生が元からサポートされているので、この辺はシンプルに実装できます。
一つのSourceVoiceに対し、複数回SubmitSourceBufferを実行することで、バッファリングが行われます。
一つのバッファの再生が終わるとSetCallback_BufferEndで設定されたコールバック関数が呼び出されるので、
そのバッファに続きのデータを書き込むだけです。
これで最低限音を鳴らすことが出来るのですが、ゲーム用途を考えるとフェード機能くらいはあっても良いかと思います。
そこで、xAPOをつかってフェードを実現します。
XAPOのセットアップは少しややこしいので、MS謹製のヘルパークラスのSampleAPOBase.hを利用します。
SampleAPOBaseを継承したクラスのInitに初期化、DoProcessにエフェクトのコードを書き込みます。
DoProcessの引数で自由なパラメータを渡すことが出来るので、
フェードのパラメータはこれを使ってxAPOに設定します。
まぁこの辺はソースを実際に見た方が早いでしょう。
というわけで、今回のソースです。
いつものことながら、エラーチェックは最低限であり、
このサンプルの使用によるいかなる不幸も当方では責任を負いかねます。
|