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

多媒体

开发平台:

Visual C++

  1. // Sound.cpp: implementation of the CSoundIn class.
  2. //
  3. /////////////////////////////////////////////////////////////////////////////////////////
  4. /*
  5.    
  6.     This program is Copyright  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 "Sound.h"
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char THIS_FILE[]=__FILE__;
  25. #define new DEBUG_NEW
  26. #endif
  27. #define real double
  28. UINT WaveThreadProc(void * pParam);
  29. //////////////////////////////////////////////////////////////////////
  30. // Construction/Destruction
  31. //////////////////////////////////////////////////////////////////////
  32. CSound::CSound()
  33. {
  34.   m_NbMaxSamples = 1024;
  35.   m_CalOffset = DEFAULT_CAL_OFFSET;
  36.   m_CalGain = DEFAULT_CAL_GAIN;
  37.   m_psSoundData = new short[m_NbMaxSamples];
  38.   bRec = false;
  39. }
  40. CSound::~CSound()
  41. {
  42. CloseMic();
  43. CloseOutput();
  44. }
  45. ///////////////////////////////////////////////////////////////////
  46. MMRESULT CSound::OpenMic(int nChannel, int nSamplesPerSec, int nBitPerPoint, int nMaxSamples)
  47. {
  48.     MMRESULT result;
  49. m_WaveInSampleRate = nSamplesPerSec;
  50. m_NbMaxSamples = nMaxSamples;
  51.     result=waveInGetNumDevs(); 
  52. if (result == 0)
  53. {
  54.         AfxMessageBox("No Sound Device");
  55. return result;
  56. }
  57.    // test for Mic available   
  58. result=waveInGetDevCaps (0, &m_WaveInDevCaps, sizeof(WAVEINCAPS));
  59. if ( result!= MMSYSERR_NOERROR)
  60. {
  61.    AfxMessageBox(_T("Cannot determine sound card capabilities !"));
  62. }
  63. // The Sound Devive is OK now we can create an Event  and start the Thread
  64. m_WaveEvent = CreateEvent(NULL,FALSE,FALSE,"WaveInThreadEvent");
  65. m_TerminateThread = FALSE;
  66. m_WaveInThread= AfxBeginThread(WaveThreadProc,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);   
  67. m_WaveInThread->m_bAutoDelete = TRUE;
  68. m_WaveInThread->ResumeThread();
  69. // init format 
  70. WaveInitFormat(nChannel/* mono*/,nSamplesPerSec /* khz */,nBitPerPoint /* bits */); 
  71. // Open Input 
  72. result = waveInOpen( &m_WaveIn,0, &m_WaveFormat,(DWORD)m_WaveEvent ,NULL ,CALLBACK_EVENT); 
  73. if ( result!= MMSYSERR_NOERROR)
  74. {
  75.         AfxMessageBox(_T("Cannot Open Sound Input Device!"));
  76.     return result;
  77. }
  78.     // prepare header
  79.     /*
  80.     typedef struct {     LPSTR  lpData;     
  81.  DWORD  dwBufferLength; 
  82. DWORD  dwBytesRecorded;  
  83. DWORD  dwUser; 
  84. DWORD  dwFlags; 
  85. DWORD  dwLoops;
  86. struct wavehdr_tag * lpNext;  
  87. DWORD  reserved; 
  88. } WAVEHDR; 
  89. */
  90. m_SizeRecord = m_NbMaxSamples;
  91.     m_WaveHeader.lpData = (CHAR *)&InputBuffer[0];
  92.     m_WaveHeader.dwBufferLength = m_SizeRecord*2;
  93. m_WaveHeader.dwFlags = 0;
  94.     result = waveInPrepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
  95. if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  96. {
  97. AfxMessageBox(_T("Cannot Prepare Header !"));
  98. return result;
  99. }
  100. result = waveInAddBuffer( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) );
  101. if  (result!= MMSYSERR_NOERROR) 
  102. {
  103. AfxMessageBox(_T("Cannot Add Buffer !"));
  104. return result;
  105. }
  106. result = waveInStart( m_WaveIn );
  107. if  (result!= MMSYSERR_NOERROR) 
  108. {
  109. AfxMessageBox(_T("Cannot Start Wave In !"));
  110. return result;
  111. }
  112.     ///////////////////////////////////////////////
  113.     ///////////////////////////////////////////////
  114.     ///////////////////////////////////////////////
  115.     result = waveOutOpen( &m_WaveOut,0, &m_WaveFormat,(DWORD)m_WaveEvent ,NULL ,CALLBACK_EVENT); 
  116. if ( result!= MMSYSERR_NOERROR)
  117. {
  118.         AfxMessageBox(_T("Sound output Cannot Open Device!"));
  119.     return result;
  120. }
  121.     result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  122. if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  123. {
  124. AfxMessageBox(_T(" Sound Output Cannot Prepare Header !"));
  125. return result;
  126. }
  127. result = waveOutWrite( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );
  128. if  (result!= MMSYSERR_NOERROR) 
  129. {
  130. AfxMessageBox(_T(" Sound Output Cannot Write Buffer !"));
  131. return result;
  132. }
  133. // all is correct now we can start the process
  134. result = waveOutRestart( m_WaveOut );
  135. if  (result!= MMSYSERR_NOERROR) 
  136. {
  137. AfxMessageBox(_T(" Sound Output Cannot Start Wave Out !"));
  138. return result;
  139. }
  140. return result;
  141. }
  142. void CSound::SetMaxSamples(int nMaxSamples)
  143. {
  144. m_NbMaxSamples = nMaxSamples;
  145. }
  146. void CSound::AddBuffer()
  147. {
  148.     MMRESULT result;
  149.     result = waveInUnprepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
  150.   m_SizeRecord = m_NbMaxSamples;
  151.     m_WaveHeader.lpData = (CHAR *)&InputBuffer[0];
  152.     m_WaveHeader.dwBufferLength = m_SizeRecord *2;
  153. m_WaveHeader.dwFlags = 0;
  154.     result = waveInPrepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
  155. result = waveInAddBuffer( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) );
  156.     result = waveInStart( m_WaveIn );
  157.   
  158. result = waveOutUnprepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  159. m_SizeRecord = m_NbMaxSamples;
  160.     m_WaveHeader.lpData = (CHAR *)&InputBuffer[0];
  161.     m_WaveHeader.dwBufferLength = m_SizeRecord *2;
  162. m_WaveHeader.dwFlags = 0;
  163.     result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  164. //    result = waveOutWrite( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );
  165.     result = waveOutRestart( m_WaveOut );
  166. }
  167. /*
  168. WAVE_FORMAT_1M08  11.025 kHz, mono, 8-bit 
  169. WAVE_FORMAT_1M16  11.025 kHz, mono, 16-bit 
  170. WAVE_FORMAT_1S08  11.025 kHz, stereo, 8-bit 
  171. WAVE_FORMAT_1S16  11.025 kHz, stereo, 16-bit 
  172. WAVE_FORMAT_2M08  22.05 kHz, mono, 8-bit 
  173. WAVE_FORMAT_2M16  22.05 kHz, mono, 16-bit 
  174. WAVE_FORMAT_2S08  22.05 kHz, stereo, 8-bit 
  175. WAVE_FORMAT_2S16  22.05 kHz, stereo, 16-bit 
  176. WAVE_FORMAT_4M08  44.1 kHz, mono, 8-bit 
  177. WAVE_FORMAT_4M16  44.1 kHz, mono, 16-bit 
  178. WAVE_FORMAT_4S08  44.1 kHz, stereo, 8-bit 
  179. WAVE_FORMAT_4S16  44.1 kHz, stereo, 16-bit 
  180. */ 
  181. void CSound:: WaveInitFormat(    WORD    nCh, // number of channels (mono, stereo)
  182. DWORD   nSampleRate, // sample rate
  183. WORD    BitsPerSample)
  184. {
  185. m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
  186. m_WaveFormat.nChannels = nCh;
  187. m_WaveFormat.nSamplesPerSec = nSampleRate;
  188. m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
  189. m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * BitsPerSample/8;
  190. m_WaveFormat.wBitsPerSample = BitsPerSample;
  191. m_WaveFormat.cbSize = 0;
  192. }   
  193. ///////////////////////////////////////////////////////////////////////////
  194. // the comutation for the input samples need to be calibrated according
  195. // to the sound board  add an Offset and a Mult coef.
  196. void CSound::ComputeSamples(SHORT *pt)
  197. {
  198. int i;
  199. for ( i = 0 ; i<m_NbMaxSamples; i++) // scaling the input samples du to the sound card
  200. {
  201. // InputBuffer[i] += m_CalOffset;
  202. // InputBuffer[i] *=m_CalGain;
  203. }
  204. }  
  205. void CSound::RecSoundData()
  206. {
  207. memcpy(m_psSoundData, InputBuffer, m_NbMaxSamples*sizeof(short));
  208. }
  209. void CSound::SetRec()
  210. {
  211. bRec = true;
  212. }
  213. void CSound::CloseMic()
  214. {
  215. m_TerminateThread = TRUE;
  216.     if (m_WaveEvent )
  217. SetEvent(m_WaveEvent);
  218.     Sleep(50);  // wait for the thread to terminate
  219. if (m_WaveIn) 
  220. waveInStop(m_WaveIn);
  221.     if (m_WaveIn) 
  222. waveInClose(m_WaveIn);
  223. }
  224. void CSound::RazBuffers()
  225. {
  226. for (int i=0;i<MAX_SAMPLES;i++)
  227. {
  228.     InputBuffer[i] = 0;
  229.     InputBuffer[i] = 0;
  230. }
  231. }
  232. void CSound::StopMic()
  233. {
  234. waveInStop(m_WaveIn);
  235. waveInReset(m_WaveIn);
  236. }
  237. void CSound::StartMic()
  238. {
  239. waveInStart(m_WaveIn);
  240. }
  241. void CSound::CloseOutput()
  242. {
  243. if (m_WaveOut) 
  244. waveOutPause(m_WaveOut);
  245.     Sleep(50);  // wait for the pause
  246. CloseHandle(m_WaveOut);
  247. m_TerminateThread = TRUE;
  248.     if (m_WaveEvent )
  249. SetEvent(m_WaveEvent);
  250.     Sleep(50);  // wait for the thread to terminate
  251. if (m_WaveOut) 
  252. {
  253. waveOutReset(m_WaveOut);
  254. waveOutClose(m_WaveOut);
  255. }
  256. }
  257. void CSound::StopOutput()
  258. {
  259. waveOutPause(m_WaveOut);
  260. }
  261. void CSound::StartOutput()
  262. {
  263. waveOutRestart(m_WaveOut);
  264. }
  265. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  266. //    Glogal Thread procedure for the CSoundIn class
  267. //    It cannot be included inside the Class
  268. //   
  269. // The LPARAM is the Class pointer (this) it can be the base class CSoundIn ptr or a derived new class
  270. // The value of this parametre can change according the Topmost class of the process 
  271. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  272. #define PT_S ((CSound*)pParam) 
  273. UINT WaveThreadProc(void * pParam)
  274. {
  275.    UINT result;
  276.    UINT FirstPass = TRUE;
  277. if ( FirstPass)
  278. result = WaitForSingleObject(((CSound*)pParam)->m_WaveEvent,INFINITE);
  279. FirstPass = FALSE;
  280.     
  281. while (!((CSound*)pParam)->m_TerminateThread)
  282. {
  283. result = WaitForSingleObject(((CSound*)pParam)->m_WaveEvent,INFINITE);
  284. if ((result == WAIT_OBJECT_0)&&(!((CSound*)pParam)->m_TerminateThread ))
  285. {
  286. PT_S->AddBuffer();      // Toggle as changed state here !Toggle point to the just received buffer
  287.     PT_S->ComputeSamples(PT_S->InputBuffer);
  288. }
  289. else
  290. return 0;  // 
  291. }
  292.     return 0;
  293. }