一个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;
- }