|
[リスト6-1] :
#define LOOPMAX 5 //sndPlaySound(高レベルオーディオ) sample4(){ if(1){ //●SND_SYNCで呼び出す //・再生中はプログラム停止してしまう //・一つのWAVEファイルを最後まで再生し終えなくてはいけない SetWindowText( hwnd, "sndPlaySound, SND_SYNC" ); Animate( TRUE ); for( int i = 0; i < LOOPMAX; i ++ ) { sndPlaySound( "tada.wav", SND_SYNC ); Animate(); } } if(1){ //●SND_ASYNCで呼び出す //・再生中、プログラムは継続実行される //・waveの長さを事前に知っておかなくてはいけない //・できたとしても、waveと絵の同期が完全ではない。 SetWindowText( hwnd, "sndPlaySound, SND_ASYNC" ); Animate( TRUE ); for( int i = 0; i < LOOPMAX; i ++ ) { sndPlaySound( "tada.wav", SND_ASYNC ); for( int j = 0; j < 4; j ++ ) { Animate2( TRUE ); DWORD dwTime = GetTickCount(); while( dwTime + 500 > GetTickCount() ) { //この間に別の処理が可能 //実際はSetTimer()を使ったほうがよい Animate2(); } Animate(); } } } } ///////////////////////////////////////// // Animate() // 動画の1コマを再生するダミーの関数です ///////////////////////////////////////// void Animate( BOOL fInit = FALSE ) { static nAni; if( fInit ) nAni = 0; nAni++; HDC hdc = GetDC( hwnd ); char sz[100]; wsprintf( sz, "%dコマ目 ", nAni ); TextOut( hdc, 0, 0, sz, lstrlen(sz) ); ReleaseDC( hwnd, hdc ); } ///////////////////////////////////////// // Animate2() // WAV再生中もプログラムが動き続けていることの確認のための関数です ///////////////////////////////////////// void Animate2( BOOL fInit = FALSE ) { static nAni; if( fInit ) nAni = 0; nAni++; HDC hdc = GetDC( hwnd ); BitBlt( hdc, nAni, 32, 1, 32, NULL, 0, 0, DSTINVERT ); ReleaseDC( hwnd, hdc ); MSG msg; while( PeekMessage( &msg, NULL, NULL, NULL, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } }
open filename.wav type waveaudio alias MYWAVE set MYWAVE time format samples play MYWAVE from 1 wait close MYWAVE実際は,mciSendString()を使うので,一つ一つのコマンドはmciSendString()のパラメータになります.
[リスト6-2] :
HWND hwnd; BOOL fNotify; //■MCIコマンド(高レベルオーディオ) sample5(){ mciSend( "open c:\\windows\\tada.wav type waveaudio alias MYWAVE" ); mciSend( "set MYWAVE time format samples" ); if(1){ //●4回に分けて再生(waitする) //・再生中はプログラム停止してしまう //・waveと絵の同期は完全になるが、音がとぎれてしまう SetWindowText( hwnd, "MCI, wait" ); Animate( TRUE ); mciSend( "status MYWAVE length" ); DWORD len = atoi( szMciRes ) / 4; for( int i = 0; i < LOOPMAX; i ++ ) { for( int j = 0; j < 4; j ++ ) { char sz[256]; fNotify = FALSE; wsprintf( sz, "play MYWAVE from %d to %d wait", 1 + len * j, len + len * j ); mciSend( sz ); Animate(); } } } if(1){ //●4回に分けて再生(notifyする) //・再生中、プログラムは継続実行される //・waveと絵の同期は完全になるが、音がとぎれてしまう SetWindowText( hwnd, "MCI, notify" ); Animate( TRUE ); mciSend( "status MYWAVE length" ); DWORD len = atoi( szMciRes ) / 4; char sz[256]; for( int i = 0; i < LOOPMAX; i ++ ) { for( int j = 0; j < 4; j ++ ) { fNotify = FALSE; wsprintf( sz, "play MYWAVE from %d to %d notify", 1 + len * j, len + len * j ); mciSend( sz ); Animate2( TRUE ); while( TRUE ) { //この間に別の処理が可能 Animate2(); if( fNotify ) break; } Animate(); } } } if(1){ //●再生位置を監視する(1回の再生のうち4回動画する例) //・再生中、プログラムは継続実行される //・waveと絵の同期は、ほぼ正しい //・遅い SetWindowText( hwnd, "MCI, 再生位置監視" ); Animate( TRUE ); mciSend( "status MYWAVE length" ); DWORD len = atoi( szMciRes ) / 4; for( int i = 0; i < LOOPMAX; i ++ ) { mciSend( "play MYWAVE from 1" ); for( int j = 0; j < 4; j ++ ) { Animate2( TRUE ); while( TRUE ) { //この間に別の処理が可能 Animate2(); if( !mciSend( "status MYWAVE position" ) ) break; DWORD pos = atoi( szMciRes ); if( pos >= len * (j+1) ) break; } Animate(); } } } mciSend( "close MYWAVE" ); } /////////////////////////// // mciSend() // MCIコマンドを実行する関数 /////////////////////////// char szMciRes[1024]; BOOL mciSend( LPSTR lpcmd ) { DWORD dwErr; if( ( dwErr = mciSendString( lpcmd, szMciRes, sizeof(szMciRes), hwnd ) ) != 0 ) { char sz[1024]; mciGetErrorString(dwErr, sz, sizeof(sz) ); MessageBox( NULL, sz, "", MB_OK ); return FALSE; } return TRUE; } /////////////////////////// // WndProc() // ウィンドウプロシージャ /////////////////////////// LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case MM_MCINOTIFY: fNotify = TRUE; return 0; } return DefWindowProc(hwnd , message ,wParam ,lParam); }
[リスト6-3] :
//■waveOut系(低レベルオーディオ) //エラー処理を省いてあります sample6(){ HMMIO hmmio; MMCKINFO ckParent; MMCKINFO ckSub; //WAVファイルのオープン hmmio = mmioOpen( "c:\\windows\\tada.wav", NULL, MMIO_READ ); //"WAVE"チャンク ckParent.fccType = mmioFOURCC( 'W', 'A', 'V', 'E' ); mmioDescend( hmmio, &ckParent, NULL, MMIO_FINDRIFF ); //"fmt "チャンク ckSub.ckid = mmioFOURCC( 'f', 'm', 't', ' ' ); mmioDescend( hmmio, &ckSub, &ckParent, MMIO_FINDCHUNK ); DWORD dwFmt = ckSub.cksize; HANDLE hFmt = GlobalAlloc( GMEM_MOVEABLE, dwFmt ); PCMWAVEFORMAT* pFmt = (PCMWAVEFORMAT*)GlobalLock( hFmt ); mmioRead( hmmio, (LPSTR)pFmt, dwFmt ); mmioAscend( hmmio, &ckSub, 0 ); //"data"チャンク ckSub.ckid = mmioFOURCC( 'd', 'a', 't', 'a' ); mmioDescend( hmmio, &ckSub, &ckParent, MMIO_FINDCHUNK ); DWORD dwData = ckSub.cksize; HANDLE hData = GlobalAlloc( GMEM_MOVEABLE, dwData ); LPSTR pData = (LPSTR)GlobalLock( hData ); mmioRead( hmmio, (LPSTR)pData, dwData ); mmioAscend( hmmio, &ckSub, 0 ); //WAVファイルのクローズ mmioClose( hmmio, 0 ); //WAV出力する int i, j; HWAVEOUT hWave; if( pFmt->wf.wFormatTag != WAVE_FORMAT_PCM || waveOutOpen( &hWave, WAVE_MAPPER, (LPWAVEFORMAT)pFmt, NULL, 0, WAVE_FORMAT_QUERY) ) { //エラー:再生できるフォーマットではない } waveOutOpen( &hWave, WAVE_MAPPER, (LPWAVEFORMAT)pFmt, (DWORD)WaveProc, 0, CALLBACK_FUNCTION ); HGLOBAL hHdr[4]; WAVEHDR* pHdr[4]; for( j = 0; j < 4; j ++ ) { hHdr[j] = GlobalAlloc( GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR) ); pHdr[j] = (WAVEHDR*)GlobalLock( hHdr[j] ); } if(1){ //●4回に分けてバッファに送る //・再生中、プログラムは継続実行される //・waveと絵の同期は完全 //・速い SetWindowText( hwnd, "waveOut, 分割バッファ転送" ); Animate( TRUE ); for( i = 0; i < LOOPMAX; i ++ ) { cWaveStock = 0; Animate2( TRUE ); for( j = 0; j < 4; j ++ ) { pHdr[j]->lpData = (BYTE*)pData + ( dwData / 4 ) * j; pHdr[j]->dwBufferLength = dwData / 4; pHdr[j]->dwFlags = 0; pHdr[j]->dwLoops = 0; waveOutPrepareHeader( hWave, pHdr[j], sizeof(WAVEHDR) ); waveOutWrite( hWave, pHdr[j], sizeof(WAVEHDR) ); cWaveStock++; } while( cWaveStock != 0 ) { //この間に別の処理が可能 Animate2(); } for( j = 0; j < 4; j ++ ) { waveOutUnprepareHeader( hWave, pHdr[j], sizeof(WAVEHDR) ); } } } if(1){ //●再生位置を監視する(1回の再生のうち4回動画する例) //・再生中、プログラムは継続実行される //・waveと絵の同期は、ほぼ正しい //・少し遅い SetWindowText( hwnd, "waveOut, 再生位置監視" ); Animate( TRUE ); for( i = 0; i < LOOPMAX; i ++ ) { waveOutReset( hWave ); pHdr[0]->lpData = (BYTE*)pData; pHdr[0]->dwBufferLength = dwData; pHdr[0]->dwFlags = 0; pHdr[0]->dwLoops = 0; waveOutPrepareHeader( hWave, pHdr[0], sizeof(WAVEHDR) ); waveOutWrite( hWave, pHdr[0], sizeof(WAVEHDR) ); cWaveStock = 1; for( j = 0; j < 4; j ++ ) { Animate2( TRUE ); while( TRUE ) { //この間に別の処理が可能 Animate2(); MMTIME mmtime; mmtime.wType = TIME_BYTES; waveOutGetPosition( hWave, &mmtime, sizeof(mmtime) ); if( mmtime.u.cb >= (dwData / 4) * (j+1) ) break; } if( j < 3 ) Animate(); } while( cWaveStock != 0 ); waveOutUnprepareHeader( hWave, pHdr[0], sizeof(WAVEHDR) ); } } for( j = 0; j < 4; j ++ ) { GlobalUnlock( hHdr[j] ); GlobalFree( hHdr[j] ); } waveOutClose( hWave ); GlobalUnlock( hFmt ); GlobalFree( hFmt ); GlobalUnlock( hData ); GlobalFree( hData ); } /////////////////////////////////////////// // WaveProc() // WAVEの再生状況を受け取るコールバック関数 /////////////////////////////////////////// int cWaveStock; void CALLBACK WaveProc( HWAVE hWave, UINT uMsg, DWORD, DWORD, DWORD ) { if( uMsg == WOM_DONE ) { Animate2( TRUE ); Animate(); cWaveStock--; } }