プログラミングメモ →目次

ダブルバッファで音声を連続的に流す(VC++)

オーディオデータを出力する為に、winmm.libをリンクして、mmsystem.hをインクルードします。ダブルバッファを使って、片方を再生しているうちに、もう片方の中身を用意できて、音声を連続的に流せます。

1.再生の初期化。WINMMAPI MMRESULT WINAPI waveOutOpen(LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD dwCallback, DWORD dwInstance, DWORD fdwOpen)関数で、PCMデバイスを開きます。WINMMAPI MMRESULT WINAPI waveOutPrepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)関数で、データバッファをPCMデバイスに関連付けます。WINMMAPI MMRESULT WINAPI waveOutWrite(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)関数で、データバッファの中身を出力するようにデバイスに書き込みます。

2.再生終了を通知するMM_WOM_DONEメッセージ処理を実装します。片方のバッファの再生が終わったら、もう片方のバッファの再生に入る直前に、MM_WOM_DONEメッセージを受け取れます。このタイミングで、再生済みのバッファの中身を更新します。メッセージのハンドルとメッセージ マップ エントリは、下記のそれぞれのようです。

afx_msg LRESULT OnPlayData(WPARAM wParam, LPARAM lParam)
ON_MESSAGE(MM_WOM_DONE, OnPlayData)

ハンドル関数の中で、waveOutWrite()を呼び出して、再生しようとするバッファの中身をデバイスに書き込みます。

3.再生を停止する処理。WINMMAPI MMRESULT WINAPI waveOutReset(HWAVEOUT hwo)関数で、再生を停止させます。WINMMAPI MMRESULT WINAPI waveOutUnprepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)関数を2回に呼び出して、ダブルバッファをデバイスから切り離します。WINMMAPI MMRESULT WINAPI waveOutClose(HWAVEOUT hwo)関数でデバイスの使用を終了させます。

4.サンプル。周波数が440HZの正弦波を流します。サンプルの中で、サンプル周波数は44100HZで、データのビット数は16で、チャンネル数は1で、バッファのデータ数は4000点です。ソースコード