AudioRenderer.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:7k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /**************************************************************************************
  2.  *                                                                                    *
  3.  *                                                                                    *
  4.  **************************************************************************************/
  5. #include "AudioRenderer.h"
  6. #define PERIOD 30
  7. MediaAudioRenderer::MediaAudioRenderer()
  8. {
  9. this->lpDirectSound = NULL;
  10. this->lpBuffer      = NULL;
  11. }
  12. MediaAudioRenderer::~MediaAudioRenderer()
  13. {
  14. }
  15. media_type_t  MediaAudioRenderer::GetType()
  16. {
  17. return MEDIA_TYPE_AUDIO_RENDERER;
  18. }
  19. char         *MediaAudioRenderer::GetName()
  20. {
  21. return "DirectSound Audio Renderer";
  22. }
  23. MP_RESULT     MediaAudioRenderer::Connect(MediaItem *item)
  24. {
  25. return MP_RESULT_ERROR;
  26. }
  27. MP_RESULT     MediaAudioRenderer::ReleaseConnections()
  28. {
  29. return MP_RESULT_ERROR;
  30. }
  31. DWORD         MediaAudioRenderer::GetCaps()
  32. {
  33. return 0;
  34. }
  35. MP_RESULT     MediaAudioRenderer::Configure(HINSTANCE hInstance, HWND hwnd)
  36. {
  37. return MP_RESULT_ERROR;
  38. }
  39. MP_RESULT     MediaAudioRenderer::Open(HWND hwnd, WAVEFORMATEX *inFormat)
  40. {
  41. if(hwnd && inFormat) {
  42. this->ourFormat = inFormat;
  43. HRESULT hr;
  44. if(DirectSoundCreate(NULL, &this->lpDirectSound, NULL) == DS_OK) {
  45. hr = lpDirectSound->SetCooperativeLevel(hwnd, DSSCL_NORMAL);
  46. if(hr != DS_OK) {
  47. this->lpDirectSound->Release();
  48. this->lpDirectSound = NULL;
  49. return MP_RESULT_ERROR;
  50. }
  51. DSBUFFERDESC  dsbdesc;
  52. WAVEFORMATEX  wf;
  53. memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
  54. dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  55.     
  56. ZeroMemory(&wf, sizeof(WAVEFORMATEX));
  57. memcpy(&wf, this->ourFormat, sizeof(WAVEFORMATEX));
  58. dsbdesc.lpwfxFormat = (LPWAVEFORMATEX) &wf;
  59.     
  60. dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS;
  61. dsbdesc.dwBufferBytes = 2 * this->ourFormat->nAvgBytesPerSec;
  62. hr = lpDirectSound->CreateSoundBuffer(&dsbdesc, &lpBuffer, NULL);
  63. if(hr != DS_OK) {
  64. this->lpDirectSound->Release();
  65. this->lpDirectSound = NULL;
  66. return MP_RESULT_ERROR;
  67. }
  68. this->dwBufferSize = 2 * this->ourFormat->nAvgBytesPerSec;
  69. this->lInTimer = FALSE;
  70. return MP_RESULT_OK;
  71. }
  72. }
  73. return MP_RESULT_ERROR;
  74. }
  75. MP_RESULT     MediaAudioRenderer::SetCallback(void *lpData, MediaAudioCallback callback)
  76. {
  77. this->lpData   = lpData;
  78. this->callback = callback;
  79. return MP_RESULT_OK;
  80. }
  81. MP_RESULT     MediaAudioRenderer::SetVolume(unsigned int volume)
  82. {
  83. if(this->lpBuffer) {
  84. double vol;
  85. vol = - ( 70*pow(10, (100.0 - (double) volume)*2.0/100.0) );
  86. if(this->lpBuffer != NULL)
  87. this->lpBuffer->SetVolume((int) vol);
  88. }
  89. return MP_RESULT_ERROR;
  90. }
  91. unsigned long MediaAudioRenderer::GetAudioTime()
  92. {
  93. return (unsigned long) (( ((double) this->dwPlayed * (1000/(this->ourFormat->wBitsPerSample*this->ourFormat->nChannels/8)))) / (this->ourFormat->nSamplesPerSec));
  94. }
  95. void CALLBACK AudioTimeFunc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
  96. {
  97. MediaAudioRenderer *audioRenderer = (MediaAudioRenderer *) dwUser;
  98. if (InterlockedExchange(&audioRenderer->lInTimer, TRUE)) return;
  99. if(audioRenderer->callback) {
  100. void *buffer1, *buffer2;
  101. DWORD bytes1 = 0, bytes2 = 0;
  102. DWORD dwPlay, dwWrite, dwSize;
  103. audioRenderer->lpBuffer->GetCurrentPosition(&dwPlay, &dwWrite);
  104. if(audioRenderer->dwLastPlayPos == dwPlay) {
  105. InterlockedExchange(&audioRenderer->lInTimer, FALSE);
  106. return;
  107. }
  108. if(audioRenderer->dwLastPlayPos <= dwPlay) {
  109. dwSize = dwPlay - audioRenderer->dwLastPlayPos;
  110. audioRenderer->lpBuffer->Lock(audioRenderer->dwLastPlayPos,
  111.   dwSize,
  112.   &buffer1, &bytes1, 
  113.   &buffer2, &bytes2, 0);
  114. if(buffer1) {
  115. bytes1 = audioRenderer->callback(audioRenderer->lpData, buffer1, bytes1);
  116. }
  117. audioRenderer->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);
  118. audioRenderer->dwLastPlayPos += bytes1;
  119. audioRenderer->dwPlayed += bytes1;
  120. }
  121. else {
  122. DWORD bytes1_ori;
  123. dwSize = (audioRenderer->dwBufferSize - audioRenderer->dwLastPlayPos) + dwPlay;
  124. audioRenderer->lpBuffer->Lock(audioRenderer->dwLastPlayPos,
  125.   dwSize,
  126.   &buffer1, &bytes1, 
  127.   &buffer2, &bytes2, 0);
  128. bytes1_ori = bytes1;
  129. if(bytes1) {
  130. bytes1 = audioRenderer->callback(audioRenderer->lpData, buffer1, bytes1);
  131. }
  132. if(bytes2) {
  133. bytes2 = audioRenderer->callback(audioRenderer->lpData, buffer2, bytes2);
  134. }
  135. audioRenderer->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);
  136. audioRenderer->dwPlayed += bytes1 + bytes2;
  137. if(bytes1_ori == bytes1)
  138. audioRenderer->dwLastPlayPos = bytes2;
  139. else 
  140. audioRenderer->dwLastPlayPos += bytes1;
  141. }
  142. InterlockedExchange(&audioRenderer->lInTimer, FALSE);
  143. return;
  144. }
  145. }
  146. MP_RESULT     MediaAudioRenderer::Bufferize()
  147. {
  148. if(this->lpBuffer) {
  149. void *buffer1, *buffer2;
  150. DWORD bytes1, bytes2, length;
  151. this->lpBuffer->SetCurrentPosition(0);
  152. this->lpBuffer->Lock(0, this->dwBufferSize,
  153.     &buffer1, &bytes1, &buffer2, &bytes2, 0);
  154. length = this->callback(this->lpData, buffer1, this->dwBufferSize);
  155. this->lpBuffer->Unlock(buffer1, bytes1, buffer2, bytes2);
  156. this->dwNextWriteOffset = this->dwProgress = this->dwPlayed = this->dwLastPlayPos = 0;
  157. }
  158. return MP_RESULT_OK;
  159. }
  160. MP_RESULT     MediaAudioRenderer::Start()
  161. {
  162. if(this->lpBuffer) {
  163. void *buffer1, *buffer2;
  164. DWORD bytes1, bytes2, length;
  165. this->lpBuffer->SetCurrentPosition(0);
  166. this->lpBuffer->Lock(0, this->dwBufferSize,
  167.     &buffer1, &bytes1, &buffer2, &bytes2, 0);
  168. length = this->callback(this->lpData, buffer1, this->dwBufferSize);
  169. this->lpBuffer->Unlock(buffer1, length, buffer2, bytes2);
  170. this->dwProgress = this->dwPlayed = this->dwLastPlayPos = 0;
  171. this->paused = 0;
  172. if(this->lpBuffer->Play(0, 0, DSBPLAY_LOOPING) != DS_OK) {
  173. return MP_RESULT_ERROR;
  174. }
  175. if( timeBeginPeriod( PERIOD ) != 0 ) {
  176. return MP_RESULT_ERROR;
  177. }
  178.         else {
  179. this->uTimerID = timeSetEvent( PERIOD, 5, AudioTimeFunc, (DWORD)(LPVOID)this, TIME_PERIODIC );
  180. }
  181. return MP_RESULT_OK;
  182. }
  183. return MP_RESULT_ERROR;
  184. }
  185. MP_RESULT     MediaAudioRenderer::Pause()
  186. {
  187. if(this->paused) {
  188. this->paused = 0;
  189. this->lpBuffer->Play(0, 0, DSBPLAY_LOOPING);
  190. this->uTimerID = timeSetEvent( PERIOD, 5, AudioTimeFunc, (DWORD)(LPVOID)this, TIME_PERIODIC );
  191. }
  192. else {
  193. if(this->uTimerID) {
  194. timeKillEvent(this->uTimerID); 
  195.   }
  196. this->paused = 1;
  197. this->lpBuffer->Stop();
  198. }
  199. return MP_RESULT_OK;
  200. }
  201. MP_RESULT     MediaAudioRenderer::Stop()
  202. {
  203. if(this->uTimerID) {
  204. timeKillEvent(this->uTimerID); 
  205.   }
  206. if(this->lpBuffer) {
  207. this->lpBuffer->Stop();
  208. timeEndPeriod(PERIOD); 
  209. }
  210. return MP_RESULT_OK;
  211. }
  212. MP_RESULT     MediaAudioRenderer::Close()
  213. {
  214. this->Stop();
  215. if(this->lpDirectSound) {
  216. if(this->lpBuffer)
  217. this->lpBuffer->Release();
  218. this->lpBuffer = NULL;
  219. this->lpDirectSound->Release();
  220. this->lpDirectSound = NULL;
  221. }
  222. return MP_RESULT_OK;
  223. }