现在的位置: 首页 > 综合 > 正文

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

2013年07月07日 ⁄ 综合 ⁄ 共 8979字 ⁄ 字号 评论关闭

头文件

#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_)

 

 

类的主体

  1. #include "stdafx.h"    
  2. #include "DirectSound.h"    
  3.    
  4. // The following macro is defined since DirectX 5, but will work with    
  5. // older versions too.    
  6. #ifndef DSBLOCK_ENTIREBUFFER    
  7.     #define DSBLOCK_ENTIREBUFFER        0x00000002    
  8. #endif    
  9.    
  10. #ifdef _DEBUG    
  11. #undef THIS_FILE    
  12. static char THIS_FILE[]=__FILE__;   
  13. #define new DEBUG_NEW    
  14. #endif    
  15.    
  16. static void DSError( HRESULT hRes ) {   
  17.     switch(hRes) {   
  18.         case DS_OK: TRACE0("NO ERROR/n"); break;   
  19.         case DSERR_ALLOCATED: TRACE0("ALLOCATED/n"); break;   
  20.         case DSERR_INVALIDPARAM: TRACE0("INVALIDPARAM/n"); break;   
  21.         case DSERR_OUTOFMEMORY: TRACE0("OUTOFMEMORY/n"); break;   
  22.         case DSERR_UNSUPPORTED: TRACE0("UNSUPPORTED/n"); break;   
  23.         case DSERR_NOAGGREGATION: TRACE0("NOAGGREGATION/n"); break;   
  24.         case DSERR_UNINITIALIZED: TRACE0("UNINITIALIZED/n"); break;   
  25.         case DSERR_BADFORMAT: TRACE0("BADFORMAT/n"); break;   
  26.         case DSERR_ALREADYINITIALIZED: TRACE0("ALREADYINITIALIZED/n"); break;   
  27.         case DSERR_BUFFERLOST: TRACE0("BUFFERLOST/n"); break;   
  28.         case DSERR_CONTROLUNAVAIL: TRACE0("CONTROLUNAVAIL/n"); break;   
  29.         case DSERR_GENERIC: TRACE0("GENERIC/n"); break;   
  30.         case DSERR_INVALIDCALL: TRACE0("INVALIDCALL/n"); break;   
  31.         case DSERR_OTHERAPPHASPRIO: TRACE0("OTHERAPPHASPRIO/n"); break;   
  32.         case DSERR_PRIOLEVELNEEDED: TRACE0("PRIOLEVELNEEDED/n"); break;   
  33.         default: TRACE1("%lu/n",hRes);break;   
  34.     }   
  35. }   
  36.    
  37. //////////////////////////////////////////////////////////////////////    
  38. // Construction/Destruction    
  39. //////////////////////////////////////////////////////////////////////    
  40.    
  41. LPDIRECTSOUND CDirectSound::m_lpDirectSound;   
  42. DWORD CDirectSound::m_dwInstances;   
  43.    
  44.    
  45. CDirectSound::CDirectSound()   
  46. {   
  47.     m_lpDirectSound = 0;   
  48.     m_pDsb = 0;   
  49.     m_pTheSound = 0;   
  50.     m_dwTheSound = 0;   
  51.     m_bEnabled = TRUE;   
  52.    
  53.     ++m_dwInstances;   
  54. }   
  55.    
  56. CDirectSound::~CDirectSound()   
  57. {   
  58.     if( m_pDsb )   
  59.         m_pDsb->Release();   
  60.    
  61.     if( !--m_dwInstances && m_lpDirectSound ) {   
  62.         m_lpDirectSound->Release();   
  63.         m_lpDirectSound = 0;   
  64.     }   
  65. }   
  66.    
  67. BOOL CDirectSound::Create(LPCTSTR pszResource, CWnd * pWnd)   
  68. {   
  69.     //////////////////////////////////////////////////////////////////    
  70.     // load resource    
  71.     HINSTANCE hApp = ::GetModuleHandle(0);   
  72.     ASSERT(hApp);   
  73.    
  74.     HRSRC hResInfo = ::FindResource(hApp, pszResource, TEXT("WAVE"));   
  75.     if(hResInfo == 0)   
  76.         return FALSE;   
  77.    
  78.     HGLOBAL hRes = ::LoadResource(hApp, hResInfo);   
  79.     if(hRes == 0)   
  80.         return FALSE;   
  81.    
  82.     LPVOID pTheSound = ::LockResource(hRes);   
  83.     if(pTheSound == 0)   
  84.         return FALSE;   
  85.    
  86.     return Create(pTheSound, pWnd);   
  87. }   
  88.    
  89.    
  90. BOOL CDirectSound :: Create(LPVOID pSoundData, CWnd * pWnd) {   
  91.     //获取窗口句柄    
  92.     if(pWnd == 0)   
  93.         pWnd = AfxGetApp()->GetMainWnd();   
  94.     ASSERT(pWnd != 0);   
  95.     ASSERT(::IsWindow(pWnd->GetSafeHwnd()));   
  96.     ASSERT(pSoundData != 0);   
  97.     //创建DirectSound 对象    
  98.     if( m_lpDirectSound == 0 )    
  99.     {   
  100.         HRESULT hRes = DS_OK;   
  101.         short nRes = 0;   
  102.         do {   
  103.             if( nRes )   
  104.                 ::Sleep(500);   
  105.             hRes = ::DirectSoundCreate(0, &m_lpDirectSound, 0);   
  106.             ++nRes;   
  107.         } while( nRes < 10 && (hRes == DSERR_ALLOCATED || hRes == DSERR_NODRIVER) );   
  108.            
  109.         if( hRes != DS_OK )   
  110.             return FALSE;   
  111.         //设置协调模式    
  112.         m_lpDirectSound->SetCooperativeLevel(pWnd->GetSafeHwnd(), DSSCL_NORMAL);   
  113.     }   
  114.     ASSERT(m_lpDirectSound != 0);   
  115.     //准备数据    
  116.     WAVEFORMATEX * pcmwf;   
  117.     if( ! GetWaveData(pSoundData, pcmwf, m_pTheSound, m_dwTheSound) ||   
  118.         ! CreateSoundBuffer(pcmwf) ||   
  119.         ! SetSoundData(m_pTheSound, m_dwTheSound) )   
  120.         return FALSE;   
  121.        
  122.     return TRUE;   
  123. }   
  124.    
  125.    
  126. BOOL CDirectSound :: GetWaveData(void * pRes, WAVEFORMATEX * & pWaveHeader, void * & pbWaveData, DWORD & cbWaveSize) {   
  127.     pWaveHeader = 0;   
  128.     pbWaveData = 0;   
  129.     cbWaveSize = 0;   
  130.        
  131.     DWORD * pdw = (DWORD *)pRes;   
  132.     DWORD dwRiff = *pdw++;   
  133.     DWORD dwLength = *pdw++;   
  134.     DWORD dwType = *pdw++;   
  135.     //检验“RIFF”标志    
  136.     if( dwRiff != mmioFOURCC('R''I''F''F') )   
  137.         return FALSE;         
  138.     //检验“WAVE”标志    
  139.     if( dwType != mmioFOURCC('W''A''V''E') )   
  140.         return FALSE;         
  141.     //指向声音数据    
  142.     DWORD * pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);   
  143.     //查找声音数据    
  144.     while( pdw < pdwEnd )    
  145.     {   
  146.         dwType = *pdw++;   
  147.         dwLength = *pdw++;   
  148.         switch( dwType ) {   
  149.         case mmioFOURCC('f''m''t'' '):   
  150.             if( !pWaveHeader )    
  151.             {   
  152.                 if( dwLength < sizeof(WAVEFORMAT) )   
  153.                     return FALSE;         
  154.                 pWaveHeader = (WAVEFORMATEX *)pdw;   
  155.                 if( pbWaveData && cbWaveSize )   
  156.                     return TRUE;   
  157.             }   
  158.             break;   
  159.                
  160.         case mmioFOURCC('d''a''t''a'):   
  161.             pbWaveData = LPVOID(pdw);   
  162.             cbWaveSize = dwLength;   
  163.             if( pWaveHeader )   
  164.                 return TRUE;   
  165.             break;   
  166.         }   
  167.         pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));   
  168.     }   
  169.        
  170.     return FALSE;   
  171. }   
  172.    
  173.    
  174. BOOL CDirectSound::CreateSoundBuffer(WAVEFORMATEX * pcmwf)   
  175. {   
  176.     DSBUFFERDESC dsbdesc;   
  177.        
  178.     //初始化DSBUFFERDESC structure.    
  179.     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));    
  180.     dsbdesc.dwSize = sizeof(DSBUFFERDESC);   
  181.     // 不需要控制pan, volume, frequency    
  182.     dsbdesc.dwFlags = DSBCAPS_STATIC;      
  183.     dsbdesc.dwBufferBytes = m_dwTheSound;   
  184.     dsbdesc.lpwfxFormat = pcmwf;       
  185.     HRESULT hRes;   
  186.     if( DS_OK != (hRes = m_lpDirectSound->CreateSoundBuffer(&dsbdesc, &m_pDsb, 0)) )   
  187.     {   
  188.         // Failed.    
  189.         DSError(hRes);   
  190.         m_pDsb = 0;   
  191.         return FALSE;   
  192.     }   
  193.        
  194.     return TRUE;   
  195. }   
  196.    
  197.    
  198. BOOL CDirectSound::SetSoundData(void * pSoundData, DWORD dwSoundSize) {   
  199.     LPVOID lpvPtr1;   
  200.     DWORD dwBytes1;   
  201.     // 获取一块内存    
  202.     HRESULT hr = m_pDsb->Lock(0, 0, &lpvPtr1, &dwBytes1, 0, 0, DSBLOCK_ENTIREBUFFER);       
  203.     //如果失败,重新分配     
  204.     if(DSERR_BUFFERLOST == hr)    
  205.     {   
  206.         m_pDsb->Restore();   
  207.         hr = m_pDsb->Lock(0, 0, &lpvPtr1, &dwBytes1, 0, 0, DSBLOCK_ENTIREBUFFER);   
  208.     }   
  209.     if(DS_OK == hr) {   
  210.         // 复制声音数据    
  211.         ::CopyMemory(lpvPtr1, pSoundData, dwBytes1);   
  212.         //释放锁定的内存块    
  213.         hr = m_pDsb->Unlock(lpvPtr1, dwBytes1, 0, 0);   
  214.         if(DS_OK == hr)   
  215.             return TRUE;   
  216.     }   
  217.     return FALSE;   
  218. }   
  219.    
  220. void CDirectSound::Play(DWORD dwStartPosition, BOOL bLoop)   
  221. {   
  222.     if( ! IsValid() || ! IsEnabled() )   
  223.         return;        
  224.     //播放位置边界检验    
  225.     if( dwStartPosition > m_dwTheSound )   
  226.         dwStartPosition = m_dwTheSound;   
  227.     //重新设置播放位置    
  228.     m_pDsb->SetCurrentPosition(dwStartPosition);   
  229.     //开始播放    
  230.     if( DSERR_BUFFERLOST == m_pDsb->Play(0, 0, bLoop ? DSBPLAY_LOOPING : 0) ) {   
  231.         SetSoundData(m_pTheSound, m_dwTheSound);   
  232.         m_pDsb->Play(0, 0, bLoop ? DSBPLAY_LOOPING : 0);   
  233.     }   
  234. }   
  235.    
  236. void CDirectSound::Stop()   
  237. {   
  238.     if( IsValid() )   
  239.         m_pDsb->Stop();   
  240. }   
  241.    
  242. void CDirectSound::Pause()   
  243. {   
  244.     Stop();   
  245. }   
  246.    
  247. void CDirectSound::Continue()   
  248. {   
  249.     if( IsValid() )    
  250.     {   
  251.         DWORD dwPlayCursor, dwWriteCursor;   
  252.         m_pDsb->GetCurrentPosition(&dwPlayCursor, &dwWriteCursor);   
  253.         Play(dwPlayCursor);   
  254.     }   
  255. }   
  256.    
  257. BOOL CDirectSound::IsValid() const   
  258. {   
  259.     return (m_lpDirectSound && m_pDsb && m_pTheSound && m_dwTheSound) ? TRUE : FALSE;   
  260. }   

抱歉!评论已关闭.