DirectSound.cpp
上传用户:hygd004
上传日期:2022-02-04
资源大小:1841k
文件大小:10k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1998 by J鰎g K鰊ig
  3. // All rights reserved
  4. //
  5. // This file is part of the completely free tetris clone "CGTetris".
  6. //
  7. // This is free software.
  8. // You may redistribute it by any means providing it is not sold for profit
  9. // without the authors written consent.
  10. //
  11. // No warrantee of any kind, expressed or implied, is included with this
  12. // software; use at your own risk, responsibility for damages (if any) to
  13. // anyone resulting from the use of this software rests entirely with the
  14. // user.
  15. //
  16. // Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  17. // I'll try to keep a version up to date.  I can be reached as follows:
  18. //    J.Koenig@adg.de                 (company site)
  19. //    Joerg.Koenig@rhein-neckar.de    (private site)
  20. /////////////////////////////////////////////////////////////////////////////
  21. // DirectSound.cpp: implementation of the CDirectSound class.
  22. //
  23. //////////////////////////////////////////////////////////////////////
  24. #include "stdafx.h"
  25. #include "DirectSound.h"
  26. #include "INITGUID.h"
  27. // The following macro is defined since DirectX 5, but will work with
  28. // older versions too.
  29. #ifndef DSBLOCK_ENTIREBUFFER
  30. #define DSBLOCK_ENTIREBUFFER        0x00000002
  31. #endif
  32. #ifdef _DEBUG
  33. #undef THIS_FILE
  34. static char THIS_FILE[]=__FILE__;
  35. #define new DEBUG_NEW
  36. #endif
  37. static void DSError( HRESULT hRes ) {
  38. switch(hRes) {
  39. case DS_OK: TRACE0("NO ERRORn"); break;
  40. case DSERR_ALLOCATED: TRACE0("ALLOCATEDn"); break;
  41. case DSERR_INVALIDPARAM: TRACE0("INVALIDPARAMn"); break;
  42. case DSERR_OUTOFMEMORY: TRACE0("OUTOFMEMORYn"); break;
  43. case DSERR_UNSUPPORTED: TRACE0("UNSUPPORTEDn"); break;
  44. case DSERR_NOAGGREGATION: TRACE0("NOAGGREGATIONn"); break;
  45. case DSERR_UNINITIALIZED: TRACE0("UNINITIALIZEDn"); break;
  46. case DSERR_BADFORMAT: TRACE0("BADFORMATn"); break;
  47. case DSERR_ALREADYINITIALIZED: TRACE0("ALREADYINITIALIZEDn"); break;
  48. case DSERR_BUFFERLOST: TRACE0("BUFFERLOSTn"); break;
  49. case DSERR_CONTROLUNAVAIL: TRACE0("CONTROLUNAVAILn"); break;
  50. case DSERR_GENERIC: TRACE0("GENERICn"); break;
  51. case DSERR_INVALIDCALL: TRACE0("INVALIDCALLn"); break;
  52. case DSERR_OTHERAPPHASPRIO: TRACE0("OTHERAPPHASPRIOn"); break;
  53. case DSERR_PRIOLEVELNEEDED: TRACE0("PRIOLEVELNEEDEDn"); break;
  54. default: TRACE1("%lun",hRes);break;
  55. }
  56. }
  57. //////////////////////////////////////////////////////////////////////
  58. // Construction/Destruction
  59. //////////////////////////////////////////////////////////////////////
  60. LPDIRECTSOUND CDirectSound::m_lpDirectSound;
  61. DWORD CDirectSound::m_dwInstances;
  62. CDirectSound::CDirectSound()
  63. {
  64. m_lpDirectSound = 0;
  65. m_pDsb = 0;
  66. // m_pTheSound = new BYTE[20481];
  67. m_dwTheSound = 0;
  68. m_bEnabled = TRUE;
  69. m_bPlay = 0;
  70. ++m_dwInstances;
  71. m_hPlayThread = 0;
  72. m_dwBufNum = 2;
  73. m_dwBufLen = 1024;
  74. }
  75. CDirectSound::~CDirectSound()
  76. {
  77. delete[] 20480;
  78. if( m_pDsb )
  79. m_pDsb->Release();
  80. if( !--m_dwInstances && m_lpDirectSound ) {
  81. m_lpDirectSound->Release();
  82. m_lpDirectSound = 0;
  83. }
  84. }
  85. BOOL CDirectSound :: CreateDSound(void* pHeader,DWORD& dwHeadLen)
  86. {
  87. if(m_lpDirectSound)
  88. {
  89. return TRUE;
  90. }
  91. HRESULT hRes = DS_OK;
  92. short nRes = 0;
  93. do {
  94. if( nRes )
  95. ::Sleep(500);
  96. hRes = ::DirectSoundCreate(0, &m_lpDirectSound, 0);
  97. ++nRes;
  98. while( nRes < 10 && (hRes == DSERR_ALLOCATED || hRes == DSERR_NODRIVER) );
  99. if( hRes != DS_OK )
  100. return FALSE;
  101. m_lpDirectSound->SetCooperativeLevel(m_hWnd, DSSCL_NORMAL);
  102. WAVEFORMATEX * pcmwf;
  103. // DWORD dwHeadLen = 1000;
  104. if(!GetWaveData(pHeader, pcmwf, m_dwBufNum) )
  105. return FALSE;
  106. if(!CreateSoundBuffer(pcmwf))
  107. return FALSE;
  108. SetSoundData(0,m_pTheSound, m_dwTheSound);
  109. m_bPlay = TRUE;
  110. dwHeadLen = m_dwTheSound;
  111. return TRUE;
  112. }
  113. BOOL CDirectSound :: GetWaveData(void * pRes, WAVEFORMATEX * & pWaveHeader, 
  114.  void * & pbWaveData, DWORD & cbWaveSize
  115.  )
  116. {
  117. pWaveHeader = 0;
  118. pbWaveData = 0;
  119. cbWaveSize = 0;
  120. DWORD * pdw = (DWORD *)pRes;
  121. DWORD dwRiff = *pdw++;
  122. DWORD dwLength = *pdw++;
  123. DWORD dwType = *pdw++;
  124. if( dwRiff != mmioFOURCC('R', 'I', 'F', 'F') )
  125. return FALSE;      // not even RIFF
  126. if( dwType != mmioFOURCC('W', 'A', 'V', 'E') )
  127. return FALSE;      // not a WAV
  128. DWORD * pdwEnd = (DWORD *)((BYTE *)pdw + 1000-4);
  129. while( pdw < pdwEnd ) {
  130. dwType = *pdw++;
  131. dwLength = *pdw++;
  132. switch( dwType ) {
  133. case mmioFOURCC('f', 'm', 't', ' '):
  134. if( !pWaveHeader ) {
  135. if( dwLength < sizeof(WAVEFORMAT) )
  136. return FALSE;      // not a WAV
  137. pWaveHeader = (WAVEFORMATEX *)pdw;
  138. if( pbWaveData && cbWaveSize )
  139. return TRUE;
  140. }
  141. break;
  142. case mmioFOURCC('d', 'a', 't', 'a'):
  143. pbWaveData = LPVOID(pdw);
  144. cbWaveSize = dwLength;
  145. if( pWaveHeader )
  146. return TRUE;
  147. break;
  148. }
  149. pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
  150. }
  151. return FALSE;
  152. }
  153. BOOL CDirectSound :: GetWaveData(void * pHeader, WAVEFORMATEX * & pWaveHeader,
  154.   DWORD & dwHeadSize)
  155. {
  156. dwHeadSize  = 0;
  157. pWaveHeader = 0;
  158. DWORD * pdw = (DWORD *)pHeader;
  159. DWORD dwRiff = *pdw++;
  160. DWORD dwLength = *pdw++;
  161. DWORD dwType = *pdw++;
  162. m_dwTotalSize = dwLength;
  163. if( dwRiff != mmioFOURCC('R', 'I', 'F', 'F') )
  164. return FALSE;      // not even RIFF
  165. if( dwType != mmioFOURCC('W', 'A', 'V', 'E') )
  166. return FALSE;      // not a WAV
  167. dwType = *pdw++;
  168. dwLength = *pdw++;
  169. if(dwType!= mmioFOURCC('f', 'm', 't', ' '))
  170. return FALSE;
  171. if( !pWaveHeader )
  172. {
  173. if( dwLength < sizeof(WAVEFORMAT) )
  174. return FALSE;      // not a WAV
  175. pWaveHeader = (WAVEFORMATEX *)pdw;
  176. }
  177. dwHeadSize += 5*sizeof(DWORD);
  178. return TRUE;
  179. }
  180. BOOL CDirectSound::WriteToBuf(BYTE* pBuf,DWORD dwLen)
  181. {
  182. // m_bPlay = TRUE;
  183. if(m_bFir)
  184. {
  185. m_bFir = FALSE;
  186. ::CopyMemory(m_pTheSound, pBuf, dwLen);
  187. SetSoundData( m_dwOffset,m_pTheSound, dwLen);
  188. }
  189. int id = WaitForMultipleObjects(m_dwBufNum,notify_events,0,INFINITE);
  190. if (id<m_dwBufNum)
  191. {
  192. m_dwOffset = id;
  193. ::CopyMemory(m_pTheSound, pBuf, dwLen);
  194. SetSoundData( m_dwOffset,m_pTheSound, dwLen);
  195. }
  196. return TRUE;
  197. // SetSoundData(m_pSoundBuf,dwSoundSize);
  198. }
  199. BOOL CDirectSound::CreateSoundBuffer(WAVEFORMATEX * pcmwf)
  200. {
  201. DSBUFFERDESC dsbdesc;
  202. // Set up DSBUFFERDESC structure.
  203. memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
  204. dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  205. // Need no controls (pan, volume, frequency).
  206. dsbdesc.dwFlags = DSBCAPS_STATIC; // assumes that the sound is played often
  207. dsbdesc.dwBufferBytes =m_dwBufNum*m_dwBufLen;// m_dwTheSound;
  208. dsbdesc.lpwfxFormat = pcmwf;    // Create buffer.
  209. HRESULT hRes;
  210. if( DS_OK != (hRes = m_lpDirectSound->CreateSoundBuffer(&dsbdesc, &m_pDsb, 0)) ) {
  211. // Failed.
  212. DSError(hRes);
  213. m_pDsb = 0;
  214. return FALSE;
  215. }
  216. for (int i=0;i<m_dwBufNum;i++)
  217. {
  218. //create dsound buffer notify points
  219. //Auto reset event
  220. m_hEvent=CreateEvent( NULL, FALSE, FALSE, NULL );
  221. DSNotify[i].hEventNotify=m_hEvent; 
  222. DSNotify[i].dwOffset=i*(m_dwBufLen);//NOTIFYNUM);
  223. }
  224. // hRes = m_pDsb->QueryInterface(IID_IDirectSoundNotify,(LPVOID *)&m_pDsNotify); 
  225.     if (FAILED(hRes)) //SUCCEEDED
  226. {
  227.           return FALSE;
  228. }
  229. //NOTIFYNUM notify point
  230. hRes=m_pDsNotify->SetNotificationPositions(m_dwBufNum,DSNotify); 
  231. if (FAILED(hRes)) //SUCCEEDED
  232. {
  233.      
  234.  return FALSE;
  235. }
  236. for (int n=0;n< m_dwBufNum;n++)
  237. {
  238. notify_events[n]=DSNotify[n].hEventNotify;
  239. ResetEvent(notify_events[n]); 
  240. }
  241. return TRUE;
  242. }
  243. BOOL CDirectSound::SetSoundData(DWORD Offset,void * pSoundData, DWORD dwSoundSize)
  244. {
  245. LPVOID lpPart1;
  246.     LPVOID lpPart2;
  247.     DWORD  Part1Len,Part2Len;
  248. // LPVOID lpvPtr1;
  249. // DWORD dwBytes1;
  250. // Obtain write pointer.
  251. HRESULT hr = m_pDsb->Lock(Offset, 0, &lpPart1, &Part1Len, &lpPart2, &Part2Len, DSBLOCK_ENTIREBUFFER);    
  252.     // If DSERR_BUFFERLOST is returned, restore and retry lock.
  253. if(DSERR_BUFFERLOST == hr) {
  254. m_pDsb->Restore();
  255. hr = m_pDsb->Lock(Offset, 0, &lpPart1, &Part1Len, &lpPart2, &Part2Len, DSBLOCK_ENTIREBUFFER);
  256. }
  257. if(DS_OK == hr) {
  258. // Write to pointers.
  259. ::CopyMemory(lpPart1, pSoundData, Part1Len);
  260. if (lpPart2)
  261. {
  262. ::CopyMemory(lpPart2, (BYTE*)pSoundData+Part1Len, Part2Len);
  263. }
  264. // Release the data back to DirectSound.
  265. hr = m_pDsb->Unlock(lpPart1, Part1Len, lpPart2, Part2Len);
  266. if(DS_OK == hr)
  267.             return TRUE;
  268. }
  269. // Lock, Unlock, or Restore failed.
  270. return FALSE;
  271. }
  272. DWORD WINAPI PlayProc(LPVOID pOwner)
  273. {
  274. CDirectSound * pThis = (CDirectSound*) pOwner;
  275. pThis->PlayThread();
  276. return 1;
  277. }
  278. void CDirectSound::PlayThread()
  279. {
  280. // while(!m_bPlay)
  281. // {
  282. // Sleep(10);
  283. // }
  284. //
  285. //// if( dwStartPosition > m_dwTheSound )
  286. //// dwStartPosition = m_dwTheSound;
  287. ////
  288. //// m_pDsb->SetCurrentPosition(dwStartPosition);
  289. //// SetSoundData(m_pSoundBuf,m_dwLen);
  290. //// while(1)
  291. // {
  292. //
  293. // if( DSERR_BUFFERLOST == m_pDsb->Play(0, 0, 0) ) {
  294. // // another application had stolen our buffer
  295. // // Note that a "Restore()" is not enough, because
  296. // // the sound data is invalid after Restore().
  297. // SetSoundData(m_pSoundBuf, m_dwLen);
  298. //
  299. // // Try playing again
  300. // m_pDsb->Play(0, 0,  0);
  301. //
  302. // }
  303. // Sleep(10000);
  304. // }
  305. }
  306. void CDirectSound::Play(DWORD dwStartPosition, BOOL bLoop)
  307. {
  308. if( ! IsValid() || ! IsEnabled() )
  309. return; // no chance to play the sound ...
  310. DWORD dwID;
  311. // m_hPlayThread =  CreateThread(0,0,PlayProc,this,0,&dwID);
  312. m_hPlayThread =  _beginthread(0,0,PlayProc,this,0,&dwID);
  313. }
  314. void CDirectSound::Stop()
  315. {
  316. if( IsValid() )
  317. m_pDsb->Stop();
  318. }
  319. void CDirectSound::Pause()
  320. {
  321. Stop();
  322. }
  323. void CDirectSound::Continue()
  324. {
  325. if( IsValid() ) {
  326. DWORD dwPlayCursor, dwWriteCursor;
  327. m_pDsb->GetCurrentPosition(&dwPlayCursor, &dwWriteCursor);
  328. Play(dwPlayCursor);
  329. }
  330. }
  331. BOOL CDirectSound::IsValid() const
  332. {
  333. return (m_lpDirectSound && m_pDsb ) ? TRUE : FALSE;
  334. }