SoundIn.cpp
上传用户:wen82zi81
上传日期:2007-01-03
资源大小:40k
文件大小:8k
源码类别:

多媒体编程

开发平台:

Visual C++

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