方式は至ってシンプル。
サウンド系統を制御するスレッド(サウンド制御スレッド)というのを作り、VGEAPIが発音指示をしたスロット番号の効果音の波形データ(PCM)をセカンダリバッファに書き込む・・・という感じ。
サウンド制御スレッドの処理内容は、下図のような感じ。
ds_bufという関数がスロット情報の波形データを合成する処理です。
合成されたデータ(buf)をセカンダリバッファ(lpBuf)へコピーして、発音して、停止するのを待って(WaitForSingleObject)というのを繰り返すだけ。
スロット情報には、「発音するか?」というフラグと位置情報を持っていて、セカンダリバッファサイズ分の音声情報がds_bufでコピー&ポジショニングします。ds_bufの実装は下図。
「合成します」とか言いながら、現時点ではプライオリティが高い(スロット番号が小さい)効果音だけ優先的に鳴らす手抜工事の状態ですが、まぁ、とりあえずこれで音は鳴りました。
しかし、若干原音と違う・・・。
データ変換にミスった訳ではなさそうだから、バッファリングに問題がありそう。
現状、セカンダリバッファは50ms分(=22050×1ch(mono)×2(16bit)÷20=2205byte)にしているのですが、どうもこれだと誤差分によるノイズの影響が大きいのかもしれません。50msということは秒間20fpsだから、リアルタイム性(描画処理=60fpsとの誤差)を考慮すると、その辺が限界だと思いますが。
これは、セカンダリバッファを2面構造にして対処する必要があるのだろうか・・・?
音声周りのプログラミングに関しては、素人同然なので、難産が続きそうです。
追記:この問題は、セカンダリバッファを100ms(10fps)分にすることで解消。
・・・妥協しました。
でも、体感上、気にならない程度のリアルタイム性は確保できたので、ヨシとします。
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。