SOUNDOUT.CPP
上传用户:huifengb
上传日期:2007-12-27
资源大小:334k
文件大小:9k
源码类别:

多媒体

开发平台:

Visual C++

  1. // SoundOut.cpp: implementation of the CSoundOut class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. /*
  5.    
  6.     This program is Developped by Yannick Sustrac
  7.                    yannstrc@mail.dotcom.fr
  8.         http://www.mygale.org/~yannstrc/
  9.  
  10. This program is free software; you can redistribute it and/or modify it under the terms
  11. of the GNU General Public License as published by the Free Software Foundation; either
  12. version 2 of the License, or (at your option) any later version.
  13. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  14. without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. See the GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License along with this program;
  17. if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. //////////////////////////////////////////////////////////////////////////////////////////    
  20. #include "stdafx.h"
  21. #include "math.h"
  22. #include "SoundOut.h"
  23. #pragma comment(lib, "winmm")
  24. #ifdef _DEBUG
  25. #undef THIS_FILE
  26. static char THIS_FILE[]=__FILE__;
  27. #define new DEBUG_NEW
  28. #endif
  29. #define real double
  30. //void CALLBACK waveOutProc( HWAVEOut hwi,  UINT uMsg,   DWORD dwInstance,   DWORD dwParam1, DWORD dwParam2 );
  31. UINT WaveOutThreadProc(void * pParam);
  32. //////////////////////////////////////////////////////////////////////
  33. // Construction/Destruction
  34. //////////////////////////////////////////////////////////////////////
  35. CSoundOut::CSoundOut()
  36. {
  37. //  int i;
  38. //  double k;
  39.   m_NbMaxSamples = MAX_OUTPUT_SAMPLES;
  40.   m_WaveOutSampleRate = 11025;
  41.   /* init the sound Ouutput buffer with a signal noise */
  42. //  k =2.0*3.1416*(double)500.0/(double)m_WaveOutSampleRate;
  43. //  for (i = 0 ; i< m_NbMaxSamples; i++)
  44. //    OutputBuffer[i] = (SHORT)(10000.0*sin(k*(double)i++)) ;
  45.   memset(OutputBuffer, 0, sizeof(short)*m_NbMaxSamples);
  46. }
  47. CSoundOut::~CSoundOut()
  48. {
  49. CloseOutput();
  50. }
  51. ///////////////////////////////////////////////////////////////////
  52. MMRESULT CSoundOut::OpenOutput()
  53. {
  54.      MMRESULT result;
  55.     result=waveOutGetNumDevs(); 
  56. if (result == 0)
  57. {
  58.         AfxMessageBox("No Sound Output Device");
  59. return result;
  60. }
  61.    // test for Mic available   
  62.    result=waveOutGetDevCaps (0, &m_WaveOutDevCaps, sizeof(WAVEOUTCAPS));
  63.    
  64.    if ( result!= MMSYSERR_NOERROR)
  65.    {
  66.        AfxMessageBox(_T("Sound output Cannot determine card capabilities !"));
  67.    }
  68. // The SoundOut Devive is OK now we can create an Event  and start the Thread
  69. m_WaveOutEvent = CreateEvent(NULL,FALSE,FALSE,"WaveOutThreadEvent");
  70. m_TerminateThread = FALSE;
  71. m_WaveOutThread= AfxBeginThread(WaveOutThreadProc,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);   
  72. m_WaveOutThread->m_bAutoDelete = TRUE;
  73. m_WaveOutThread->ResumeThread();
  74. // init format 
  75. WaveInitFormat(1/* mono*/,m_WaveOutSampleRate /* khz */,16 /* bits */); 
  76. // Open Output 
  77. result = waveOutOpen( &m_WaveOut,0, &m_WaveFormat,(DWORD)m_WaveOutEvent ,NULL ,CALLBACK_EVENT); 
  78. if ( result!= MMSYSERR_NOERROR)
  79. {
  80.         AfxMessageBox(_T("Sound output Cannot Open Device!"));
  81.     return result;
  82. }
  83.   // prepare header
  84.    /*
  85.     typedef struct {     LPSTR  lpData;     
  86.  DWORD  dwBufferLength; 
  87. DWORD  dwBytesRecorded;  
  88. DWORD  dwUser; 
  89. DWORD  dwFlags; 
  90. DWORD  dwLoops;
  91. struct wavehdr_tag * lpNext;  
  92. DWORD  reserved; 
  93. } WAVEHDR; 
  94. */
  95. // m_Toggle = FALSE;
  96. m_SizeRecord = m_NbMaxSamples;
  97.     m_WaveHeader.lpData = (CHAR *)&OutputBuffer[0];
  98.     m_WaveHeader.dwBufferLength = m_SizeRecord*2;
  99. m_WaveHeader.dwFlags = 0;
  100.     result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  101.   //MMRESULT waveOutPrepareHeader( HWAVEOUT hwi, LPWAVEHDR pwh, UINT cbwh ); 
  102.    if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  103.    {
  104.         AfxMessageBox(_T(" Sound Output Cannot Prepare Header !"));
  105.     return result;
  106.    }
  107.    result = waveOutWrite( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );
  108.    if  (result!= MMSYSERR_NOERROR) 
  109.    {
  110.         AfxMessageBox(_T(" Sound Output Cannot Write Buffer !"));
  111.     return result;
  112.    }
  113.    // all is correct now we can start the process
  114.    result = waveOutRestart( m_WaveOut );
  115.    if  (result!= MMSYSERR_NOERROR) 
  116.    {
  117.         AfxMessageBox(_T(" Sound Output Cannot Start Wave Out !"));
  118.     return result;
  119.    }
  120.    return result;
  121. }
  122. void CSoundOut::AddBuffer()
  123. {
  124.     MMRESULT result;
  125.     result = waveOutUnprepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  126.    if  (result!= MMSYSERR_NOERROR) 
  127.    {
  128.         //AfxMessageBox(_T("Sound output Cannot UnPrepareHeader !"));
  129.         return;
  130.    };
  131.   m_SizeRecord = m_NbMaxSamples;
  132.     m_WaveHeader.lpData = (CHAR *)&OutputBuffer[0];
  133.     m_WaveHeader.dwBufferLength = m_SizeRecord *2;
  134. m_WaveHeader.dwFlags = 0;
  135.     result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  136.   //MMRESULT waveOutPrepareHeader( HWAVEOUT hwi, LPWAVEHDR pwh, UINT cbwh ); 
  137.    if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  138.         AfxMessageBox(_T("Sound output Cannot Prepare Header !"));
  139.    result = waveOutWrite( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );
  140.    if  (result!= MMSYSERR_NOERROR) 
  141.         AfxMessageBox(_T("Sound output Cannot Add Buffer !"));
  142.    result = waveOutRestart( m_WaveOut );
  143.    if  (result!= MMSYSERR_NOERROR) 
  144.         AfxMessageBox(_T(" Sound Output Cannot Start Wave Out !"));
  145. }
  146. void CSoundOut::SendBuffer(short *psOutPutBuffer)
  147. {
  148. for(int i=0; i<m_NbMaxSamples; i++)
  149. {
  150. OutputBuffer[i] = psOutPutBuffer[i];
  151. }
  152. // memcpy(OutputBuffer, psOutPutBuffer, sizeof(short)*m_NbMaxSamples);
  153. }
  154. /*
  155. WAVE_FORMAT_1M08  11.025 kHz, mono, 8-bit 
  156. WAVE_FORMAT_1M16  11.025 kHz, mono, 16-bit 
  157. WAVE_FORMAT_1S08  11.025 kHz, stereo, 8-bit 
  158. WAVE_FORMAT_1S16  11.025 kHz, stereo, 16-bit 
  159. WAVE_FORMAT_2M08  22.05 kHz, mono, 8-bit 
  160. WAVE_FORMAT_2M16  22.05 kHz, mono, 16-bit 
  161. WAVE_FORMAT_2S08  22.05 kHz, stereo, 8-bit 
  162. WAVE_FORMAT_2S16  22.05 kHz, stereo, 16-bit 
  163. WAVE_FORMAT_4M08  44.1 kHz, mono, 8-bit 
  164. WAVE_FORMAT_4M16  44.1 kHz, mono, 16-bit 
  165. WAVE_FORMAT_4S08  44.1 kHz, stereo, 8-bit 
  166. WAVE_FORMAT_4S16  44.1 kHz, stereo, 16-bit 
  167. */ 
  168. void CSoundOut:: WaveInitFormat(    WORD    nCh, // number of channels (mono, stereo)
  169. DWORD   nSampleRate, // sample rate
  170. WORD    BitsPerSample)
  171. {
  172. m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
  173. m_WaveFormat.nChannels = nCh;
  174. m_WaveFormat.nSamplesPerSec = nSampleRate;
  175. m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
  176. m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * BitsPerSample/8;
  177. m_WaveFormat.wBitsPerSample = BitsPerSample;
  178. m_WaveFormat.cbSize = 0;
  179. }   
  180. ///////////////////////////////////////////////////////////////////////////
  181. // the comutation for the Output samples need to be calibrated according
  182. // to the SoundOut board  add an Offset and a Mult coef.
  183. void CSoundOut::ComputeSamples(SHORT *pt)
  184. {
  185. }  
  186. void CSoundOut::CloseOutput()
  187. {
  188. if (m_WaveOut) 
  189. waveOutPause(m_WaveOut);
  190.     Sleep(50);  // wait for the pause
  191. // CloseHandle(m_WaveOut);
  192. m_TerminateThread = TRUE;
  193.     if (m_WaveOutEvent )
  194. SetEvent(m_WaveOutEvent);
  195.     Sleep(50);  // wait for the thread to terminate
  196.    if (m_WaveOut) 
  197.    {
  198. waveOutReset(m_WaveOut);
  199. waveOutClose(m_WaveOut);
  200.    }
  201. }
  202. void CSoundOut::RazBuffers()
  203. {
  204. for (int i=0;i<MAX_OUTPUT_SAMPLES;i++)
  205. {
  206.         OutputBuffer[i] = 0;
  207. }
  208. }
  209. void CSoundOut::StopOutput()
  210. {
  211. waveOutPause(m_WaveOut);
  212. }
  213. void CSoundOut::StartOutput()
  214. {
  215. waveOutRestart(m_WaveOut);
  216. }
  217. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  218. //    Glogal Thread procedure for the CSoundOut class
  219. //    It cannot be included inside the Class
  220. //   
  221. // The LPARAM is the Class pointer it can be the base class CSoundOut
  222. // or a drived class like CFft 
  223. // The value of this parametre can change according because 
  224. //  OpenMic() call a virtual funtion 
  225. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  226. #define PT_S ((CSoundOut*)pParam) 
  227. UINT WaveOutThreadProc(void * pParam)
  228. {
  229. //   CSoundOut * SoundOut = (class CSoundOut *)pParam;
  230.    UINT result;
  231.    UINT FirstPass = TRUE;
  232. if ( FirstPass)
  233. result = WaitForSingleObject(((CSoundOut*)pParam)->m_WaveOutEvent,INFINITE);
  234. FirstPass = FALSE;
  235.     
  236. while (!((CSoundOut*)pParam)->m_TerminateThread)
  237. {
  238. result = WaitForSingleObject(((CSoundOut*)pParam)->m_WaveOutEvent,INFINITE);
  239. if ((result == WAIT_OBJECT_0)&&(!((CSoundOut*)pParam)->m_TerminateThread ))
  240. {
  241. PT_S->AddBuffer();      // Toggle as changed state here !Toggle point to the just received buffer
  242.     PT_S->ComputeSamples(PT_S->OutputBuffer);
  243. }
  244. else
  245. return 0;  // 
  246. }
  247.     return 0;
  248. }