マルチメディアAPI(MME)利用してマイクから録音する
(その3)
waveInAddBuffer()にてサウンド入力デバイスにキューイングされたデータブロックにサンプリングした音声データが全て書き込まれると、サウンド入力デバイスより MM_WIM_DATAメッセージが、waveInOpen()の第4引数で指定したウインドウハンドルでメッセージ待ちをしているアプリケーションに送られます。
MM_WIM_DATAメッセージの、第1パラメータ(WPARAM)にサウンド入力デバイスのハンドル、 第2パラメータ(LPARAM)にデータ入力が完了したデータブロック(WAVEHDR構造体)のアドレスが通知されます。
入力が完了したデータブロック(WAVEHDR構造体)のdwFlagsメンバにWHDR_DONEビットがセットされます。
サンプルコードでは、サンプリングが完了したブロックをWAVファイルに保存し、その後に空いている出力データにコピーして出力デバイスからモニタ出力を行います。
最後にデータブロックをクリアして、入力デバイスの入力バッファに再度キューイングします。
(一応WAVファイルへの保存を先に行うのは、その方がWAVファイルにデータを保存した時間分出力データの再生完了が遅れるので、少しでも出力側のバッファの枯渇が防げるかな。という理由です。
まぁ、気休め程度ですが。。。)
サンプルコードを以下に示します。
/****************************************************************************/
/*!
* @brief サウンド入力データの取込み完了通知.
*
* @param [in] hDlg ダイアログのウインドウ・ハンドル.
* @param [in] wh データブロック構造体のポインタ.
*
* @retval なし.
*/
static void SoundInputDone( HWND hDlg, WAVEHDR* wh )
{
if( hWI ){
if( wh->dwBytesRecorded > 0 ){
//! 録画中の場合のみWAVファイルに入力音声データを保存する.
if( RecFlag ){
if( WritedWaveFile( wh->lpData, wh->dwBytesRecorded ) == 0 ){
CloseWaveFile();
}
}
//! 空いている出力データバッファを探して、入力音声データをコピーする.
for( DWORD i = 0; i < 2; i++ ){
if( OutHdr[i].dwBufferLength == 0 && OutHdr[i].lpData ){
memcpy( OutHdr[i].lpData, wh->lpData, wh->dwBytesRecorded );
OutHdr[i].dwBufferLength = wh->dwBytesRecorded;
waveOutWrite( hWO, &OutHdr[i], sizeof(WAVEHDR) );
break;
}
}
//! デバイスに空いた入力バッファをキューイングする.
wh->dwBytesRecorded = 0;
waveInAddBuffer( hWI, wh, sizeof(WAVEHDR) );
}
}
}