long audio_file_write(Chan *c, void *va, long count, vlong offset) { MMRESULT status; WAVEHDR *hHdr = (WAVEHDR *) NULL; char *hData = NULL; char *p = (char *) va; long ba; long bufsz; long chunk; long total; qlock(&flag_lock); if(waserror()) { qunlock(&flag_lock); nexterror(); } if(!(audio_flags & OUTISOPEN)) error(Eperm); /* check for block alignment */ ba = av.out.bits * av.out.chan / Bits_Per_Byte; if(count % ba) error(Ebadarg); bufsz = av.out.buf * Audio_Max_Buf / Audio_Max_Val; if(bufsz < 1) error(Ebadarg); total = 0; while(total < count) { Again: chunk = min(bufsz, count - total); Drain: WaitForSingleObject(outlock, INFINITE); while(out_buf_count > bufsz) { ReleaseMutex(outlock); sleep(0); goto Drain; } if(out_buf_count == 0) audioerror(waveOutReset(audio_file_out), AUDIOOUT, "wave out reset"); ReleaseMutex(outlock); /* * allocate and lock the memory for the wave header * and data blocks */ hHdr = (WAVEHDR *) malloc(sizeof(WAVEHDR)); if (!hHdr) error(Enomem); hData = malloc(chunk); if (!hData) { free(hHdr); error(Enomem); } /* * initialize the wave header struct */ /* * copy user data into write Q */ memmove(hData, p+total, chunk); hHdr->lpData = hData; hHdr->dwBufferLength = chunk; hHdr->dwBytesRecorded = 0; hHdr->dwUser = chunk; hHdr->dwFlags = 0; hHdr->dwLoops = 0; hHdr->lpNext = 0; hHdr->reserved = 0; status = waveOutPrepareHeader(audio_file_out, hHdr, sizeof(WAVEHDR)); if (audioerror(status, AUDIOOUT, "out prepare header") == -1) { free(hHdr); free(hData); error(Eio); } status = waveOutWrite(audio_file_out, hHdr, sizeof(WAVEHDR)); if (audioerror(status, AUDIOOUT, "out write data") == -1) { waveOutUnprepareHeader(audio_file_out, hHdr, sizeof(WAVEHDR)); free(hHdr); free(hData); error(Eio); } WaitForSingleObject(outlock, INFINITE); out_buf_count += chunk; ReleaseMutex(outlock); total += chunk; } poperror(); qunlock(&flag_lock); osmillisleep(1); /* hack to get around thread scheduler */ return count; }
/* ================== FreeSound ================== */ void FreeSound (void) { int i; Com_Printf( "Shutting down sound system\n" ); if ( pDS ) DS_DestroyBuffers(); if ( hWaveOut ) { Com_Printf( "...resetting waveOut\n" ); waveOutReset (hWaveOut); if (lpWaveHdr) { Com_Printf( "...unpreparing headers\n" ); for (i=0 ; i< WAV_BUFFERS ; i++) waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); } Com_Printf( "...closing waveOut\n" ); waveOutClose (hWaveOut); if (hWaveHdr) { Com_Printf( "...freeing WAV header\n" ); GlobalUnlock(hWaveHdr); GlobalFree(hWaveHdr); } if (hData) { Com_Printf( "...freeing WAV buffer\n" ); GlobalUnlock(hData); GlobalFree(hData); } } if ( pDS ) { Com_Printf( "...releasing DirectSound 8 object\n" ); #ifdef QDSNDCOMPILERHACK pDS->lpVtbl->Release(pDS); #else pDS->Release(); #endif } if ( hInstDS ) { Com_Printf( "...freeing dsound.dll\n" ); FreeLibrary( hInstDS ); hInstDS = NULL; } pDS = NULL; pDSBuf = NULL; pDSPBuf = NULL; hWaveOut = 0; hData = 0; hWaveHdr = 0; lpData = NULL; lpWaveHdr = NULL; dsound_init = 0; wav_init = 0; }
static void purge_output (void) { waveOutReset (dev); wait (); }
void CWaveOut::Reset() { waveOutReset(m_hWave); }
void WaveOut::ClearBuffers(){ waveOutReset(this->waveHandle); }
void cancelPcmOutput (PcmDevice *pcm) { waveOutReset(pcm->handle); }
static void WIN_PlayStop(void) { if (hwaveout) waveOutReset(hwaveout); VC_PlayStop(); }
unsigned int __stdcall SpkrThread(LPVOID Unused) { int i; DWORD bufLen = ((N_SAMPLES * BITS_PER_SAMPLE) / 8); WAVEHDR* pWH; MMRESULT ret; int played; OsMsg *pMsg = NULL; OsIntPtrMsg *pSpeakerMsg = NULL; BOOL bGotMsg ; int n; bool bDone ; static bool sLastRingerEnabled = false; OsStatus res; static bool bRunning = false ; HWAVEOUT hOut = NULL; UINT timerId=0; // Verify that only 1 instance of the MicThread is running if (bRunning) { ResumeThread(hMicThread); return 1 ; } else { bRunning = true ; } ResumeThread(hMicThread); #ifdef OHISTORY /* [ */ WAVEHDR* lastWH[OHISTORY]; int lastInd[OHISTORY]; int last = 0; for (i=0;i<OHISTORY;i++) { lastWH[i] = 0; lastInd[i] = 0; } memset(histOut, 0xff, sizeof(histOut)); lastOut = 0; #endif /* OHISTORY ] */ // Initialize headers for (i=0; i<N_OUT_BUFFERS; i++) { hOutHdr[i] = hOutBuf[i] = NULL; pOutHdr[i] = NULL; } if (openSpeakerDevices(pWH, hOut)) { // NOT using a sound card // Set up a 10ms timer to call back to this routine timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } played = 0; bDone = false ; while (!bDone) { bGotMsg = (gSpeakerStatusQueue->receive(pMsg) == OS_SUCCESS); // when switching devices, ringer to in-call we need to make // sure any outstanding buffers are flushed if (sLastRingerEnabled != DmaTask::isRingerEnabled()) { if (audioOutH) { ret = waveOutReset(audioOutH); } if (audioOutCallH) { ret = waveOutReset(audioOutCallH); } if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutReset", ret, -1, __LINE__); } else { waitForDeviceResetCompletion(); } } if (bGotMsg && pMsg) { pSpeakerMsg = (OsIntPtrMsg*)pMsg; intptr_t msgType = pSpeakerMsg->getData1(); intptr_t data2 = pSpeakerMsg->getData2(); pSpeakerMsg->releaseMsg(); pSpeakerMsg = NULL; pMsg = NULL; switch (msgType) { case WM_ALT_HEARTBEAT: OsSysLog::add(FAC_MP, PRI_DEBUG, "SpeakerThreadWnt invoking MpMediaTask::signalFrameStart from timer message"); res = MpMediaTask::signalFrameStart(); switch (res) { case OS_SUCCESS: frameCount++; break; #ifdef DEBUG_WINDOZE /* [ */ case OS_LIMIT_REACHED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_LIMIT_REACHED\n", frameCount); break; case OS_WAIT_TIMEOUT: // Should bump missed frame statistic osPrintf(" Frame %d: OS_WAIT_TIMEOUT\n", frameCount); break; case OS_ALREADY_SIGNALED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_ALREADY_SIGNALED\n", frameCount); break; default: osPrintf("Frame %d, signalFrameStart() returned %d\n", frameCount, res); break; #else /* DEBUG_WINDOZE ] [ */ case OS_LIMIT_REACHED: case OS_WAIT_TIMEOUT: case OS_ALREADY_SIGNALED: default: // Should bump missed frame statistic break; #endif /* DEBUG_WINDOZE ] */ } // Check for a changed speaker device if (DmaTask::isOutputDeviceChanged()) { DmaTask::clearOutputDeviceChanged() ; closeSpeakerDevices() ; if (audioOutH) { ret = waveOutReset(audioOutH); } if (audioOutCallH) { ret = waveOutReset(audioOutCallH); } if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutReset", ret, -1, __LINE__); } else { waitForDeviceResetCompletion(); } // Kill the hearbeat timer if it exists if (timerId>0) timeKillEvent(timerId); if (openSpeakerDevices(pWH, hOut)) { // Open failed - so start the heartbeat timer timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } continue ; } break ; case WOM_DONE: pWH = (WAVEHDR *) data2; n = (pWH->dwUser) & USER_BUFFER_MASK; #ifdef OHISTORY /* [ */ lastWH[last] = pWH; lastInd[last] = n; last = (last + 1) % OHISTORY; if (N_OUT_BUFFERS == played) { osPrintf("after first %d buffers:", played + 1); osPrintf("\nCall Backs:"); for (i=0; i<OHISTORY; i++) { osPrintf("%c%3d", (0 == (i % 20)) ? '\n' : ' ', histOut[i]); } osPrintf("\n\nMessages:"); for (i=0; i<OHISTORY; i++) { osPrintf("%c%3d", (0 == (i % 20)) ? '\n' : ' ', lastInd[i]); } osPrintf("\n"); } #endif /* OHISTORY ] */ if (DmaTask::isOutputDeviceChanged()) { DmaTask::clearOutputDeviceChanged() ; closeSpeakerDevices() ; if (openSpeakerDevices(pWH, hOut)) { if (timerId>0) timeKillEvent(timerId); timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } continue ; } hOut = selectSpeakerDevice() ; if (hOut) { ret = waveOutUnprepareHeader(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutUnprepareHeader", ret, played, __LINE__); } outPostUnprep(n, false); pWH = outPrePrep(n, bufLen); ret = waveOutPrepareHeader(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutPrepareHeader", ret, played, __LINE__); } ret = waveOutWrite(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutWrite", ret, played, __LINE__); } played++; } OsSysLog::add(FAC_MP, PRI_DEBUG, "SpeakerThreadWnt invoking MpMediaTask::signalFrameStart from WOM_DONE message"); res = MpMediaTask::signalFrameStart(); switch (res) { #ifdef DEBUG_WINDOZE /* [ */ case OS_SUCCESS: frameCount++; osPrintf(" Frame %d: OS_SUCCESSFUL\n", frameCount); break; case OS_LIMIT_REACHED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_LIMIT_REACHED\n", frameCount); break; case OS_WAIT_TIMEOUT: // Should bump missed frame statistic osPrintf(" Frame %d: OS_WAIT_TIMEOUT\n", frameCount); break; case OS_ALREADY_SIGNALED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_ALREADY_SIGNALED\n", frameCount); break; default: osPrintf("Frame %d, signalFrameStart() returned %d\n", frameCount, res); break; #else /* DEBUG_WINDOZE ] [ */ case OS_SUCCESS: frameCount++; break; case OS_LIMIT_REACHED: case OS_WAIT_TIMEOUT: case OS_ALREADY_SIGNALED: default: // Should bump missed frame statistic break; #endif /* DEBUG_WINDOZE ] */ } break; case WOM_CLOSE: // Audio device was closed on us (doesn't happen as far as I // know) bDone = true ; break; default: break; } } else { // Sky is falling, kick out so that we don't spin a high priority // thread. bDone = true ; } // record our last ringer state sLastRingerEnabled = DmaTask::isRingerEnabled(); } // Stop heartbeat timer if it exist if (timerId>0) timeKillEvent(timerId); closeSpeakerDevices() ; bRunning = false ; return 0; }
static DWORD wodReset(WAVEMAPDATA* wom) { TRACE("(%p)\n",wom); return waveOutReset(wom->u.out.hInnerWave); }
/*************************************************************************** * MCIAVI_player [internal] */ static DWORD MCIAVI_player(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) { DWORD dwRet; LPWAVEHDR waveHdr = NULL; unsigned i, nHdr = 0; DWORD numEvents = 1; HANDLE events[2]; double next_frame_us; EnterCriticalSection(&wma->cs); if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame) { dwRet = 0; goto mci_play_done; } events[0] = wma->hStopEvent; if (wma->lpWaveFormat) { if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0) { /* can't play audio */ HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat); wma->lpWaveFormat = NULL; } else { /* fill the queue with as many wave headers as possible */ MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); events[1] = wma->hEvent; numEvents = 2; } } next_frame_us = currenttime_us(); while (wma->dwStatus == MCI_MODE_PLAY) { HDC hDC; double tc, delta; DWORD ret; tc = currenttime_us(); hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0; if (hDC) { while(next_frame_us <= tc && wma->dwCurrVideoFrame < wma->dwToVideoFrame) { double dur; dur = MCIAVI_PaintFrame(wma, hDC); ++wma->dwCurrVideoFrame; if(!dur) break; next_frame_us += dur; TRACE("next_frame: %f\n", next_frame_us); } ReleaseDC(wma->hWndPaint, hDC); } if (wma->dwCurrVideoFrame >= wma->dwToVideoFrame) { if (!(dwFlags & MCI_DGV_PLAY_REPEAT)) break; TRACE("repeat media as requested\n"); wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0; } if (wma->lpWaveFormat) MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); tc = currenttime_us(); if (tc < next_frame_us) delta = next_frame_us - tc; else delta = 0; LeaveCriticalSection(&wma->cs); ret = WaitForMultipleObjects(numEvents, events, FALSE, delta / 1000); EnterCriticalSection(&wma->cs); if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break; } if (wma->lpWaveFormat) { while (wma->dwEventCount != nHdr - 1) { LeaveCriticalSection(&wma->cs); Sleep(100); EnterCriticalSection(&wma->cs); } /* just to get rid of some race conditions between play, stop and pause */ LeaveCriticalSection(&wma->cs); waveOutReset(wma->hWave); EnterCriticalSection(&wma->cs); for (i = 0; i < nHdr; i++) waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR)); } dwRet = 0; if (wma->lpWaveFormat) { HeapFree(GetProcessHeap(), 0, waveHdr); if (wma->hWave) { LeaveCriticalSection(&wma->cs); waveOutClose(wma->hWave); EnterCriticalSection(&wma->cs); wma->hWave = 0; } CloseHandle(wma->hEvent); } mci_play_done: wma->dwStatus = MCI_MODE_STOP; if (dwFlags & MCI_NOTIFY) { TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback); mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), wma->wDevID, MCI_NOTIFY_SUCCESSFUL); } LeaveCriticalSection(&wma->cs); return dwRet; }
void closeSpeakerDevices() { MMRESULT ret; int i ; // Clean up ringer audio if (audioOutH) { ret = waveOutReset(audioOutH); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutReset", ret, -1, __LINE__); } else { waitForDeviceResetCompletion(); } for (i=0; i<N_OUT_BUFFERS; i++) { if (NULL != hOutHdr[i]) { ret = waveOutUnprepareHeader(audioOutH, pOutHdr[i], sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutUnprepareHeader", ret, i, __LINE__); } outPostUnprep(i, TRUE); } } ret = waveOutClose(audioOutH); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutClose", ret, -1, __LINE__); } audioOutH = NULL; waitForSpeakerStatusMessage(WOM_CLOSE); } // Clean up call audio if (audioOutCallH) { ret = waveOutReset(audioOutCallH); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutReset", ret, -1, __LINE__); } else { waitForDeviceResetCompletion(); } for (i=0; i<N_OUT_BUFFERS; i++) { if (NULL != hOutHdr[i]) { ret = waveOutUnprepareHeader(audioOutCallH, pOutHdr[i], sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutUnprepareHeader", ret, i, __LINE__); } outPostUnprep(i, true); } } ret = waveOutClose(audioOutCallH); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutClose", ret, -1, __LINE__); } audioOutCallH = NULL; waitForSpeakerStatusMessage(WOM_CLOSE); } }
int AudioWaveOut::push_pcm_data(char* pbuf, int nlen) { if (pbuf == NULL || nlen <= 0) return -1; if (!m_bInit && !bCanInPCM) { if (FailedCount++ >= 500) { FailedCount = 0; Log::writeMessage(LOG_RTSPSERV, 1, "waveout devicename %s 没有初始化成功 return!", WcharToAnsi(m_DeviceName.c_str()).c_str()); } return -2; } MMRESULT mr = MMSYSERR_NOERROR; PWAVEPERIO hdr = m_wavequeue.front(); if( hdr->hdr.dwFlags & WHDR_DONE || hdr->hdr.dwFlags == 0 ) { mr = waveOutUnprepareHeader(m_outdev, &hdr->hdr, sizeof(WAVEHDR)); if (mr != MMSYSERR_NOERROR) Log::writeMessage(LOG_RTSPSERV, 1, "waveOutUnprepareHeader ERROR devicename %s ", WcharToAnsi(m_DeviceName.c_str()).c_str()); } else { Log::writeMessage(LOG_RTSPSERV, 1, "overrun reset devicename %s ", WcharToAnsi(m_DeviceName.c_str()).c_str()); waveOutReset(m_outdev); } hdr->hdr.dwFlags = 0; hdr->hdr.dwUser = 0; if( nlen > MAX_SUPPORT_PCMPKG_LEN ) { Log::writeMessage(LOG_RTSPSERV, 1, "PCM package len > MAX_SUPPORT_PCMPKG_LEN not play devicename %s ", WcharToAnsi(m_DeviceName.c_str())); return -5; } int dlen = nlen; if( m_bConver32t16 ) { if( awresample( pbuf, nlen, (char*)hdr->buf, &dlen ) != 0 ) Log::writeMessage(LOG_RTSPSERV, 1, "AudioWaveOut resample fail devicename %s ", WcharToAnsi(m_DeviceName.c_str())); } else memcpy(hdr->buf, pbuf, nlen ); hdr->hdr.lpData = (LPSTR)hdr->buf; hdr->hdr.dwBufferLength = dlen; mr = waveOutPrepareHeader(m_outdev, &hdr->hdr, sizeof(WAVEHDR)); if (mr != MMSYSERR_NOERROR){ if (FailedCount++ >= 100) { FailedCount = 0; Log::writeMessage(LOG_RTSPSERV, 1, "waveOutPrepareHeader fail devicename %s ", WcharToAnsi(m_DeviceName.c_str()).c_str()); Uninitialize(); Initialize(const_cast<TCHAR*>(m_DeviceName.c_str()), iChannels, iSamplerate, iSampleperbits); } return -3; } mr = waveOutWrite(m_outdev, &hdr->hdr, sizeof(WAVEHDR)); if (mr != MMSYSERR_NOERROR){ if (FailedCount++ >= 100) { FailedCount = 0; Log::writeMessage(LOG_RTSPSERV, 1, "waveOutWrite fail devicename %s ", WcharToAnsi(m_DeviceName.c_str()).c_str()); Uninitialize(); Initialize(const_cast<TCHAR*>(m_DeviceName.c_str()), iChannels, iSamplerate, iSampleperbits); } return -4; } m_wavequeue.pop(); m_wavequeue.push(hdr); return 0; }
int main(int argc, char* argv[]) { // LPWSTR szFileName;//声音文件名 MMCKINFO mmckinfoParent; MMCKINFO mmckinfoSubChunk; DWORD dwFmtSize; HMMIO m_hmmio;//音频文件句柄 DWORD m_WaveLong; HPSTR lpData;//音频数据 HANDLE m_hData=NULL; HANDLE m_hFormat; WAVEFORMATEX * lpFormat; DWORD m_dwDataOffset; DWORD m_dwDataSize; WAVEHDR pWaveOutHdr; WAVEOUTCAPS pwoc; HWAVEOUT hWaveOut; int SoundOffset=0; int SoundLong=0; int DevsNum; //打开波形文件 if(!(m_hmmio=mmioOpen(argv[1],NULL,MMIO_READ|MMIO_ALLOCBUF))) { //File open Error printf("Failed to open the file.");//错误处理函数 return false; } //检查打开文件是否是声音文件 mmckinfoParent.fccType =mmioFOURCC('W','A','V','E'); if(mmioDescend(m_hmmio,(LPMMCKINFO)&mmckinfoParent,NULL,MMIO_FINDRIFF)) { printf("NOT WAVE FILE AND QUIT"); return 0; } //寻找 'fmt' 块 mmckinfoSubChunk.ckid =mmioFOURCC('f','m','t',' '); if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK)) { printf("Can't find 'fmt' chunk"); return 0; } //获得 'fmt '块的大小,申请内存 dwFmtSize=mmckinfoSubChunk.cksize ; m_hFormat=LocalAlloc(LMEM_MOVEABLE,LOWORD(dwFmtSize)); if(!m_hFormat) { printf("failed alloc memory"); return 0; } lpFormat=(WAVEFORMATEX*)LocalLock(m_hFormat); if(!lpFormat) { printf("failed to lock the memory"); return 0; } if((unsigned long)mmioRead(m_hmmio,(HPSTR)lpFormat,dwFmtSize)!=dwFmtSize) { printf("failed to read format chunk"); return 0; } //离开 fmt 块 mmioAscend(m_hmmio,&mmckinfoSubChunk,0); //寻找 'data' 块 mmckinfoSubChunk.ckid=mmioFOURCC('d','a','t','a'); if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK)) { printf("Can't find 'data' chunk"); return 0; } //获得 'data'块的大小 m_dwDataSize=mmckinfoSubChunk.cksize ; m_dwDataOffset =mmckinfoSubChunk.dwDataOffset ; if(m_dwDataSize==0L) { printf("no data in the 'data' chunk"); return 0; } //为音频数据分配内存 lpData=new char[m_dwDataSize]; if(!lpData) { printf("\ncan not alloc mem"); return 0; } if(mmioSeek(m_hmmio,m_dwDataOffset,SEEK_SET)<0) { printf("Failed to read the data chunk"); return 0; } // m_WaveLong=mmioRead(m_hmmio,lpData,SoundLong); m_WaveLong=mmioRead(m_hmmio,lpData,m_dwDataSize); if(m_WaveLong<0) { printf("Failed to read the data chunk"); return 0; } //检查音频设备,返回音频输出设备的性能 if(waveOutGetDevCaps(WAVE_MAPPER,&pwoc,sizeof(WAVEOUTCAPS))!=0) { printf("Unable to allocate or lock memory"); return 0; } //检查音频输出设备是否能播放指定的音频文件 DevsNum = WAVE_MAPPER; if(waveOutOpen(&hWaveOut,DevsNum,lpFormat,NULL,NULL,CALLBACK_NULL)!=0) { printf("Failed to OPEN the wave out devices"); // return 0; } //准备待播放的数据 pWaveOutHdr.lpData =(HPSTR)lpData; pWaveOutHdr.dwBufferLength =m_WaveLong; pWaveOutHdr.dwFlags =0; pWaveOutHdr.dwLoops = 10; if(waveOutPrepareHeader(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0) { printf("Failed to prepare the wave data buffer"); return 0; } printFlags(pWaveOutHdr.dwFlags, "after [waveOutPrepareHeader]"); pWaveOutHdr.dwFlags |= (WHDR_BEGINLOOP | WHDR_ENDLOOP); //播放音频数据文件 if(waveOutWrite(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0) { printf("Failed to write the wave data buffer"); return 0; } printFlags(pWaveOutHdr.dwFlags, "after [waveOutWrite]"); //关闭音频输出设备,释放内存 // printf("\npress any key"); // getchar(); Sleep(20000); printFlags(pWaveOutHdr.dwFlags, "after [Sleep]"); if(waveOutUnprepareHeader(hWaveOut, &pWaveOutHdr, sizeof(pWaveOutHdr)) != 0) { printf("Failed to unPrepare the wave data buffer"); return 0; } printFlags(pWaveOutHdr.dwFlags, "after [waveOutUnprepareHeader]"); waveOutReset(hWaveOut); printFlags(pWaveOutHdr.dwFlags, "after [waveOutReset]"); waveOutClose(hWaveOut); printFlags(pWaveOutHdr.dwFlags, "after [waveOutClose]"); LocalUnlock(m_hFormat); LocalFree(m_hFormat); delete [] lpData; return 0; }
/*************************************************************************** * MCIAVI_mciPlay [internal] */ static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) { WINE_MCIAVI *wma; DWORD frameTime; DWORD dwRet; LPWAVEHDR waveHdr = NULL; unsigned i, nHdr = 0; DWORD dwFromFrame, dwToFrame; DWORD numEvents = 1; HANDLE events[2]; TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; wma = MCIAVI_mciGetOpenDev(wDevID); if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION; if (dwFlags & MCI_TEST) return 0; EnterCriticalSection(&wma->cs); if (!wma->hFile) { LeaveCriticalSection(&wma->cs); return MCIERR_FILE_NOT_FOUND; } if (!wma->hWndPaint) { LeaveCriticalSection(&wma->cs); return MCIERR_NO_WINDOW; } LeaveCriticalSection(&wma->cs); if (!(dwFlags & MCI_WAIT)) return MCIAVI_mciPlay_async(wma, dwFlags, lpParms); if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE)) ShowWindow(wma->hWndPaint, SW_SHOWNA); EnterCriticalSection(&wma->cs); dwFromFrame = wma->dwCurrVideoFrame; dwToFrame = wma->dwPlayableVideoFrames - 1; if (lpParms && (dwFlags & MCI_FROM)) { dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom); } if (lpParms && (dwFlags & MCI_TO)) { dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo); } if (dwToFrame >= wma->dwPlayableVideoFrames) dwToFrame = wma->dwPlayableVideoFrames - 1; TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame); wma->dwCurrVideoFrame = dwFromFrame; wma->dwToVideoFrame = dwToFrame; /* if already playing exit */ if (wma->dwStatus == MCI_MODE_PLAY) { LeaveCriticalSection(&wma->cs); SetEvent(wma->ack_event); return 0; } if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame) { dwRet = 0; SetEvent(wma->ack_event); goto mci_play_done; } wma->dwStatus = MCI_MODE_PLAY; /* signal the state change */ SetEvent(wma->ack_event); if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN)) FIXME("Unsupported flag %08x\n", dwFlags); /* time is in microseconds, we should convert it to milliseconds */ frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000; events[0] = wma->hStopEvent; if (wma->lpWaveFormat) { if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0) { /* can't play audio */ HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat); wma->lpWaveFormat = NULL; } else { /* fill the queue with as many wave headers as possible */ MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); events[1] = wma->hEvent; numEvents = 2; } } while (wma->dwStatus == MCI_MODE_PLAY) { HDC hDC; DWORD tc, delta; DWORD ret; tc = GetTickCount(); hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0; if (hDC) { MCIAVI_PaintFrame(wma, hDC); ReleaseDC(wma->hWndPaint, hDC); } if (wma->lpWaveFormat) MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); delta = GetTickCount() - tc; if (delta < frameTime) delta = frameTime - delta; else delta = 0; LeaveCriticalSection(&wma->cs); ret = WaitForMultipleObjects(numEvents, events, FALSE, delta); EnterCriticalSection(&wma->cs); if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break; if (wma->dwCurrVideoFrame < dwToFrame) wma->dwCurrVideoFrame++; else break; } if (wma->lpWaveFormat) { while (wma->dwEventCount != nHdr - 1) { LeaveCriticalSection(&wma->cs); Sleep(100); EnterCriticalSection(&wma->cs); } /* just to get rid of some race conditions between play, stop and pause */ LeaveCriticalSection(&wma->cs); waveOutReset(wma->hWave); EnterCriticalSection(&wma->cs); for (i = 0; i < nHdr; i++) waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR)); } dwRet = 0; if (wma->lpWaveFormat) { HeapFree(GetProcessHeap(), 0, waveHdr); if (wma->hWave) { LeaveCriticalSection(&wma->cs); waveOutClose(wma->hWave); EnterCriticalSection(&wma->cs); wma->hWave = 0; } CloseHandle(wma->hEvent); } mci_play_done: wma->dwStatus = MCI_MODE_STOP; if (lpParms && (dwFlags & MCI_NOTIFY)) { TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback); mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), wDevID, MCI_NOTIFY_SUCCESSFUL); } LeaveCriticalSection(&wma->cs); return dwRet; }
void closeWaveDevice() { waveOutReset(hWaveOut); waveOutClose(hWaveOut); }
unsigned int WavePlayer::PlayThreadProcImpl() { /// 定义为寄存器变量,因为它将会被高频率的使用,用于编译器优化 register ThreadMsg tmsg = TMSG_ALIVE; /// 线程循环 while (tmsg) { // 每次循环后,交出CPU控制权,放在此处,因为下面有continue语句 Sleep(10); /// 首先检查线程消息 EnterCriticalSection(&m_cs); tmsg = m_msgPlayThread; LeaveCriticalSection(&m_cs); // 线程要结束,退出线程循环 if (!tmsg) break; // 如果设备为空,表示还没有打开设备,需要打开设备 if (m_hWaveoutDev == NULL) { EnterCriticalSection(&m_cs); MMRESULT mmres = waveOutOpen(&m_hWaveoutDev, WAVE_MAPPER, &m_waveData.wfmtx, (DWORD_PTR)WaveOutProc, (DWORD_PTR)this, CALLBACK_FUNCTION); LeaveCriticalSection(&m_cs); if (mmres != MMSYSERR_NOERROR) { // failed, try again. continue; } } // 检查空闲缓存块 EnterCriticalSection(&m_cs); int free = m_wBlock.wfreeblock; LeaveCriticalSection(&m_cs); // 如果没有空闲的缓存了,等待... if (free < BP_TURN) { continue; } ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// /// < 播放主循环 > /// ///////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// WAVEHDR *current = NULL; /// BP_TURN为每次写入播放队列的块数 for (unsigned int m = 0; m < BP_TURN; m++) { /// 当前空闲播放缓存块 current = &m_wBlock.pWaveHdr[m_wBlock.wcurrblock]; // 首先需要检查有没有被Unprepare掉 if (current->dwFlags & WHDR_PREPARED) { waveOutUnprepareHeader(m_hWaveoutDev, current, sizeof(WAVEHDR)); } /// 计算剩余需要播放的数据 EnterCriticalSection(&m_cs); unsigned long left = m_waveData.dwSize - m_wBlock.wpos; unsigned int bDecodeFinished = m_waveData.bDecodeFinished; LeaveCriticalSection(&m_cs); unsigned long chunk = 0; if (left >= BLOCK_SIZE) { chunk = BLOCK_SIZE; } else if (!bDecodeFinished) { // 如果解码还没有结束,现有的数据量有不足以填满一个缓存块,先不写入缓存 break; } else if (left && left < BLOCK_SIZE) { chunk = left; } else { ////////////////////////////////////////////////////////////////////// /// < 播放完成> /// ////////////////////////////////////////////////////////////////////// /// 获取空闲缓存块数量 EnterCriticalSection(&m_cs); int free = m_wBlock.wfreeblock; LeaveCriticalSection(&m_cs); /// 当所有的缓存块都播放完了,才意味着播放真正完成 if (free == BLOCK_COUNT) { /// Unprepare缓存块 for (int j = 0; j < m_wBlock.wfreeblock; j++) { if (m_wBlock.pWaveHdr[j].dwFlags & WHDR_PREPARED) { waveOutUnprepareHeader(m_hWaveoutDev, &m_wBlock.pWaveHdr[j], sizeof(WAVEHDR)); } } // 此时,才算真正的播放完成,关闭线程 tmsg = TMSG_CLOSE; // 处理播放完成事件 OnPlayFinished(); } // 此break仅跳出该循环,没有跳出线程循环 break; } /// prepare current wave data block header EnterCriticalSection(&m_cs); memcpy(current->lpData, &m_waveData.pData[m_wBlock.wpos], chunk); LeaveCriticalSection(&m_cs); current->dwBufferLength = chunk; // sizeof block m_wBlock.wpos += chunk; // update position /// prepare for playback waveOutPrepareHeader(m_hWaveoutDev, current, sizeof(WAVEHDR)); /// push to the queue waveOutWrite(m_hWaveoutDev, current, sizeof(WAVEHDR)); /// 减小空闲块计数 EnterCriticalSection(&m_cs); m_wBlock.wfreeblock--; LeaveCriticalSection(&m_cs); /// 使当前空闲块指向下一个 m_wBlock.wcurrblock++; m_wBlock.wcurrblock %= BLOCK_COUNT; } }/// thread /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /// /// < force to close device which are still playing > /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// if (m_hWaveoutDev) { waveOutReset(m_hWaveoutDev); /// unprepare any blocks that are still prepared for (int j = 0; j < BLOCK_COUNT; j++) { if (m_wBlock.pWaveHdr[j].dwFlags & WHDR_PREPARED) { waveOutUnprepareHeader(m_hWaveoutDev, &m_wBlock.pWaveHdr[j], sizeof(WAVEHDR)); } } waveOutClose(m_hWaveoutDev); m_hWaveoutDev = NULL; } return THREAD_EXIT; }
// -------------------------------- // Code // -------------------------------- void audioPlay() { if (g_AudioData.hWaveOut == NULL) // not initialized return; const AudioMetaData* pAudioMD = getAudioMetaData(); if (pAudioMD == NULL || pAudioMD->DataSize() == 0 || !pAudioMD->IsDataNew()) return; if (g_AudioData.bFlush) { printf("Audio is falling behind. Flushing all queue.\n"); xnDumpFileWriteString(g_AudioData.SyncDump, "Flushing queue...\n"); // mark not to check all dropped headers g_AudioData.nFirstToCheck = g_AudioData.nAudioNextBuffer; // flush all queued headers waveOutReset(g_AudioData.hWaveOut); g_AudioData.bFlush = false; return; } int nBufferSize = pAudioMD->DataSize(); WAVEHDR* pHeader = &g_AudioData.pAudioBuffers[g_AudioData.nAudioNextBuffer]; if ((pHeader->dwFlags & WHDR_DONE) == 0) { printf("No audio buffer is available!. Audio buffer will be lost!\n"); return; } // first unprepare this header MMRESULT mmRes = waveOutUnprepareHeader(g_AudioData.hWaveOut, pHeader, sizeof(WAVEHDR)); if (mmRes != MMSYSERR_NOERROR) { CHAR msg[250]; waveOutGetErrorText(mmRes, msg, 250); printf("Failed unpreparing header: %s\n", msg); } int nMaxPlayedAudio = (int)(pAudioMD->SampleRate() / 1000.0 * pAudioMD->NumberOfChannels() * 2 * AUDIO_LATENCY_THRESHOLD); if (nBufferSize > nMaxPlayedAudio) { printf("Dropping %d bytes of audio to keep synch.\n", nBufferSize - nMaxPlayedAudio); nBufferSize = nMaxPlayedAudio; } const XnUInt8* pData = pAudioMD->Data(); if (nBufferSize > g_AudioData.nBufferSize) { printf("Dropping %d bytes of audio to match buffer size.\n", nBufferSize - g_AudioData.nBufferSize); pData += (nBufferSize - g_AudioData.nBufferSize); nBufferSize = g_AudioData.nBufferSize; } pHeader->dwFlags = 0; xnOSMemCopy(pHeader->lpData, pData, nBufferSize); pHeader->dwBufferLength = nBufferSize; // prepare header mmRes = waveOutPrepareHeader(g_AudioData.hWaveOut, pHeader, sizeof(WAVEHDR)); if (mmRes != MMSYSERR_NOERROR) { CHAR msg[250]; waveOutGetErrorText(mmRes, msg, 250); printf("Unable to prepare header: %s\n", msg); return; } // queue header mmRes = waveOutWrite(g_AudioData.hWaveOut, pHeader, sizeof(WAVEHDR)); if (mmRes != MMSYSERR_NOERROR) { CHAR msg[250]; waveOutGetErrorText(mmRes, msg, 250); printf("Unable to queue header: %s\n", msg); return; } // place end-time as a timestamp g_AudioData.pAudioTimestamps[g_AudioData.nAudioNextBuffer] = (XnUInt64)(pAudioMD->Timestamp() + nBufferSize / (pAudioMD->BitsPerSample() / 8.0) / pAudioMD->NumberOfChannels() / (pAudioMD->SampleRate() / 1e6)); xnDumpFileWriteString(g_AudioData.SyncDump, "Queued index %d with timestamp %llu (%u bytes, %f ms, end timestamp: %llu)\n", g_AudioData.nAudioNextBuffer, pAudioMD->Timestamp(), nBufferSize, nBufferSize / 2.0 / pAudioMD->NumberOfChannels() / (pAudioMD->SampleRate() / 1e3), g_AudioData.pAudioTimestamps[g_AudioData.nAudioNextBuffer]); g_AudioData.nAudioNextBuffer = (g_AudioData.nAudioNextBuffer + 1) % NUMBER_OF_AUDIO_BUFFERS; }
void CDeviceWaveIO::AbortCloseAndRelease() { if (mbStarted) { // Prevent more data from getting buffered mbBlocked_volatile = TRUE; // Wait until callback is finished - max wait time one second tbool bWait = true; tbool bTimeOut = false; DWORD dwTime0 = ::GetTickCount(); while (bWait) { ::Sleep(5); if (!mbInCallback_volatile) bWait = false; else { DWORD dwTime1 = ::GetTickCount(); DWORD dwElapsed = (dwTime1 - dwTime0); if (dwElapsed > 1000) { // We've waited a whole second - abort now bWait = false; bTimeOut = true; } } } MMRESULT mmres = 0; if (!bTimeOut) { // Kill queued output (invokes waveOutProc_static with uMsg == WOM_DONE // - but new data won't get queued, because we've blocked) if (mbOutput) mmres = waveOutReset(mhandle_out); if (mbInput) mmres = waveInStop(mhandle_in); // Release the pair of buffers before we close device mmres = StopBuffers(); // Close driver (invokes waveOutProc_static with uMsg == WOM_CLOSE) if (mbOutput) mmres = waveOutClose(mhandle_out); if (mbInput) mmres = waveInClose(mhandle_in); } // Remember we're closed mbStarted = FALSE; } for (tint32 iStructIx = 0; iStructIx < miRunningStructs; iStructIx++) { if (mapcOutputPCM[iStructIx]) { delete[] mapcOutputPCM[iStructIx]; mapcOutputPCM[iStructIx] = NULL; } if (mapcInputPCM[iStructIx]) { delete[] mapcInputPCM[iStructIx]; mapcInputPCM[iStructIx] = NULL; } } if (mppfInputs) { for (tint i = 0; i < WAVE_IO_MAX_INPUT_CHANNELS; i++) { delete[] mppfInputs[i]; } delete[] mppfInputs; mppfInputs = NULL; } if (mppfOutputs) { for (tint i = 0; i < WAVE_IO_MAX_OUTPUT_CHANNELS; i++) { delete[] mppfOutputs[i]; } delete[] mppfOutputs; mppfOutputs = NULL; } miRunningStructs = 0; } // CDeviceWaveIO::AbortCloseAndRelease
bool SoundGenerator::Stop() { return waveOutReset(m_hDeviceHandle) != MMSYSERR_NOERROR; }
SoundLibrary2dWin32::~SoundLibrary2dWin32() { waveOutReset(s_device); delete [] m_buffers; m_buffers = NULL; waveOutClose(s_device); s_device = NULL; }
static void win32_play (get_audio_callback_t callback, AUDIO_OUT *audio_out, void *callback_data) { WIN32_AUDIO_OUT *win32_out ; int error ; if ((win32_out = (WIN32_AUDIO_OUT*) audio_out) == NULL) { printf ("win32_play : AUDIO_OUT is NULL.\n") ; return ; } ; if (win32_out->magic != WIN32_MAGIC) { printf ("win32_play : Bad magic number (%d %d).\n", win32_out->magic, WIN32_MAGIC) ; return ; } ; /* Set the callback function and callback data. */ win32_out->callback = callback ; win32_out->callback_data = callback_data ; win32_out->whdr [0].lpData = (char*) win32_out->short_buffer ; win32_out->whdr [1].lpData = ((char*) win32_out->short_buffer) + sizeof (win32_out->short_buffer) / 2 ; win32_out->whdr [0].dwBufferLength = sizeof (win32_out->short_buffer) / 2 ; win32_out->whdr [1].dwBufferLength = sizeof (win32_out->short_buffer) / 2 ; win32_out->bufferlen = sizeof (win32_out->short_buffer) / 2 / sizeof (short) ; /* Prepare the WAVEHDRs */ if ((error = waveOutPrepareHeader (win32_out->hwave, &(win32_out->whdr [0]), sizeof (WAVEHDR)))) { printf ("waveOutPrepareHeader [0] failed : %08X\n", error) ; waveOutClose (win32_out->hwave) ; return ; } ; if ((error = waveOutPrepareHeader (win32_out->hwave, &(win32_out->whdr [1]), sizeof (WAVEHDR)))) { printf ("waveOutPrepareHeader [1] failed : %08X\n", error) ; waveOutUnprepareHeader (win32_out->hwave, &(win32_out->whdr [0]), sizeof (WAVEHDR)) ; waveOutClose (win32_out->hwave) ; return ; } ; waveOutRestart (win32_out->hwave) ; /* Fake 2 calls to the callback function to queue up enough audio. */ win32_audio_out_callback (0, MM_WOM_DONE, (DWORD) win32_out, 0, 0) ; win32_audio_out_callback (0, MM_WOM_DONE, (DWORD) win32_out, 0, 0) ; /* Wait for playback to finish. The callback notifies us when all ** wave data has been played. */ WaitForSingleObject (win32_out->Event, INFINITE) ; waveOutPause (win32_out->hwave) ; waveOutReset (win32_out->hwave) ; waveOutUnprepareHeader (win32_out->hwave, &(win32_out->whdr [0]), sizeof (WAVEHDR)) ; waveOutUnprepareHeader (win32_out->hwave, &(win32_out->whdr [1]), sizeof (WAVEHDR)) ; waveOutClose (win32_out->hwave) ; win32_out->hwave = 0 ; return ; } /* win32_play */
void WaveOut::close() { waveOutReset(hWaveOut); waveOutClose(hWaveOut); hWaveOut = NULL; }
BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static BOOL bShutOff, bClosing ; static HWAVEOUT hWaveOut ; static HWND hwndScroll ; static int iFreq = FREQ_INIT ; static PBYTE pBuffer1, pBuffer2 ; static PWAVEHDR pWaveHdr1, pWaveHdr2 ; static WAVEFORMATEX waveformat ; int iDummy ; switch (message) { case WM_INITDIALOG: hwndScroll = GetDlgItem (hwnd, IDC_SCROLL) ; SetScrollRange (hwndScroll, SB_CTL, FREQ_MIN, FREQ_MAX, FALSE) ; SetScrollPos (hwndScroll, SB_CTL, FREQ_INIT, TRUE) ; SetDlgItemInt (hwnd, IDC_TEXT, FREQ_INIT, FALSE) ; return TRUE ; case WM_HSCROLL: switch (LOWORD (wParam)) { case SB_LINELEFT: iFreq -= 1 ; break ; case SB_LINERIGHT: iFreq += 1 ; break ; case SB_PAGELEFT: iFreq /= 2 ; break ; case SB_PAGERIGHT: iFreq *= 2 ; break ; case SB_THUMBTRACK: iFreq = HIWORD (wParam) ; break ; case SB_TOP: GetScrollRange (hwndScroll, SB_CTL, &iFreq, &iDummy) ; break ; case SB_BOTTOM: GetScrollRange (hwndScroll, SB_CTL, &iDummy, &iFreq) ; break ; } iFreq = max (FREQ_MIN, min (FREQ_MAX, iFreq)) ; SetScrollPos (hwndScroll, SB_CTL, iFreq, TRUE) ; SetDlgItemInt (hwnd, IDC_TEXT, iFreq, FALSE) ; return TRUE ; case WM_COMMAND: switch (LOWORD (wParam)) { case IDC_ONOFF: // If turning on waveform, hWaveOut is NULL if (hWaveOut == NULL) { // Allocate memory for 2 headers and 2 buffers pWaveHdr1 = malloc (sizeof (WAVEHDR)) ; pWaveHdr2 = malloc (sizeof (WAVEHDR)) ; pBuffer1 = malloc (OUT_BUFFER_SIZE) ; pBuffer2 = malloc (OUT_BUFFER_SIZE) ; if (!pWaveHdr1 || !pWaveHdr2 || !pBuffer1 || !pBuffer2) { if (!pWaveHdr1) free (pWaveHdr1) ; if (!pWaveHdr2) free (pWaveHdr2) ; if (!pBuffer1) free (pBuffer1) ; if (!pBuffer2) free (pBuffer2) ; MessageBeep (MB_ICONEXCLAMATION) ; MessageBox (hwnd, TEXT ("Error allocating memory!"), szAppName, MB_ICONEXCLAMATION | MB_OK) ; return TRUE ; } // Variable to indicate Off button pressed bShutOff = FALSE ; // Open waveform audio for output waveformat.wFormatTag = WAVE_FORMAT_PCM ; waveformat.nChannels = 1 ; waveformat.nSamplesPerSec = SAMPLE_RATE ; waveformat.nAvgBytesPerSec = SAMPLE_RATE ; waveformat.nBlockAlign = 1 ; waveformat.wBitsPerSample = 8 ; waveformat.cbSize = 0 ; if (waveOutOpen (&hWaveOut, WAVE_MAPPER, &waveformat, (DWORD) hwnd, 0, CALLBACK_WINDOW) != MMSYSERR_NOERROR) { free (pWaveHdr1) ; free (pWaveHdr2) ; free (pBuffer1) ; free (pBuffer2) ; hWaveOut = NULL ; MessageBeep (MB_ICONEXCLAMATION) ; MessageBox (hwnd, TEXT ("Error opening waveform audio device!"), szAppName, MB_ICONEXCLAMATION | MB_OK) ; return TRUE ; } // Set up headers and prepare them pWaveHdr1->lpData = pBuffer1 ; pWaveHdr1->dwBufferLength = OUT_BUFFER_SIZE ; pWaveHdr1->dwBytesRecorded = 0 ; pWaveHdr1->dwUser = 0 ; pWaveHdr1->dwFlags = 0 ; pWaveHdr1->dwLoops = 1 ; pWaveHdr1->lpNext = NULL ; pWaveHdr1->reserved = 0 ; waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ; pWaveHdr2->lpData = pBuffer2 ; pWaveHdr2->dwBufferLength = OUT_BUFFER_SIZE ; pWaveHdr2->dwBytesRecorded = 0 ; pWaveHdr2->dwUser = 0 ; pWaveHdr2->dwFlags = 0 ; pWaveHdr2->dwLoops = 1 ; pWaveHdr2->lpNext = NULL ; pWaveHdr2->reserved = 0 ; waveOutPrepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ; } // If turning off waveform, reset waveform audio else { bShutOff = TRUE ; waveOutReset (hWaveOut) ; } return TRUE ; } break ; // Message generated from waveOutOpen call case MM_WOM_OPEN: SetDlgItemText (hwnd, IDC_ONOFF, TEXT ("Turn Off")) ; // Send two buffers to waveform output device FillBuffer (pBuffer1, iFreq) ; waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ; FillBuffer (pBuffer2, iFreq) ; waveOutWrite (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ; return TRUE ; // Message generated when a buffer is finished case MM_WOM_DONE: if (bShutOff) { waveOutClose (hWaveOut) ; return TRUE ; } // Fill and send out a new buffer FillBuffer (((PWAVEHDR) lParam)->lpData, iFreq) ; waveOutWrite (hWaveOut, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ; return TRUE ; case MM_WOM_CLOSE: waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ; waveOutUnprepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ; free (pWaveHdr1) ; free (pWaveHdr2) ; free (pBuffer1) ; free (pBuffer2) ; hWaveOut = NULL ; SetDlgItemText (hwnd, IDC_ONOFF, TEXT ("Turn On")) ; if (bClosing) EndDialog (hwnd, 0) ; return TRUE ; case WM_SYSCOMMAND: switch (wParam) { case SC_CLOSE: if (hWaveOut != NULL) { bShutOff = TRUE ; bClosing = TRUE ; waveOutReset (hWaveOut) ; } else EndDialog (hwnd, 0) ; return TRUE ; } break ; } return FALSE ; }
/***************************************************************************** * Open: open the audio device ***************************************************************************** * This function opens and setups Win32 waveOut *****************************************************************************/ static int Open( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; vlc_value_t val; int i; /* Allocate structure */ p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) ); if( p_aout->output.p_sys == NULL ) { msg_Err( p_aout, "out of memory" ); return VLC_EGENERIC; } p_aout->output.pf_play = Play; p_aout->b_die = VLC_FALSE; if( var_Type( p_aout, "audio-device" ) == 0 ) { Probe( p_aout ); } if( var_Get( p_aout, "audio-device", &val ) < 0 ) { /* Probe() has failed. */ free( p_aout->output.p_sys ); return VLC_EGENERIC; } var_Create( p_aout, "waveout-float32", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); /* Open the device */ if( val.i_int == AOUT_VAR_SPDIF ) { p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i'); if( OpenWaveOut( p_aout, VLC_FOURCC('s','p','d','i'), p_aout->output.output.i_physical_channels, aout_FormatNbChannels( &p_aout->output.output ), p_aout->output.output.i_rate, VLC_FALSE ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open waveout audio device" ); free( p_aout->output.p_sys ); return VLC_EGENERIC; } /* Calculate the frame size in bytes */ p_aout->output.i_nb_samples = A52_FRAME_NB; p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE; p_aout->output.output.i_frame_length = A52_FRAME_NB; p_aout->output.p_sys->i_buffer_size = p_aout->output.output.i_bytes_per_frame; aout_VolumeNoneInit( p_aout ); } else { if( val.i_int == AOUT_VAR_5_1 ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; } else if( val.i_int == AOUT_VAR_2F2R ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; } else if( val.i_int == AOUT_VAR_MONO ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; } else { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } if( OpenWaveOutPCM( p_aout, &p_aout->output.output.i_format, p_aout->output.output.i_physical_channels, aout_FormatNbChannels( &p_aout->output.output ), p_aout->output.output.i_rate, VLC_FALSE ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open waveout audio device" ); free( p_aout->output.p_sys ); return VLC_EGENERIC; } /* Calculate the frame size in bytes */ p_aout->output.i_nb_samples = FRAME_SIZE; aout_FormatPrepare( &p_aout->output.output ); p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * p_aout->output.output.i_bytes_per_frame; aout_VolumeSoftInit( p_aout ); } waveOutReset( p_aout->output.p_sys->h_waveout ); /* Allocate silence buffer */ p_aout->output.p_sys->p_silence_buffer = malloc( p_aout->output.p_sys->i_buffer_size ); if( p_aout->output.p_sys->p_silence_buffer == NULL ) { free( p_aout->output.p_sys ); msg_Err( p_aout, "out of memory" ); return 1; } /* Zero the buffer. WinCE doesn't have calloc(). */ memset( p_aout->output.p_sys->p_silence_buffer, 0, p_aout->output.p_sys->i_buffer_size ); /* Now we need to setup our waveOut play notification structure */ p_aout->output.p_sys->p_notif = vlc_object_create( p_aout, sizeof(notification_thread_t) ); p_aout->output.p_sys->p_notif->p_aout = p_aout; p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL ); /* Then launch the notification thread */ if( vlc_thread_create( p_aout->output.p_sys->p_notif, "waveOut Notification Thread", WaveOutThread, VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) ) { msg_Err( p_aout, "cannot create WaveOutThread" ); } /* We need to kick off the playback in order to have the callback properly * working */ for( i = 0; i < FRAMES_NUM; i++ ) { p_aout->output.p_sys->waveheader[i].dwFlags = WHDR_DONE; p_aout->output.p_sys->waveheader[i].dwUser = 0; } PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout, &p_aout->output.p_sys->waveheader[0], NULL ); return 0; }
static BOOL MULTIMEDIA_PlaySound(const void* pszSound, HMODULE hmod, DWORD fdwSound, BOOL bUnicode) { WINE_PLAYSOUND* wps = NULL; TRACE("pszSound='%p' hmod=%p fdwSound=%08X\n", pszSound, hmod, fdwSound); /* FIXME? I see no difference between SND_NOWAIT and SND_NOSTOP ! * there could be one if several sounds can be played at once... */ if ((fdwSound & (SND_NOWAIT | SND_NOSTOP)) && PlaySoundList != NULL) return FALSE; /* alloc internal structure, if we need to play something */ if (pszSound && !(fdwSound & SND_PURGE)) { if (!(wps = PlaySound_Alloc(pszSound, hmod, fdwSound, bUnicode))) return FALSE; } EnterCriticalSection(&WINMM_cs); /* since several threads can enter PlaySound in parallel, we're not * sure, at this point, that another thread didn't start a new playsound */ while (PlaySoundList != NULL) { ResetEvent(psLastEvent); /* FIXME: doc says we have to stop all instances of pszSound if it's non * NULL... as of today, we stop all playing instances */ SetEvent(psStopEvent); waveOutReset(PlaySoundList->hWave); LeaveCriticalSection(&WINMM_cs); WaitForSingleObject(psLastEvent, INFINITE); EnterCriticalSection(&WINMM_cs); ResetEvent(psStopEvent); } if (wps) wps->lpNext = PlaySoundList; PlaySoundList = wps; LeaveCriticalSection(&WINMM_cs); if (!pszSound || (fdwSound & SND_PURGE)) return TRUE; if (fdwSound & SND_ASYNC) { DWORD id; HANDLE handle; wps->bLoop = (fdwSound & SND_LOOP) ? TRUE : FALSE; if ((handle = CreateThread(NULL, 0, proc_PlaySound, wps, 0, &id)) != 0) { wps->hThread = handle; SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); return TRUE; } } else return proc_PlaySound(wps); /* error cases */ PlaySound_Free(wps); return FALSE; }
void W32AudioDriver::StopDriver() { if (waveOut_) { waveOutReset(waveOut_) ; } } ;
static DWORD WINAPI proc_PlaySound(LPVOID arg) { WINE_PLAYSOUND* wps = arg; BOOL bRet = FALSE; HMMIO hmmio = 0; MMCKINFO ckMainRIFF; MMCKINFO mmckInfo; LPWAVEFORMATEX lpWaveFormat = NULL; HWAVEOUT hWave = 0; LPWAVEHDR waveHdr = NULL; INT count, bufsize, left, index; struct playsound_data s; void* data; s.hEvent = 0; TRACE("SoundName=%s !\n", debugstr_w(wps->pszSound)); /* if resource, grab it */ if ((wps->fdwSound & SND_RESOURCE) == SND_RESOURCE) { static const WCHAR wszWave[] = {'W','A','V','E',0}; HRSRC hRes; HGLOBAL hGlob; if ((hRes = FindResourceW(wps->hMod, wps->pszSound, wszWave)) == 0 || (hGlob = LoadResource(wps->hMod, hRes)) == 0) goto errCleanUp; if ((data = LockResource(hGlob)) == NULL) { FreeResource(hGlob); goto errCleanUp; } FreeResource(hGlob); } else data = (void*)wps->pszSound; /* construct an MMIO stream (either in memory, or from a file */ if (wps->fdwSound & SND_MEMORY) { /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */ MMIOINFO mminfo; memset(&mminfo, 0, sizeof(mminfo)); mminfo.fccIOProc = FOURCC_MEM; mminfo.pchBuffer = data; mminfo.cchBuffer = -1; /* FIXME: when a resource, could grab real size */ TRACE("Memory sound %p\n", data); hmmio = mmioOpenW(NULL, &mminfo, MMIO_READ); } if (!hmmio && wps->fdwSound & SND_ALIAS) { if ((wps->fdwSound & SND_ALIAS_ID) == SND_ALIAS_ID) { static const WCHAR wszSystemAsterisk[] = {'S','y','s','t','e','m','A','s','t','e','r','i','s','k',0}; static const WCHAR wszSystemDefault[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t',0}; static const WCHAR wszSystemExclamation[] = {'S','y','s','t','e','m','E','x','c','l','a','m','a','t','i','o','n',0}; static const WCHAR wszSystemExit[] = {'S','y','s','t','e','m','E','x','i','t',0}; static const WCHAR wszSystemHand[] = {'S','y','s','t','e','m','H','a','n','d',0}; static const WCHAR wszSystemQuestion[] = {'S','y','s','t','e','m','Q','u','e','s','t','i','o','n',0}; static const WCHAR wszSystemStart[] = {'S','y','s','t','e','m','S','t','a','r','t',0}; static const WCHAR wszSystemWelcome[] = {'S','y','s','t','e','m','W','e','l','c','o','m','e',0}; wps->fdwSound &= ~(SND_ALIAS_ID ^ SND_ALIAS); if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMASTERISK) wps->pszSound = wszSystemAsterisk; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMDEFAULT) wps->pszSound = wszSystemDefault; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXCLAMATION) wps->pszSound = wszSystemExclamation; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXIT) wps->pszSound = wszSystemExit; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMHAND) wps->pszSound = wszSystemHand; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMQUESTION) wps->pszSound = wszSystemQuestion; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMSTART) wps->pszSound = wszSystemStart; else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMWELCOME) wps->pszSound = wszSystemWelcome; else goto errCleanUp; } hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound); if (!hmmio) { wps->fdwSound &= ~SND_ALIAS; wps->fdwSound |= SND_FILENAME; } } if (!hmmio && wps->fdwSound & SND_FILENAME) { hmmio = get_mmioFromFile(wps->pszSound); } if (!(wps->fdwSound & (SND_FILENAME|SND_ALIAS|SND_MEMORY))) { if ((hmmio = get_mmioFromProfile(wps->fdwSound | SND_NODEFAULT, wps->pszSound)) == 0) { if ((hmmio = get_mmioFromFile(wps->pszSound)) == 0) { hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound); } } } if (hmmio == 0) goto errCleanUp; if (mmioDescend(hmmio, &ckMainRIFF, NULL, 0)) goto errCleanUp; TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08X\n", (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType, ckMainRIFF.cksize); if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) goto errCleanUp; mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' '); if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK)) goto errCleanUp; TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n", (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize); lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize); if (!lpWaveFormat) goto errCleanUp; if (mmioRead(hmmio, (HPSTR)lpWaveFormat, mmckInfo.cksize) < sizeof(PCMWAVEFORMAT)) goto errCleanUp; TRACE("wFormatTag=%04X !\n", lpWaveFormat->wFormatTag); TRACE("nChannels=%d\n", lpWaveFormat->nChannels); TRACE("nSamplesPerSec=%d\n", lpWaveFormat->nSamplesPerSec); TRACE("nAvgBytesPerSec=%d\n", lpWaveFormat->nAvgBytesPerSec); TRACE("nBlockAlign=%d\n", lpWaveFormat->nBlockAlign); TRACE("wBitsPerSample=%u !\n", lpWaveFormat->wBitsPerSample); /* move to end of 'fmt ' chunk */ mmioAscend(hmmio, &mmckInfo, 0); mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a'); if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK)) goto errCleanUp; TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n", (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize); s.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (!s.hEvent || bPlaySoundStop) goto errCleanUp; if (waveOutOpen(&hWave, WAVE_MAPPER, lpWaveFormat, (DWORD_PTR)PlaySound_Callback, (DWORD_PTR)&s, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) goto errCleanUp; /* make it so that 3 buffers per second are needed */ bufsize = (((lpWaveFormat->nAvgBytesPerSec / 3) - 1) / lpWaveFormat->nBlockAlign + 1) * lpWaveFormat->nBlockAlign; waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize); if (!waveHdr) goto errCleanUp; waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR); waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize; waveHdr[0].dwUser = waveHdr[1].dwUser = 0L; waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L; waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L; waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize; if (waveOutPrepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR)) || waveOutPrepareHeader(hWave, &waveHdr[1], sizeof(WAVEHDR))) { goto errCleanUp; } wps->hWave = hWave; s.dwEventCount = 1L; /* for first buffer */ index = 0; do { left = mmckInfo.cksize; mmioSeek(hmmio, mmckInfo.dwDataOffset, SEEK_SET); while (left) { if (bPlaySoundStop) { wps->bLoop = FALSE; break; } count = mmioRead(hmmio, waveHdr[index].lpData, min(bufsize, left)); if (count < 1) break; left -= count; waveHdr[index].dwBufferLength = count; if (waveOutWrite(hWave, &waveHdr[index], sizeof(WAVEHDR)) == MMSYSERR_NOERROR) { index ^= 1; PlaySound_WaitDone(&s); } else { ERR("Aborting play loop, waveOutWrite error\n"); wps->bLoop = FALSE; break; } } bRet = TRUE; } while (wps->bLoop); PlaySound_WaitDone(&s); /* to balance first buffer */ waveOutReset(hWave); waveOutUnprepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR)); waveOutUnprepareHeader(hWave, &waveHdr[1], sizeof(WAVEHDR)); errCleanUp: TRACE("Done playing=%s => %s!\n", debugstr_w(wps->pszSound), bRet ? "ok" : "ko"); HeapFree(GetProcessHeap(), 0, lpWaveFormat); if (hWave) { EnterCriticalSection(&WINMM_cs); /* the CS prevents a concurrent waveOutReset */ wps->hWave = 0; LeaveCriticalSection(&WINMM_cs); while (waveOutClose(hWave) == WAVERR_STILLPLAYING) Sleep(100); } CloseHandle(s.hEvent); HeapFree(GetProcessHeap(), 0, waveHdr); if (hmmio) mmioClose(hmmio, 0); PlaySound_Free(wps); return bRet; }
/* ==================== SndSys_Shutdown Stop the sound card, delete "snd_renderbuffer" and free its other resources ==================== */ void SndSys_Shutdown (void) { #ifdef SUPPORTDIRECTX if (pDSBuf) { IDirectSoundBuffer_Stop(pDSBuf); IDirectSoundBuffer_Release(pDSBuf); } // only release primary buffer if it's not also the mixing buffer we just released if (pDSPBuf && (pDSBuf != pDSPBuf)) { IDirectSoundBuffer_Release(pDSPBuf); } if (pDS) { IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL); IDirectSound_Release(pDS); } #endif if (hWaveOut) { waveOutReset (hWaveOut); if (lpWaveHdr) { unsigned int i; for (i=0 ; i< WAV_BUFFERS ; i++) waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); } waveOutClose (hWaveOut); if (hWaveHdr) { GlobalUnlock(hWaveHdr); GlobalFree(hWaveHdr); } if (hData) { GlobalUnlock(hData); GlobalFree(hData); } } if (snd_renderbuffer != NULL) { Mem_Free(snd_renderbuffer); snd_renderbuffer = NULL; } #ifdef SUPPORTDIRECTX pDS = NULL; pDSBuf = NULL; pDSPBuf = NULL; dsound_init = false; #endif hWaveOut = 0; hData = 0; hWaveHdr = 0; lpData = NULL; lpWaveHdr = NULL; wav_init = false; }
BOOL playTestTone() { SHORT* buffer; BOOL isChannelChecked; #if 1 WAVEFORMATEXTENSIBLE wfx; ZeroMemory(&wfx, sizeof(WAVEFORMATEXTENSIBLE)); wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfx.Format.nChannels = (WORD)currentChannelCount; wfx.Format.nSamplesPerSec = SAMPLE_RATE; wfx.Format.wBitsPerSample = 16; wfx.Format.nBlockAlign = (wfx.Format.wBitsPerSample >> 3) * wfx.Format.nChannels; wfx.Format.nAvgBytesPerSec = SAMPLE_RATE * (wfx.Format.wBitsPerSample >> 3) * wfx.Format.nChannels; wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample ; wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; #else WAVEFORMATEX wfx; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.wBitsPerSample = 16; wfx.nChannels = (WORD)currentChannelCount; wfx.nSamplesPerSec = SAMPLE_RATE; wfx.nAvgBytesPerSec = SAMPLE_RATE * (wfx.wBitsPerSample >> 3) * wfx.nChannels; wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels; wfx.cbSize = 0; #endif isChannelChecked = (SendMessage(GetDlgItem(hWndChild[0], IDC_LEFT), BM_GETCHECK, 0, 0) == BST_CHECKED); isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_RIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED); isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_BLEFT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 2); isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_BRIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 2); isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CENTER), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 4); isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_SUB), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 4); isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CLEFT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 6); isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CRIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 6); if (!isChannelChecked) return FALSE; if (waveOutOpen(&hWave, findWaveDeviceID(), (WAVEFORMATEX*)&(wfx), 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) { PrintLastError("waveOutOpen()"); return FALSE; } if (!generateTestSignal(SPEAKER_AMPLITUDE, currentChannelCount, SAMPLE_RATE, &buffer)) { return FALSE; } ZeroMemory(&pwh, sizeof(pwh)); pwh.lpData = (LPSTR)buffer; pwh.dwBufferLength = SAMPLE_RATE*sizeof(SHORT)*currentChannelCount; pwh.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; pwh.dwLoops = 0xFFFFFFFF; if (waveOutPrepareHeader(hWave, &pwh, sizeof(pwh)) != MMSYSERR_NOERROR) { LocalFree(buffer); PrintLastError("waveOutPrepareHeader()"); return FALSE; } if (waveOutReset(hWave) != MMSYSERR_NOERROR) { LocalFree(buffer); PrintLastError("waveOutReset()"); return FALSE; } if (waveOutWrite(hWave, &pwh, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) { LocalFree(buffer); PrintLastError("waveOutWrite()"); return FALSE; } return TRUE; }
BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static BOOL bRecording, bPlaying, bReverse, bPaused, bEnding, bTerminating ; static DWORD dwDataLength, dwRepetitions = 1 ; static HWAVEIN hWaveIn ; static HWAVEOUT hWaveOut ; static PBYTE pBuffer1, pBuffer2, pSaveBuffer, pNewBuffer ; static PWAVEHDR pWaveHdr1, pWaveHdr2 ; static TCHAR szOpenError[] = TEXT ("Error opening waveform audio!"); static TCHAR szMemError [] = TEXT ("Error allocating memory!") ; static WAVEFORMATEX waveform ; switch (message) { case WM_INITDIALOG: // Allocate memory for wave header pWaveHdr1 = malloc (sizeof (WAVEHDR)) ; pWaveHdr2 = malloc (sizeof (WAVEHDR)) ; // Allocate memory for save buffer pSaveBuffer = malloc (1) ; return TRUE ; case WM_COMMAND: switch (LOWORD (wParam)) { case IDC_RECORD_BEG: // Allocate buffer memory pBuffer1 = malloc (INP_BUFFER_SIZE) ; pBuffer2 = malloc (INP_BUFFER_SIZE) ; if (!pBuffer1 || !pBuffer2) { if (pBuffer1) free (pBuffer1) ; if (pBuffer2) free (pBuffer2) ; MessageBeep (MB_ICONEXCLAMATION) ; MessageBox (hwnd, szMemError, szAppName, MB_ICONEXCLAMATION | MB_OK) ; return TRUE ; } // Open waveform audio for input waveform.wFormatTag = WAVE_FORMAT_PCM ; waveform.nChannels = 1 ; waveform.nSamplesPerSec = 11025 ; waveform.nAvgBytesPerSec = 11025 ; waveform.nBlockAlign = 1 ; waveform.wBitsPerSample = 8 ; waveform.cbSize = 0 ; if (waveInOpen (&hWaveIn, WAVE_MAPPER, &waveform, (DWORD) hwnd, 0, CALLBACK_WINDOW)) { free (pBuffer1) ; free (pBuffer2) ; MessageBeep (MB_ICONEXCLAMATION) ; MessageBox (hwnd, szOpenError, szAppName, MB_ICONEXCLAMATION | MB_OK) ; } // Set up headers and prepare them pWaveHdr1->lpData = pBuffer1 ; pWaveHdr1->dwBufferLength = INP_BUFFER_SIZE ; pWaveHdr1->dwBytesRecorded = 0 ; pWaveHdr1->dwUser = 0 ; pWaveHdr1->dwFlags = 0 ; pWaveHdr1->dwLoops = 1 ; pWaveHdr1->lpNext = NULL ; pWaveHdr1->reserved = 0 ; waveInPrepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ; pWaveHdr2->lpData = pBuffer2 ; pWaveHdr2->dwBufferLength = INP_BUFFER_SIZE ; pWaveHdr2->dwBytesRecorded = 0 ; pWaveHdr2->dwUser = 0 ; pWaveHdr2->dwFlags = 0 ; pWaveHdr2->dwLoops = 1 ; pWaveHdr2->lpNext = NULL ; pWaveHdr2->reserved = 0 ; waveInPrepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ; return TRUE ; case IDC_RECORD_END: // Reset input to return last buffer bEnding = TRUE ; waveInReset (hWaveIn) ; return TRUE ; case IDC_PLAY_BEG: // Open waveform audio for output waveform.wFormatTag = WAVE_FORMAT_PCM ; waveform.nChannels = 1 ; waveform.nSamplesPerSec = 11025 ; waveform.nAvgBytesPerSec = 11025 ; waveform.nBlockAlign = 1 ; waveform.wBitsPerSample = 8 ; waveform.cbSize = 0 ; if (waveOutOpen (&hWaveOut, WAVE_MAPPER, &waveform, (DWORD) hwnd, 0, CALLBACK_WINDOW)) { MessageBeep (MB_ICONEXCLAMATION) ; MessageBox (hwnd, szOpenError, szAppName, MB_ICONEXCLAMATION | MB_OK) ; } return TRUE ; case IDC_PLAY_PAUSE: // Pause or restart output if (!bPaused) { waveOutPause (hWaveOut) ; SetDlgItemText (hwnd, IDC_PLAY_PAUSE, TEXT ("Resume")) ; bPaused = TRUE ; } else { waveOutRestart (hWaveOut) ; SetDlgItemText (hwnd, IDC_PLAY_PAUSE, TEXT ("Pause")) ; bPaused = FALSE ; } return TRUE ; case IDC_PLAY_END: // Reset output for close preparation bEnding = TRUE ; waveOutReset (hWaveOut) ; return TRUE ; case IDC_PLAY_REV: // Reverse save buffer and play bReverse = TRUE ; ReverseMemory (pSaveBuffer, dwDataLength) ; SendMessage (hwnd, WM_COMMAND, IDC_PLAY_BEG, 0) ; return TRUE ; case IDC_PLAY_REP: // Set infinite repetitions and play dwRepetitions = -1 ; SendMessage (hwnd, WM_COMMAND, IDC_PLAY_BEG, 0) ; return TRUE ; case IDC_PLAY_SPEED: // Open waveform audio for fast output waveform.wFormatTag = WAVE_FORMAT_PCM ; waveform.nChannels = 1 ; waveform.nSamplesPerSec = 22050 ; waveform.nAvgBytesPerSec = 22050 ; waveform.nBlockAlign = 1 ; waveform.wBitsPerSample = 8 ; waveform.cbSize = 0 ; if (waveOutOpen (&hWaveOut, 0, &waveform, (DWORD) hwnd, 0, CALLBACK_WINDOW)) { MessageBeep (MB_ICONEXCLAMATION) ; MessageBox (hwnd, szOpenError, szAppName, MB_ICONEXCLAMATION | MB_OK) ; } return TRUE ; } break ; case MM_WIM_OPEN: // Shrink down the save buffer pSaveBuffer = realloc (pSaveBuffer, 1) ; // Enable and disable Buttons EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REV), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REP), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_SPEED), FALSE) ; SetFocus (GetDlgItem (hwnd, IDC_RECORD_END)) ; // Add the buffers waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ; waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ; // Begin sampling bRecording = TRUE ; bEnding = FALSE ; dwDataLength = 0 ; waveInStart (hWaveIn) ; return TRUE ; case MM_WIM_DATA: // Reallocate save buffer memory pNewBuffer = realloc (pSaveBuffer, dwDataLength + ((PWAVEHDR) lParam)->dwBytesRecorded) ; if (pNewBuffer == NULL) { waveInClose (hWaveIn) ; MessageBeep (MB_ICONEXCLAMATION) ; MessageBox (hwnd, szMemError, szAppName, MB_ICONEXCLAMATION | MB_OK) ; return TRUE ; } pSaveBuffer = pNewBuffer ; CopyMemory (pSaveBuffer + dwDataLength, ((PWAVEHDR) lParam)->lpData, ((PWAVEHDR) lParam)->dwBytesRecorded) ; dwDataLength += ((PWAVEHDR) lParam)->dwBytesRecorded ; if (bEnding) { waveInClose (hWaveIn) ; return TRUE ; } // Send out a new buffer waveInAddBuffer (hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ; return TRUE ; case MM_WIM_CLOSE: // Free the buffer memory waveInUnprepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ; waveInUnprepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ; free (pBuffer1) ; free (pBuffer2) ; // Enable and disable buttons EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), FALSE) ; SetFocus (GetDlgItem (hwnd, IDC_RECORD_BEG)) ; if (dwDataLength > 0) { EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REP), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REV), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_SPEED), TRUE) ; SetFocus (GetDlgItem (hwnd, IDC_PLAY_BEG)) ; } bRecording = FALSE ; if (bTerminating) SendMessage (hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L) ; return TRUE ; case MM_WOM_OPEN: // Enable and disable buttons EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REP), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REV), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_SPEED), FALSE) ; SetFocus (GetDlgItem (hwnd, IDC_PLAY_END)) ; // Set up header pWaveHdr1->lpData = pSaveBuffer ; pWaveHdr1->dwBufferLength = dwDataLength ; pWaveHdr1->dwBytesRecorded = 0 ; pWaveHdr1->dwUser = 0 ; pWaveHdr1->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP ; pWaveHdr1->dwLoops = dwRepetitions ; pWaveHdr1->lpNext = NULL ; pWaveHdr1->reserved = 0 ; // Prepare and write waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ; waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ; bEnding = FALSE ; bPlaying = TRUE ; return TRUE ; case MM_WOM_DONE: waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ; waveOutClose (hWaveOut) ; return TRUE ; case MM_WOM_CLOSE: // Enable and disable buttons EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END), FALSE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REV), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REP), TRUE) ; EnableWindow (GetDlgItem (hwnd, IDC_PLAY_SPEED), TRUE) ; SetFocus (GetDlgItem (hwnd, IDC_PLAY_BEG)) ; SetDlgItemText (hwnd, IDC_PLAY_PAUSE, TEXT ("Pause")) ; bPaused = FALSE ; dwRepetitions = 1 ; bPlaying = FALSE ; if (bReverse) { ReverseMemory (pSaveBuffer, dwDataLength) ; bReverse = FALSE ; } if (bTerminating) SendMessage (hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L) ; return TRUE ; case WM_SYSCOMMAND: switch (LOWORD (wParam)) { case SC_CLOSE: if (bRecording) { bTerminating = TRUE ; bEnding = TRUE ; waveInReset (hWaveIn) ; return TRUE ; } if (bPlaying) { bTerminating = TRUE ; bEnding = TRUE ; waveOutReset (hWaveOut) ; return TRUE ; } free (pWaveHdr1) ; free (pWaveHdr2) ; free (pSaveBuffer) ; EndDialog (hwnd, 0) ; return TRUE ; } break ; } return FALSE ; }