自定义的CTPAudioDsound,使用DirectSound

来源:百度文库 编辑:神马文学网 时间:2024/10/03 03:00:34
#pragma once
#define  CDS_SECONDS_SAMPLE  1920 *3*4#define  CDS_SECONDS_EVENT   3#define  CDS_SECONDS_DELAY   1920*2*4
#define VU_MAXLEN    25
#include
typedef struct tag_TPAudioSoundLayer{ int    m_iIndex ; LPDIRECTSOUNDBUFFER              m_pDsb;               //播放缓存  int m_iLastPlayPos; //上次播放位置 LPBYTE m_pBuffer; long m_lReadPos; long m_lWritePos; long m_lBufferLen; tag_TPAudioSoundLayer(long lBufferLen = CDS_SECONDS_SAMPLE*4) { m_iIndex = 0; m_pDsb = NULL; m_iLastPlayPos = 0; m_pBuffer = new BYTE[lBufferLen]; ZeroMemory(m_pBuffer,lBufferLen); m_lReadPos = 0; m_lWritePos = 0; m_lBufferLen = lBufferLen; } ~tag_TPAudioSoundLayer() { if(m_pBuffer) delete [] m_pBuffer; } void Clear() { m_lReadPos = 0; m_lWritePos = m_lBufferLen/2; ZeroMemory(m_pBuffer,m_lBufferLen); } void Reset() { if(m_pDsb) { m_pDsb ->Restore(); m_pDsb ->SetCurrentPosition(0); m_pDsb ->SetVolume(DSBVOLUME_MAX); } m_lReadPos = 0; m_lWritePos = 0; m_iLastPlayPos = 0; ZeroMemory(m_pBuffer,m_lBufferLen); }}TPAudioSoundLayer;typedef CArray TPAudioSoundLayerArray;
class AFX_EXT_CLASS CTPAudioDsound{public: CTPAudioDsound(); ~CTPAudioDsound();public: BOOL (*m_pGetBuffer)(LPBYTE pBuffer[8],long &lSample,void * lParam); void *m_pGetBufferParam; DWORD   m_eVideoStandard;private: LPDIRECTSOUND m_pDirectSound; //主通道指针 LPDIRECTSOUNDNOTIFY m_pdsNotify; //播放事件 DSBPOSITIONNOTIFY m_pgdscbpn[CDS_SECONDS_EVENT]; //播放事件 LPDIRECTSOUNDBUFFER m_pPrimDsb; //辅通道 HANDLE m_hrghEvent[CDS_SECONDS_EVENT]; //播放事件 HANDLE   m_hReadThread; //读文件 DWORD m_dwSndBufLen; //读写设备的Buffer大小 BOOL m_bThreadRun; //线程播放标志 WAVEFORMATEX m_waveFormat; TPAudioSoundLayerArray m_aSoundLayer; int m_iSoundLayer; long m_lLoopLength; long m_lCacheLength; BOOL  m_bDeviceInitOK; DWORD m_uPlayState; CCriticalSection m_Lock; BOOL m_bFirstSample; long m_iDeviceLen;public: HRESULT InitDevice2( int iSoundLayer, HWND hWnd = NULL, int iSamplesPerSec = 48000); void SetBufferLength(long lBuffer,long lLoop,long lDSound); HRESULT ReleaseDevice(); HRESULT OnStop(); HRESULT OnPlay(long lResetSample = -1,BOOL bSetEvent = FALSE); void DoReadThread(); HRESULT InitPrimaryBuffer(WAVEFORMATEX *pwf); //主 HRESULT InitSoundBuffer(WAVEFORMATEX *pwf); //从 int  WriteDataToDevice(LPDIRECTSOUNDBUFFER pDsb,LPBYTE pb, DWORD dwWriteCursor, DWORD dwWriteBytes, BOOL bFillZero);



#include "StdAfx.h"#include ".\tpaudiodsound.h"
#pragma comment (lib, "dsound.lib")
CTPAudioDsound::CTPAudioDsound(){ m_pGetBuffer = NULL; m_pGetBufferParam = NULL; m_eVideoStandard = VIDEO_25; m_pDirectSound = NULL; m_pdsNotify = NULL; m_pPrimDsb = NULL; for(int i = 0 ; i< CDS_SECONDS_EVENT ; i++) { m_hrghEvent[CDS_SECONDS_EVENT] = NULL; } m_iSoundLayer = 0; m_bDeviceInitOK = FALSE; m_uPlayState = 0; m_bFirstSample = TRUE; m_iDeviceLen = 0x7fffff; m_iDeviceLen = 0x7fffff; m_lLoopLength = CDS_SECONDS_SAMPLE*4; m_lCacheLength = CDS_SECONDS_SAMPLE*4; m_dwSndBufLen = CDS_SECONDS_SAMPLE; m_hReadThread = NULL;}
CTPAudioDsound::~CTPAudioDsound(){ }
#define PLAY_PLAY    0x01#define PLAY_RECORD  0x04void CTPAudioDsound::SetBufferLength(long lBuffer,long lLoop,long lDSound){ m_lLoopLength    = lLoop; m_lCacheLength   = lBuffer; m_dwSndBufLen    = lDSound; ASSERT(m_lLoopLength<=m_lCacheLength); ASSERT((long)m_dwSndBufLen<=m_lLoopLength);}
HRESULT CTPAudioDsound::InitDevice2( int iSoundLayer, HWND hWnd, int iSamplesPerSec){ m_iSoundLayer = iSoundLayer;//一个播放层  // 构建一个waveFormat memset(&m_waveFormat, 0, sizeof(WAVEFORMATEX)); m_waveFormat.wFormatTag = WAVE_FORMAT_PCM; m_waveFormat.nChannels = 2; m_waveFormat.nSamplesPerSec = iSamplesPerSec;// 48000 m_waveFormat.nBlockAlign = 4; m_waveFormat.nAvgBytesPerSec = m_waveFormat.nSamplesPerSec * m_waveFormat.nBlockAlign; m_waveFormat.wBitsPerSample = 16; m_waveFormat.cbSize = sizeof(WAVEFORMATEX); m_hSoundWnd = hWnd; if(m_hSoundWnd == NULL) m_hSoundWnd = AfxGetMainWnd() ->GetSafeHwnd(); HRESULT hr = DirectSoundCreate(NULL, &m_pDirectSound, NULL);////创建DirectSound对象;      if(DS_OK == hr)  { if(InitPrimaryBuffer(&m_waveFormat) == NO_ERROR) { if(iSoundLayer >0 && InitSoundBuffer(&m_waveFormat) != NO_ERROR) return S_FALSE; } } return hr;}
HRESULT CTPAudioDsound::InitPrimaryBuffer(WAVEFORMATEX *pwf){ //设置声音设备优先级别为"NORMAL"; hr = m_pDirectSound->SetCooperativeLevel(m_hSoundWnd, DSSCL_NORMAL); if(DS_OK != hr) { m_pDirectSound->Release(); m_pDirectSound = NULL; return FALSE; } DSBUFFERDESC dsbdesc; HRESULT hr; memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GLOBALFOCUS ; dsbdesc.dwBufferBytes = m_dwSndBufLen; dsbdesc.lpwfxFormat = &m_waveFormat; ////创建声音数据缓冲; hr = m_pDirectSound->CreateSoundBuffer(&dsbdesc, &m_pPrimDsb, NULL); if(DS_OK == hr) { hr = m_pPrimDsb->SetFormat(pwf); if(DS_OK == hr) return hr; else return NO_ERROR; } else { m_pDirectSound->Release(); m_pDirectSound = NULL; m_pPrimDsb=NULL; return hr; }}
HRESULT CTPAudioDsound::InitSoundBuffer(WAVEFORMATEX *pwf){ DSBUFFERDESC dsbdesc; HRESULT hr; memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));  dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME ;  dsbdesc.dwBufferBytes = m_dwSndBufLen;  dsbdesc.lpwfxFormat = pwf;

for(int i=0;im_pBuffer == NULL) {ASSERT(0); return S_FALSE;} pReadData ->m_iIndex = i; hr = m_pDirectSound-> CreateSoundBuffer(&dsbdesc, &pReadData -> m_pDsb, NULL); if(DS_OK != hr) { pReadData -> m_pDsb = NULL; continue; } m_aSoundLayer.Add(pReadData);  }
for (int i = 0; i < CDS_SECONDS_EVENT; i++ ) { m_hrghEvent[i] = CreateEvent( NULL, FALSE, FALSE, NULL ); if ( NULL == m_hrghEvent[i] ) return FALSE; m_pgdscbpn[i].dwOffset = ( m_dwSndBufLen *(i+1)/CDS_SECONDS_EVENT) - 1; m_pgdscbpn[i].hEventNotify = m_hrghEvent[i]; } if(m_aSoundLayer[0] == NULL || m_aSoundLayer[0] -> m_pDsb == NULL) return -2; if ( FAILED( hr = m_aSoundLayer[0] -> m_pDsb->QueryInterface( IID_IDirectSoundNotify, ( VOID ** )&m_pdsNotify))) return hr; if ( FAILED( hr = m_pdsNotify->SetNotificationPositions( CDS_SECONDS_EVENT, m_pgdscbpn))) return hr; return NO_ERROR;}
HRESULT  CTPAudioDsound::OnStop(){ if(!(m_uPlayState & PLAY_PLAY)) return S_FALSE; m_uPlayState &= ~PLAY_PLAY;
for(int i=0;im_pDsb!=NULL) m_aSoundLayer[i]->m_pDsb ->Stop(); } if(m_pPrimDsb!=NULL) m_pPrimDsb ->Stop(); m_bThreadRun = FALSE; for(int i=0;iint CTPAudioDsound::WriteDataToDevice(LPDIRECTSOUNDBUFFER  pDsb,LPBYTE pb, DWORD dwWriteCursor, DWORD dwWriteBytes, BOOL bFillZero){ LPVOID lpvPtr1,lpvPtr2; DWORD dwBytes1,dwBytes2;  if(pDsb==NULL) return -100; HRESULT hr = pDsb ->Lock(dwWriteCursor, dwWriteBytes, &lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2,0); if(DSERR_BUFFERLOST == hr) { pDsb ->Restore(); hr = pDsb ->Lock(dwWriteCursor, dwWriteBytes,&lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2, 0); } if(DS_OK == hr) { if(bFillZero) { memset(lpvPtr1, 0, dwBytes1); if(NULL != lpvPtr2)   memset(lpvPtr2, 0, dwBytes2); } else { CopyMemory(lpvPtr1, pb, dwBytes1); if(NULL != lpvPtr2) CopyMemory(lpvPtr2, pb+dwBytes1, dwBytes2); ZeroMemory(pb,dwWriteBytes); } hr = pDsb ->Unlock(lpvPtr1, dwBytes1, lpvPtr2, dwBytes2); if(DS_OK == hr)         return dwBytes1+dwBytes2; else                    return -100; } else  { return -100; }}
HRESULT  CTPAudioDsound::OnPlay(long lResetSample,BOOL bSetEvent){ if(m_uPlayState & PLAY_PLAY)  return S_FALSE;
if(lResetSample<0) lResetSample = m_dwSndBufLen/CDS_SECONDS_EVENT;
for(int i=0;iReset();  if(lResetSample >0) WriteDataToDevice(m_aSoundLayer[i] ->m_pDsb,NULL,m_aSoundLayer[i]->m_iLastPlayPos,lResetSample,TRUE); m_aSoundLayer[i]->m_iLastPlayPos = lResetSample; }
m_bThreadRun  = TRUE; CWinThread *pThread = AfxBeginThread((AFX_THREADPROC)TPAudioDsoundReadThread,this,THREAD_PRIORITY_HIGHEST, 0, CREATE_SUSPENDED);  // 这个线程来取BUFFER m_hReadThread = pThread->m_hThread; pThread->ResumeThread(); m_uPlayState |=  PLAY_PLAY; m_iDeviceLen  = 0x7fffff;
::SetEvent( m_hWriteEvent); //by zhh
for(int i=0;im_pDsb!=NULL) m_aSoundLayer[i]->m_pDsb ->Play(0, 0, DSBPLAY_LOOPING); } if(m_pPrimDsb!=NULL) m_pPrimDsb ->Play(0, 0, DSBPLAY_LOOPING);
if(bSetEvent) { for(int i=0;iUINT TPAudioDsoundReadThread(LPVOID pVoid){ CTPAudioDsound *pApp = (CTPAudioDsound *)pVoid; pApp ->DoReadThread();  return 0;}// 在WaitForMultipleObjects 等待DirectSound的通知,然后读取wave文件将数据填充到DirectSound的空buffer中。void      CTPAudioDsound::DoReadThread(){ DWORD   dwOldEvent = -1; DWORD   dwTime     = 0; int     iWrite     = 0; long    lDefLen    = 1920*4; if(m_eVideoStandard != VIDEO_25) lDefLen = 1602*4;
while(m_bThreadRun) { DWORD dwEvt = WaitForMultipleObjects( CDS_SECONDS_EVENT, m_hrghEvent, FALSE, 20000);
if(!m_bThreadRun) break; if(dwEvt==dwOldEvent || dwEvt>CDS_SECONDS_EVENT) continue; dwOldEvent = dwEvt; m_Lock.Lock(); int iDeviceLen = 0x7fffff; int iBufferLen = 0x7fffff; int iSndLen = m_dwSndBufLen/3; if(m_pGetBuffer) { LPBYTE pBuffer[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; long lSample = 1920; for(int l=0;lm_pBuffer; DWORD dwPlayPos,dwWritePos; int iDistance; LPDIRECTSOUNDBUFFER pDsb =m_aSoundLayer[l]->m_pDsb; if(pDsb != NULL) { pDsb ->GetCurrentPosition(&dwPlayPos, &dwWritePos); iDistance = dwPlayPos - m_aSoundLayer[l] -> m_iLastPlayPos; while(iDistance < 0) iDistance += m_dwSndBufLen; iDeviceLen = min(iDeviceLen,iDistance); } } if(iDeviceLen == 0x7fffff || iDeviceLen =lDefLen) { lSample = iDeviceLen/4; if(m_pGetBuffer(pBuffer,lSample,m_pGetBufferParam)) { for(int l=0;lm_pDsb; iWrite = WriteDataToDevice(pDsb,m_aSoundLayer[l]->m_pBuffer,m_aSoundLayer[l]->m_iLastPlayPos,lSample*4,FALSE); m_aSoundLayer[l]->m_iLastPlayPos = (m_aSoundLayer[l]->m_iLastPlayPos + iWrite)%m_dwSndBufLen; ASSERT(iWrite == lSample*4); } iDeviceLen -= lSample*4; } else break; } } } m_Lock.Unlock(); } m_hReadThread = NULL;}