一个vc++ direct sound播放wav文件的类

头文件

#if !defined(AFX_DIRECTSOUND_H__A20FE86F_118F_11D2_9AB3_0060B0CDC13E__INCLUDED_) 
#define AFX_DIRECTSOUND_H__A20FE86F_118F_11D2_9AB3_0060B0CDC13E__INCLUDED_ 

#if _MSC_VER >= 1000 
#pragma once 
#endif // _MSC_VER >= 1000 

#include 
#include 

#pragma message("linking with Microsoft's DirectSound library ...") 
#pragma comment(lib, "dsound.lib") 

class CDirectSound   
public: 
// 构造、析构函数 
CDirectSound(); 
virtual ~CDirectSound(); 
//创建DirectSound对象 
BOOL Create(LPCTSTR pszResource, CWnd * pWnd = 0); 
BOOL Create(UINT uResourceID, CWnd * pWnd = 0) { 
return Create(MAKEINTRESOURCE(uResourceID), pWnd); 
BOOL Create(LPVOID pSoundData, CWnd * pWnd = 0); 

public: 
//操作函数 
BOOL IsValid() const; 
void Play(DWORD dwStartPosition = 0, BOOL bLoop = FALSE); 
void Stop(); 
void Pause(); 
void Continue(); 
CDirectSound & EnableSound(BOOL bEnable = TRUE) { 
m_bEnabled = bEnable; 
if( ! bEnable ) 
Stop(); 
return * this; 
BOOL IsEnabled() const { return m_bEnabled; } 

protected: 
//设置声音数据缓冲区 
BOOL SetSoundData(LPVOID pSoundData, DWORD dwSoundSize); 
//创建DirectSoundBuffer 
BOOL CreateSoundBuffer(WAVEFORMATEX * pcmwf); 
//获取Wave数据 
BOOL GetWaveData(void * pRes, WAVEFORMATEX * & pWaveHeader, void * & pbWaveData, DWORD & cbWaveSize); 

private: 
//声音数据 
LPVOID m_pTheSound; 
//数据大小 
DWORD m_dwTheSound; 
//DirectSoundBuffer指针 
LPDIRECTSOUNDBUFFER m_pDsb; 
BOOL m_bEnabled; 
//DirectSound对象 
static LPDIRECTSOUND m_lpDirectSound; 
static DWORD m_dwInstances; 
}; 

#endif // !defined(AFX_DIRECTSOUND_H__A20FE86F_118F_11D2_9AB3_0060B0CDC13E__INCLUDED_) 

类的主体

#include "stdafx.h"     
#include "DirectSound.h"     
    
// The following macro is defined since DirectX 5, but will work with     
// older versions too.     
#ifndef DSBLOCK_ENTIREBUFFER     
    #define DSBLOCK_ENTIREBUFFER        0x00000002     
#endif     
    
#ifdef _DEBUG     
#undef THIS_FILE     
static char THIS_FILE[]=__FILE__;    
#define new DEBUG_NEW     
#endif     
    
static void DSError( HRESULT hRes ) {    
    switch(hRes) {    
        case DS_OK: TRACE0("NO ERROR\n"); break;    
        case DSERR_ALLOCATED: TRACE0("ALLOCATED\n"); break;    
        case DSERR_INVALIDPARAM: TRACE0("INVALIDPARAM\n"); break;    
        case DSERR_OUTOFMEMORY: TRACE0("OUTOFMEMORY\n"); break;    
        case DSERR_UNSUPPORTED: TRACE0("UNSUPPORTED\n"); break;    
        case DSERR_NOAGGREGATION: TRACE0("NOAGGREGATION\n"); break;    
        case DSERR_UNINITIALIZED: TRACE0("UNINITIALIZED\n"); break;    
        case DSERR_BADFORMAT: TRACE0("BADFORMAT\n"); break;    
        case DSERR_ALREADYINITIALIZED: TRACE0("ALREADYINITIALIZED\n"); break;    
        case DSERR_BUFFERLOST: TRACE0("BUFFERLOST\n"); break;    
        case DSERR_CONTROLUNAVAIL: TRACE0("CONTROLUNAVAIL\n"); break;    
        case DSERR_GENERIC: TRACE0("GENERIC\n"); break;    
        case DSERR_INVALIDCALL: TRACE0("INVALIDCALL\n"); break;    
        case DSERR_OTHERAPPHASPRIO: TRACE0("OTHERAPPHASPRIO\n"); break;    
        case DSERR_PRIOLEVELNEEDED: TRACE0("PRIOLEVELNEEDED\n"); break;    
        default: TRACE1("%lu\n",hRes);break;    
    }    
}    
    
//////////////////////////////////////////////////////////////////////     
// Construction/Destruction     
//////////////////////////////////////////////////////////////////////     
    
LPDIRECTSOUND CDirectSound::m_lpDirectSound;    
DWORD CDirectSound::m_dwInstances;    
    
    
CDirectSound::CDirectSound()    
{    
    m_lpDirectSound = 0;    
    m_pDsb = 0;    
    m_pTheSound = 0;    
    m_dwTheSound = 0;    
    m_bEnabled = TRUE;    
    
    ++m_dwInstances;    
}    
    
CDirectSound::~CDirectSound()    
{    
    if( m_pDsb )    
        m_pDsb->Release();    
    
    if( !--m_dwInstances && m_lpDirectSound ) {    
        m_lpDirectSound->Release();    
        m_lpDirectSound = 0;    
    }    
}    
    
BOOL CDirectSound::Create(LPCTSTR pszResource, CWnd * pWnd)    
{    
    //////////////////////////////////////////////////////////////////     
    // load resource     
    HINSTANCE hApp = ::GetModuleHandle(0);    
    ASSERT(hApp);    
    
    HRSRC hResInfo = ::FindResource(hApp, pszResource, TEXT("WAVE"));    
    if(hResInfo == 0)    
        return FALSE;    
    
    HGLOBAL hRes = ::LoadResource(hApp, hResInfo);    
    if(hRes == 0)    
        return FALSE;    
    
    LPVOID pTheSound = ::LockResource(hRes);    
    if(pTheSound == 0)    
        return FALSE;    
    
    return Create(pTheSound, pWnd);    
}    
    
    
BOOL CDirectSound :: Create(LPVOID pSoundData, CWnd * pWnd) {    
    //获取窗口句柄     
    if(pWnd == 0)    
        pWnd = AfxGetApp()->GetMainWnd();    
    ASSERT(pWnd != 0);    
    ASSERT(::IsWindow(pWnd->GetSafeHwnd()));    
    ASSERT(pSoundData != 0);    
    //创建DirectSound 对象     
    if( m_lpDirectSound == 0 )     
    {    
        HRESULT hRes = DS_OK;    
        short nRes = 0;    
        do {    
            if( nRes )    
                ::Sleep(500);    
            hRes = ::DirectSoundCreate(0, &m_lpDirectSound, 0);    
            ++nRes;    
        } while( nRes < 10 && (hRes == DSERR_ALLOCATED || hRes == DSERR_NODRIVER) );    
            
        if( hRes != DS_OK )    
            return FALSE;    
        //设置协调模式     
        m_lpDirectSound->SetCooperativeLevel(pWnd->GetSafeHwnd(), DSSCL_NORMAL);    
    }    
    ASSERT(m_lpDirectSound != 0);    
    //准备数据     
    WAVEFORMATEX * pcmwf;    
    if( ! GetWaveData(pSoundData, pcmwf, m_pTheSound, m_dwTheSound) ||    
        ! CreateSoundBuffer(pcmwf) ||    
        ! SetSoundData(m_pTheSound, m_dwTheSound) )    
        return FALSE;    
        
    return TRUE;    
}    
    
    
BOOL CDirectSound :: GetWaveData(void * pRes, WAVEFORMATEX * & pWaveHeader, void * & pbWaveData, DWORD & cbWaveSize) {    
    pWaveHeader = 0;    
    pbWaveData = 0;    
    cbWaveSize = 0;    
        
    DWORD * pdw = (DWORD *)pRes;    
    DWORD dwRiff = *pdw++;    
    DWORD dwLength = *pdw++;    
    DWORD dwType = *pdw++;    
    //检验“RIFF”标志     
    if( dwRiff != mmioFOURCC('R', 'I', 'F', 'F') )    
        return FALSE;          
    //检验“WAVE”标志     
    if( dwType != mmioFOURCC('W', 'A', 'V', 'E') )    
        return FALSE;          
    //指向声音数据     
    DWORD * pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);    
    //查找声音数据     
    while( pdw < pdwEnd )     
    {    
        dwType = *pdw++;    
        dwLength = *pdw++;    
        switch( dwType ) {    
        case mmioFOURCC('f', 'm', 't', ' '):    
            if( !pWaveHeader )     
            {    
                if( dwLength < sizeof(WAVEFORMAT) )    
                    return FALSE;          
                pWaveHeader = (WAVEFORMATEX *)pdw;    
                if( pbWaveData && cbWaveSize )    
                    return TRUE;    
            }    
            break;    
                
        case mmioFOURCC('d', 'a', 't', 'a'):    
            pbWaveData = LPVOID(pdw);    
            cbWaveSize = dwLength;    
            if( pWaveHeader )    
                return TRUE;    
            break;    
        }    
        pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));    
    }    
        
    return FALSE;    
}    
    
    
BOOL CDirectSound::CreateSoundBuffer(WAVEFORMATEX * pcmwf)    
{    
    DSBUFFERDESC dsbdesc;    
        
    //初始化DSBUFFERDESC structure.     
    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));     
    dsbdesc.dwSize = sizeof(DSBUFFERDESC);    
    // 不需要控制pan, volume, frequency     
    dsbdesc.dwFlags = DSBCAPS_STATIC;       
    dsbdesc.dwBufferBytes = m_dwTheSound;    
    dsbdesc.lpwfxFormat = pcmwf;        
    HRESULT hRes;    
    if( DS_OK != (hRes = m_lpDirectSound->CreateSoundBuffer(&dsbdesc, &m_pDsb, 0)) )    
    {    
        // Failed.     
        DSError(hRes);    
        m_pDsb = 0;    
        return FALSE;    
    }    
        
    return TRUE;    
}    
    
    
BOOL CDirectSound::SetSoundData(void * pSoundData, DWORD dwSoundSize) {    
    LPVOID lpvPtr1;    
    DWORD dwBytes1;    
    // 获取一块内存     
    HRESULT hr = m_pDsb->Lock(0, 0, &lpvPtr1, &dwBytes1, 0, 0, DSBLOCK_ENTIREBUFFER);        
    //如果失败,重新分配      
    if(DSERR_BUFFERLOST == hr)     
    {    
        m_pDsb->Restore();    
        hr = m_pDsb->Lock(0, 0, &lpvPtr1, &dwBytes1, 0, 0, DSBLOCK_ENTIREBUFFER);    
    }    
    if(DS_OK == hr) {    
        // 复制声音数据     
        ::CopyMemory(lpvPtr1, pSoundData, dwBytes1);    
        //释放锁定的内存块     
        hr = m_pDsb->Unlock(lpvPtr1, dwBytes1, 0, 0);    
        if(DS_OK == hr)    
            return TRUE;    
    }    
    return FALSE;    
}    
    
void CDirectSound::Play(DWORD dwStartPosition, BOOL bLoop)    
{    
    if( ! IsValid() || ! IsEnabled() )    
        return;         
    //播放位置边界检验     
    if( dwStartPosition > m_dwTheSound )    
        dwStartPosition = m_dwTheSound;    
    //重新设置播放位置     
    m_pDsb->SetCurrentPosition(dwStartPosition);    
    //开始播放     
    if( DSERR_BUFFERLOST == m_pDsb->Play(0, 0, bLoop ? DSBPLAY_LOOPING : 0) ) {    
        SetSoundData(m_pTheSound, m_dwTheSound);    
        m_pDsb->Play(0, 0, bLoop ? DSBPLAY_LOOPING : 0);    
    }    
}    
    
void CDirectSound::Stop()    
{    
    if( IsValid() )    
        m_pDsb->Stop();    
}    
    
void CDirectSound::Pause()    
{    
    Stop();    
}    
    
void CDirectSound::Continue()    
{    
    if( IsValid() )     
    {    
        DWORD dwPlayCursor, dwWriteCursor;    
        m_pDsb->GetCurrentPosition(&dwPlayCursor, &dwWriteCursor);    
        Play(dwPlayCursor);    
    }    
}    
    
BOOL CDirectSound::IsValid() const    
{    
    return (m_lpDirectSound && m_pDsb && m_pTheSound && m_dwTheSound) ? TRUE : FALSE;    
posted on 2010-05-30 21:35  carekee  阅读(1332)  评论(0编辑  收藏  举报