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
相关文章
相关标签/搜索