標籤:
要使用waveout函數組,族,首先要知道幾個資料結構,首先是這個
typedef struct tWAVEFORMATEX{ WORD wFormatTag; /* 格式的類型 */ WORD nChannels; /* 通道數 */ DWORD nSamplesPerSec; /* 採樣頻率 */ DWORD nAvgBytesPerSec; /* 位元速率 採樣率*聲道數*採樣位元/8 */ WORD nBlockAlign; /* 一次採樣的寬度 通道數*採樣位元/8 */ WORD wBitsPerSample; /* 採樣位元 */ WORD cbSize; /* 外部附加資訊,不用設定為0 */ /* extra information (after cbSize) */} WAVEFORMATEX,
這個結構體在開啟音訊裝置準備播放聲音的時候是必須的,開啟音訊裝置的時候需要使用的函數為
if(!(waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,(LPWAVEFORMATEX)&pFormat,(DWORD)this, 0, 0) == MMSYSERR_NOERROR))
第一個參數是音訊裝置的控制代碼,定義如下
LPHWAVEOUT hWaveOut;
實際上也就是一個裝置指標
第二個參數為裝置類型,其中選擇WAVE_MAPPER能選一個能夠播放給定格式的波形音訊輸出裝置
第三個參數為音頻資料的格式資訊
第四個參數是一個回呼函數
第五個是回呼函數的資源控制代碼
第六個是開啟裝置的標識,具體的描述可以去看msdn成功後返回MMSYSERR_NOERROR ,否則返回以下值:
值描述
MMSYSERR_ALLOCATED 表示資源已存在
MMSYSERR_BADDEVICEID 裝置ID超出範圍
MMSYSERR_NODRIVER 沒有驅動
MMSYSERR_NOMEM 不能分配記憶體
WAVERR_BADFORMAT 企圖開啟一個不被支援的格式
WAVERR_SYNC 裝置是可同步的,但waveOutOpen沒用有WAVE_ALLOWSYNC
開啟音訊裝置之後就需要準備音訊格式資訊了,這裡需要第二個結構體
/* wave data block header */typedef struct wavehdr_tag { LPSTR lpData; /*指向鎖定資料緩衝區的指標 */ DWORD dwBufferLength; /*資料緩衝區長度 */ DWORD dwBytesRecorded; /* used for input only */ DWORD_PTR dwUser; /* for client‘s use */ DWORD dwFlags; /* assorted flags (see defines) */ DWORD dwLoops; /* loop control counter */ struct wavehdr_tag FAR *lpNext; /* reserved for driver */ DWORD_PTR reserved; /* reserved for driver */} WAVEHDR
使用方式如下
hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD)sizeof(WAVEHDR)); if(hWaveHdr == NULL) { MessageBox("Not enough memory for header","error",MB_OK);//開啟裝置失敗 return; } lpWaveHdr = (LPWAVEHDR)GlobalLock(hWaveHdr); if(lpWaveHdr == NULL) { MessageBox("Failed to lock memory for header","error",MB_OK); return; } // 初始化音頻結構After allocation, set up and prepare header. lpWaveHdr->lpData = (char *)pVoiceBuffer; lpWaveHdr->dwBufferLength = lFileSize; lpWaveHdr->dwFlags = 0L; //WHDR_BEGINLOOP | WHDR_ENDLOOP; lpWaveHdr->dwLoops = 0L; if(waveOutPrepareHeader((HWAVEOUT)hWaveOut, lpWaveHdr, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
緩衝區可以設定為我們讀取進來的資料的記憶體位址,另外,該緩衝區需要鎖定
接下來就可以寫入資料了
wResult = waveOutWrite((HWAVEOUT)hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
寫入資料失敗的話要把之前鎖定的緩衝區解除掉,使用這個函數
waveOutUnprepareHeader((HWAVEOUT)hWaveOut, lpWaveHdr, sizeof(WAVEHDR)); GlobalUnlock(lpWaveHdr); GlobalFree(hWaveHdr);
如果成功就可以進入迴圈一直播放知道資料播放完成,如下
while(waveOutUnprepareHeader((HWAVEOUT)hWaveOut, lpWaveHdr, sizeof(WAVEHDR))!= MMSYSERR_NOERROR) { //迴圈清除緩衝區,如果成功表示播放完畢 //如果沒有播放完畢則迴圈下面語句 if(bExit) break;//讓迴圈也可以響應訊息 MSG message; if(::PeekMessage (&message,NULL,0,0,PM_REMOVE)) { ::TranslateMessage (&message); ::DispatchMessage (&message); } }
資料播放完成之後需要先複位播放器在關閉音訊裝置,如下
//播放完畢 if(waveOutReset((HWAVEOUT)hWaveOut) != MMSYSERR_NOERROR) { MessageBox("WaveOutReset Error!","error",MB_OK); return; } if(waveOutClose((HWAVEOUT)hWaveOut)!= MMSYSERR_NOERROR) { MessageBox("WaveOutClose Error!","error",MB_OK); return; }
通過這些就能完成一個基本的wav播放器了,同時mp3的播放器只需要mp3解碼也能做了
介面如下
工程代碼連結如下
http://download.csdn.net/detail/dengrengong/8639579
windows下使用waveout函數族播放wav檔案