SoundOut.cpp
上传用户:onsales
上传日期:2010-01-31
资源大小:224k
文件大小:6k
源码类别:

网络编程

开发平台:

Visual C++

  1. // SoundOut.cpp: implementation of the CSoundOut class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "Speak.h"
  6. #include "SoundOut.h"
  7. #pragma comment(lib, "winmm")
  8. #ifdef _DEBUG
  9. #undef THIS_FILE
  10. static char THIS_FILE[]=__FILE__;
  11. #define new DEBUG_NEW
  12. #endif
  13. UINT WaveOutThreadProc(void * pParam); 
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. CSoundOut::CSoundOut()
  18. {
  19. m_nBits=8;
  20. m_nBlock=1024;
  21. m_WaveOutSampleRate=11025;
  22. m_nCurrent=1;
  23. m_TerminateThread=FALSE;
  24. m_pOutputBuffer=NULL;
  25. m_WaveHeader=NULL;
  26. }
  27. CSoundOut::~CSoundOut()
  28. {
  29. if(m_pOutputBuffer!=NULL)
  30. free(m_pOutputBuffer);
  31. if(m_WaveHeader!=NULL)
  32. free(m_WaveHeader);
  33. }
  34. MMRESULT CSoundOut::OpenSpk()
  35. {
  36. int n=(int)m_nBits/8;
  37. m_WaveHeader=(WAVEHDR*)malloc(sizeof(WAVEHDR));
  38. m_pOutputBuffer=(char*)malloc(n*m_nBlock*m_nBlockNum);
  39.     
  40. MMRESULT result;
  41.     result=waveOutGetNumDevs(); 
  42. if (result == 0)
  43. {
  44.         AfxMessageBox("No Sound Output Device");
  45. return result;
  46. }
  47. // test for Mic available   
  48.     result=waveOutGetDevCaps (0, &m_WaveOutDevCaps, sizeof(WAVEOUTCAPS));
  49.     if ( result!= MMSYSERR_NOERROR)
  50.     {
  51.        AfxMessageBox(_T("Sound output Cannot determine card capabilities !"));
  52.     }
  53. // The SoundOut Devive is OK now we can create an Event  and start the Thread
  54. m_WaveOutEvent = CreateEvent(NULL,FALSE,FALSE,"WaveOutThreadEvent");
  55. m_TerminateThread = FALSE;
  56. m_WaveOutThread= AfxBeginThread(WaveOutThreadProc,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);   
  57. m_WaveOutThread->m_bAutoDelete = TRUE;
  58. m_WaveOutThread->ResumeThread();
  59.   // init format 
  60. WaveInitFormat(1/* mono*/,m_WaveOutSampleRate /* khz */,m_nBits /* bits */); 
  61. // Open Output 
  62. result = waveOutOpen( &m_WaveOut,0, &m_WaveFormat,(DWORD)m_WaveOutEvent ,NULL ,CALLBACK_EVENT);  
  63. if ( result!= MMSYSERR_NOERROR)
  64. {
  65.         AfxMessageBox(_T("Sound output Cannot Open Device!"));
  66.     return result;
  67. }
  68. (*m_WaveHeader).lpData = (LPSTR)(m_pOutputBuffer);
  69. (*m_WaveHeader).dwBufferLength = m_nBlock*n*m_nBlockNum;
  70. (*m_WaveHeader).dwFlags = 0;
  71. result = waveOutPrepareHeader( m_WaveOut,m_WaveHeader, sizeof(WAVEHDR) ); 
  72. if ((result!= MMSYSERR_NOERROR)||((*m_WaveHeader).dwFlags != WHDR_PREPARED))
  73. {
  74. //AfxMessageBox(_T(" Sound Output Cannot Prepare Header !"));
  75. return result;
  76. }
  77. result = waveOutWrite( m_WaveOut, m_WaveHeader, sizeof(WAVEHDR));
  78. if  (result!= MMSYSERR_NOERROR) 
  79. {
  80. AfxMessageBox(_T(" Sound Output Cannot Write Buffer !"));
  81. return result;
  82. }
  83.     // all is correct now we can start the process
  84.     result = waveOutRestart( m_WaveOut );
  85.     if  (result!= MMSYSERR_NOERROR) 
  86.     {
  87.         AfxMessageBox(_T(" Sound Output Cannot Start Wave Out !"));
  88.     return result;
  89.     }
  90.     return result;
  91. }
  92. void CSoundOut::WaveInitFormat(WORD nCh,//channels of output
  93.    DWORD nSampleRate,//sample rate
  94.    WORD BitsPerSample)
  95. {
  96. m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
  97. m_WaveFormat.nChannels = nCh;
  98. m_WaveFormat.nSamplesPerSec = nSampleRate;
  99. m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
  100. m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * BitsPerSample/8;
  101. m_WaveFormat.wBitsPerSample = BitsPerSample;
  102. m_WaveFormat.cbSize = 0;
  103. }
  104. void CSoundOut::CloseSpk()
  105. {
  106. if (m_WaveOut) 
  107. waveOutPause(m_WaveOut);
  108.     Sleep(50); 
  109. m_TerminateThread = TRUE;
  110.     if (m_WaveOutEvent )
  111. SetEvent(m_WaveOutEvent);
  112.     Sleep(50);
  113.    if (m_WaveOut) 
  114.    {
  115. waveOutReset(m_WaveOut);
  116. waveOutClose(m_WaveOut);
  117.    }
  118. }
  119. void CSoundOut::StartSpk()
  120. {
  121. waveOutRestart(m_WaveOut);
  122. }
  123. void CSoundOut::AddBuffer()
  124. {
  125. MMRESULT result;
  126. if(m_nCurrent>2)
  127. m_nCurrent=1;
  128. result = waveOutUnprepareHeader( m_WaveOut,m_WaveHeader, sizeof(WAVEHDR) ); 
  129. if  (result!= MMSYSERR_NOERROR) 
  130.     {
  131.         return;
  132.     }
  133.   int n=(int)m_nBits/8;
  134. (*m_WaveHeader).lpData = (LPSTR)(m_pOutputBuffer);
  135. (*m_WaveHeader).dwBufferLength = m_nBlock*n*m_nBlockNum;
  136. (*m_WaveHeader).dwFlags = 0;
  137. result = waveOutPrepareHeader( m_WaveOut,m_WaveHeader, sizeof(WAVEHDR) ); 
  138. if ((result!= MMSYSERR_NOERROR)||((*m_WaveHeader).dwFlags != WHDR_PREPARED))
  139. {
  140. //AfxMessageBox(_T(" Sound Output Cannot Prepare Header !"));
  141. return ;
  142. }
  143. result = waveOutWrite( m_WaveOut, m_WaveHeader, sizeof(WAVEHDR));
  144. if  (result!= MMSYSERR_NOERROR) 
  145. {
  146. AfxMessageBox(_T(" Sound Output Cannot Write Buffer !"));
  147. return ;
  148. }
  149. }
  150. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  151. //    Glogal Thread procedure for the CSoundOut class
  152. //    It cannot be included inside the Class
  153. //   
  154. // The LPARAM is the Class pointer it can be the base class CSoundOut
  155. // or a drived class like CFft 
  156. // The value of this parametre can change according because 
  157. //  OpenSpk() call a virtual funtion 
  158. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. #define PT_S ((CSoundOut*)pParam) 
  160. UINT WaveOutThreadProc(void * pParam)
  161. {
  162.     UINT result;
  163.     UINT FirstPass = TRUE;
  164.     if ( FirstPass)
  165. result = WaitForSingleObject(PT_S->m_WaveOutEvent,INFINITE);
  166. FirstPass = FALSE;
  167.     
  168. while (!(PT_S->m_TerminateThread))
  169. {
  170. result = WaitForSingleObject(((CSoundOut*)pParam)->m_WaveOutEvent,INFINITE);
  171. if ((result == WAIT_OBJECT_0)&&(!(PT_S->m_TerminateThread )))
  172. {
  173. PT_S->AddBuffer();     
  174. }
  175. else
  176. return 0;  
  177. }
  178.     return 0;
  179. }
  180. void CSoundOut::WriteData(char *lpData,long length)
  181. {
  182. int n=(int)(m_nBits/8);
  183. m_nCurrent++;
  184. m_nCurrent%=m_nBlockNum;
  185. memcpy(m_pOutputBuffer+m_nCurrent*m_nBlock*n,lpData,length);
  186. if(length<m_nBlock*n)
  187. memset(m_pOutputBuffer+m_nCurrent*m_nBlock*n+length,127,m_nBlock*n-length-1);
  188. return;
  189. }