SoundOut.cpp
上传用户:zjb_0001
上传日期:2007-01-11
资源大小:154k
文件大小:4k
源码类别:

Audio

开发平台:

Visual C++

  1. // SoundOut.cpp: implementation of the CSoundOut class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "SoundOut.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction/Destruction
  13. //////////////////////////////////////////////////////////////////////
  14. // IMPLEMENT_DYNCREATE(CSoundOut, CWinThread)
  15. CSoundOut::CSoundOut()
  16. {
  17. m_QueuedBuffers = 0;
  18. m_hPlay = NULL;
  19. m_bPlaying = false;
  20. GetDataToSoundOut = NULL;
  21. m_pOwner = NULL;
  22. CreateThread();
  23. m_bAutoDelete = false;
  24. }
  25. CSoundOut::~CSoundOut()
  26. {
  27. if(m_bPlaying)
  28. Stop();
  29. ::PostQuitMessage(0);
  30. }
  31. BOOL CSoundOut::InitInstance()
  32. {
  33. m_ThreadID = ::GetCurrentThreadId();
  34. return TRUE;
  35. }
  36. BEGIN_MESSAGE_MAP(CSoundOut, CWinThread)
  37. //{{AFX_MSG_MAP(CSoundOut)
  38. // NOTE - the ClassWizard will add and remove mapping macros here.
  39. //}}AFX_MSG_MAP
  40. ON_THREAD_MESSAGE(MM_WOM_DONE, OnMM_WOM_DONE)
  41. END_MESSAGE_MAP()
  42. bool CSoundOut::Start(WAVEFORMATEX* format)
  43. {
  44. MMRESULT mmReturn = 0;
  45. if(m_bPlaying || GetDataToSoundOut == NULL || m_pOwner == NULL)
  46. {
  47. // already recording!
  48. return FALSE;
  49. }
  50. else
  51. {
  52. if(format != NULL) // was this function called with at specific format
  53. m_Format = *format;
  54. // open wavein device
  55. mmReturn = ::waveOutOpen( &m_hPlay, WAVE_MAPPER, &m_Format, m_ThreadID, NULL, CALLBACK_THREAD);
  56. if(mmReturn)
  57. {
  58. waveOutErrorMsg(mmReturn, "in start()");
  59. return FALSE;
  60. }
  61. else
  62. {
  63. m_bPlaying = true;
  64. // we need at least 2 -> one for playing, one for refilling (3 is better)
  65. for(int i=0; i<3; i++)
  66. {
  67. CBuffer buf(m_Format.nBlockAlign*m_BufferSize, false);
  68. GetDataToSoundOut(&buf, m_pOwner);
  69. AddOutputBufferToQueue(&buf);
  70. }
  71. }
  72. }
  73. return TRUE;
  74. }
  75. void CSoundOut::Stop()
  76. {
  77. MMRESULT mmReturn = 0;
  78. if(m_bPlaying)
  79. {
  80. m_bPlaying = FALSE;
  81. mmReturn = ::waveOutReset(m_hPlay);
  82. if(mmReturn) waveOutErrorMsg(mmReturn, "in stop()");
  83. TRACE("waveOutReset()n");
  84. }
  85. }
  86. void CSoundOut::OnMM_WOM_DONE(UINT parm1, LONG parm2)
  87. {
  88. MMRESULT mmReturn = 0;
  89. LPWAVEHDR pHdr = (LPWAVEHDR) parm2;
  90. mmReturn = ::waveOutUnprepareHeader(m_hPlay, pHdr, sizeof(WAVEHDR));
  91. if(mmReturn)
  92. {
  93. waveOutErrorMsg(mmReturn, "in OnWOM_DONE()");
  94. return;
  95. }
  96. m_QueuedBuffers--;
  97. if(m_bPlaying)
  98. {
  99. CBuffer buf(pHdr->lpData, pHdr->dwBufferLength);
  100. // virtual function supplyed by user
  101. GetDataToSoundOut(&buf, m_pOwner);
  102. if(buf.ByteLen > 0)
  103. {
  104. AddOutputBufferToQueue(&buf);
  105. TRACE("WOM_DONE : refill buffern");
  106. // delete old header
  107. delete pHdr;
  108. return;
  109. }
  110. else
  111. {
  112. Stop();
  113. }
  114. }
  115. // we are closing the waveOut handle, 
  116. // all data must be deleted
  117. // this buffer was allocated in Start()
  118. delete pHdr->lpData;
  119. delete pHdr;
  120. TRACE("WOM_DONE : remove buffern");
  121. if(m_QueuedBuffers == 0 && m_bPlaying == false)
  122. {
  123. mmReturn = ::waveOutClose(m_hPlay);
  124. if(mmReturn) waveOutErrorMsg(mmReturn, "in stop()");
  125. TRACE("waveOutClose()n");
  126. }
  127. }
  128. int CSoundOut::AddOutputBufferToQueue(CBuffer *buffer)
  129. {
  130. MMRESULT mmReturn = 0;
  131. // create the header
  132. LPWAVEHDR pHdr = new WAVEHDR;
  133. if(pHdr == NULL) return NULL;
  134. // new a buffer
  135. pHdr->lpData = buffer->ptr.c;
  136. pHdr->dwBufferLength = buffer->ByteLen;
  137. pHdr->dwFlags = 0;
  138. // prepare it
  139. mmReturn = ::waveOutPrepareHeader(m_hPlay,pHdr, sizeof(WAVEHDR));
  140. if(mmReturn)
  141. {
  142. waveOutErrorMsg(mmReturn, "in AddOutputBufferToQueue()");
  143. return m_QueuedBuffers;
  144. }
  145. // write the buffer to output queue
  146. mmReturn = ::waveOutWrite(m_hPlay, pHdr, sizeof(WAVEHDR));
  147. if(mmReturn) waveOutErrorMsg(mmReturn, "in AddOutputBufferToQueue()");
  148. // increment the number of waiting buffers
  149. return m_QueuedBuffers++;
  150. }
  151. void CSoundOut::waveOutErrorMsg(MMRESULT result, LPCTSTR addstr)
  152. {
  153. // say error message
  154. char errorbuffer[100];
  155. waveOutGetErrorText(result, errorbuffer,100);
  156. ErrorMsg("WAVEOUT:%x:%s %s", result, errorbuffer, addstr);
  157. }