unsigned directSoundBufferUser::playThreadProc(void *datasource) { directSoundBufferUser *du ; du = (directSoundBufferUser *)datasource ; du->pDSBuffer->Play(0, 0, DSBPLAY_LOOPING) ; BOOL fileEndFound ; // ファイルが終了したらTRUEになる(但し、今回の読み込みで終わる、という場合はまだ立たない) fileEndFound = FALSE ; int lastBlock ; lastBlock = -1 ; for(;;) { if(*(volatile BOOL *)&du->stopCommand) { // 停止命令が出ているので直ちに停止する du->pDSBuffer->Stop() ; du->pcmSource->seek(0) ; // 次の再生時には先頭から再生するように du->pDSBuffer->SetCurrentPosition(0) ; _endthreadex(0) ; return 0 ; } // 再生位置通知イベント待ち DWORD ans ; ans = WaitForMultipleObjects(3, du->notifyEvent, FALSE, 100) ; if(ans == WAIT_TIMEOUT) { // 命令がきていないかチェック continue ; } if(ans >= WAIT_ABANDONED_0) { MessageBox(NULL, "WaitForMultipleObjectsで異常な値が返りました", "directSoundBufferUser error", MB_OK|MB_ICONEXCLAMATION) ; du->pDSBuffer->Stop() ; _endthreadex(2) ; return 2 ; } ans = ans - WAIT_OBJECT_0 ; if(ans == lastBlock) { // 同じブロックが2回連続する事は無い。これはこのバッファへの通知ではないので無視する continue ; } DWORD lockStartPosition ; lockStartPosition = 0 ; // どこからロックするか if(ans == 0) { lockStartPosition = du->bufferLength / 2 ; } else if(ans == 1) { lockStartPosition = 0 ; } // 正しく再生位置が通知位置に到達している事を確認する // 音楽を再生中に他の音を再生すると、偶に他の音の通知を受け取ってしまう場合がある為 // ここで通知の正当性を確認する必要がある // DirectSoundBuffer8::GetCurrentPositionによって再生カーソルの位置を取得し、 // その位置がnotifyPosition[ans].dwOffsetと同じか後ろにあり、且つoneSecBytes/2を // 超えない範囲に留まっている事を確認する。 DWORD playPosition ; du->pDSBuffer->GetCurrentPosition(&playPosition, NULL) ; if((du->notifyPositions[ans].dwOffset > playPosition) || ((du->notifyPositions[ans].dwOffset+(du->bufferLength/2)) < playPosition)) { // 再生位置がおかしいので恐らくこのバッファへの通知ではないと判断する continue ; } lastBlock = ans ; if(fileEndFound) { // ファイルは終わっているがループフラグが立っている場合は最初から再生をやりなおす if(du->loopFlg) { du->pcmSource->seek(0) ; du->pDSBuffer->SetCurrentPosition(0) ; fileEndFound = FALSE ; } else { // 既にファイルは終わっているのでサウンド再生も終わらせる du->pDSBuffer->Stop() ; du->pcmSource->seek(0) ; du->pDSBuffer->SetCurrentPosition(0) ; _endthreadex(0) ; return 0 ; } } LPVOID soundBuffer ; DWORD lockedBytes ; if(FAILED(du->pDSBuffer->Lock(lockStartPosition, du->bufferLength/2, &soundBuffer, &lockedBytes, NULL, NULL, 0))) { MessageBox(NULL, "サウンドバッファのロックに失敗しました", "directSoundBufferUser error", MB_OK|MB_ICONEXCLAMATION) ; du->pDSBuffer->Stop() ; _endthreadex(3) ; return 3 ; } int filled ; filled = du->pcmSource->fillBuffer((char *)soundBuffer, du->bufferLength/2) ; du->pDSBuffer->Unlock(soundBuffer, du->bufferLength/2, NULL, 0) ; if(filled == 0) { fileEndFound = TRUE ; } } return 0 ; // このreturnに来ることはない }