windows下使用waveout函數族播放wav文件

  要使用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;

實際上也就是一個設備指針oop

第二個參數爲設備類型,其中選擇WAVE_MAPPER能選一個可以播放給定格式的波形音頻輸出裝置this

第三個參數爲音頻數據的格式信息spa

第四個參數是一個回調函數.net

第五個是回調函數的資源句柄指針

第六個是打開裝置的標識,具體的描述能夠去看msdn成功後返回MMSYSERR_NOERROR ,不然返回如下值:code

值描述
MMSYSERR_ALLOCATED   表示資源已存在
MMSYSERR_BADDEVICEID   裝置ID超出範圍
MMSYSERR_NODRIVER   沒有驅動
MMSYSERR_NOMEM    不能分配內存
WAVERR_BADFORMAT   企圖打開一個不被支持的格式
WAVERR_SYNC 裝置是可同步的,但waveOutOpen沒用有WAVE_ALLOWSYNCorm

 

打開音頻設備以後就須要準備音頻的格式信息了,這裏須要第二個結構體

/* 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
相關文章
相關標籤/搜索