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

多媒体

开发平台:

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 "SoundIn.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 WaveInThreadProc(void * pParam);
  29. //////////////////////////////////////////////////////////////////////
  30. // Construction/Destruction
  31. //////////////////////////////////////////////////////////////////////
  32. CSoundIn::CSoundIn()
  33. {
  34.   m_NbMaxSamples = 2048;
  35.   m_CalOffset = DEFAULT_CAL_OFFSET;
  36.   m_CalGain = DEFAULT_CAL_GAIN;
  37. //  m_WaveInSampleRate = 44100;
  38. }
  39. CSoundIn::~CSoundIn()
  40. {
  41. CloseMic();
  42. }
  43. ///////////////////////////////////////////////////////////////////
  44. MMRESULT CSoundIn::OpenMic(int nChannel, int nSamplesPerSec, int nBitPerPoint, CSoundOut *pSOut)
  45. {
  46. pSoundOut = pSOut;
  47.     MMRESULT result;
  48. m_WaveInSampleRate = nSamplesPerSec;
  49.     result=waveInGetNumDevs(); 
  50. if (result == 0)
  51. {
  52.         AfxMessageBox("No Sound Device");
  53. return result;
  54. }
  55.    // test for Mic available   
  56.    result=waveInGetDevCaps (0, &m_WaveInDevCaps, sizeof(WAVEINCAPS));
  57.    
  58.    if ( result!= MMSYSERR_NOERROR)
  59.    {
  60.        AfxMessageBox(_T("Cannot determine sound card capabilities !"));
  61.    }
  62. // The Sound Devive is OK now we can create an Event  and start the Thread
  63. m_WaveInEvent = CreateEvent(NULL,FALSE,FALSE,"WaveInThreadEvent");
  64. m_TerminateThread = FALSE;
  65. m_WaveInThread= AfxBeginThread(WaveInThreadProc,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);   
  66. m_WaveInThread->m_bAutoDelete = TRUE;
  67. m_WaveInThread->ResumeThread();
  68. // init format 
  69. WaveInitFormat(nChannel/* mono*/,nSamplesPerSec /* khz */,nBitPerPoint /* bits */); 
  70. // Open Input 
  71. result = waveInOpen( &m_WaveIn,0, &m_WaveFormat,(DWORD)m_WaveInEvent ,NULL ,CALLBACK_EVENT); 
  72. if ( result!= MMSYSERR_NOERROR)
  73. {
  74.         AfxMessageBox(_T("Cannot Open Sound Input Device!"));
  75.     return result;
  76. }
  77.   // prepare header
  78.    /*
  79.     typedef struct {     LPSTR  lpData;     
  80.  DWORD  dwBufferLength; 
  81. DWORD  dwBytesRecorded;  
  82. DWORD  dwUser; 
  83. DWORD  dwFlags; 
  84. DWORD  dwLoops;
  85. struct wavehdr_tag * lpNext;  
  86. DWORD  reserved; 
  87. } WAVEHDR; 
  88. */
  89. m_SizeRecord = m_NbMaxSamples;
  90.     m_WaveHeader.lpData = (CHAR *)&InputBuffer[0];
  91.     m_WaveHeader.dwBufferLength = m_SizeRecord*2;
  92. m_WaveHeader.dwFlags = 0;
  93.     result = waveInPrepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
  94.    if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  95.    {
  96.         AfxMessageBox(_T("Cannot Prepare Header !"));
  97.     return result;
  98.    }
  99.    result = waveInAddBuffer( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) );
  100.    if  (result!= MMSYSERR_NOERROR) 
  101.    {
  102.         AfxMessageBox(_T("Cannot Add Buffer !"));
  103.     return result;
  104.    }
  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. waveInStop(m_WaveIn);
  182.     if (m_WaveIn) 
  183. waveInClose(m_WaveIn);
  184. }
  185. void CSoundIn::RazBuffers()
  186. {
  187. for (int i=0;i<MAX_SAMPLES;i++)
  188. {
  189.         InputBuffer[i] = 0;
  190.         InputBuffer[i] = 0;
  191. }
  192. }
  193. void CSoundIn::StopMic()
  194. {
  195. waveInStop(m_WaveIn);
  196. waveInReset(m_WaveIn);
  197. }
  198. void CSoundIn::StartMic()
  199. {
  200. waveInStart(m_WaveIn);
  201. }
  202. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  203. //    Glogal Thread procedure for the CSoundIn class
  204. //    It cannot be included inside the Class
  205. //   
  206. // The LPARAM is the Class pointer (this) it can be the base class CSoundIn ptr or a derived new class
  207. // The value of this parametre can change according the Topmost class of the process 
  208. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  209. #define PT_S ((CSoundIn*)pParam) 
  210. UINT WaveInThreadProc(void * pParam)
  211. {
  212.    UINT result;
  213.    UINT FirstPass = TRUE;
  214. if ( FirstPass)
  215. result = WaitForSingleObject(((CSoundIn*)pParam)->m_WaveInEvent,INFINITE);
  216. FirstPass = FALSE;
  217.     
  218. while (!((CSoundIn*)pParam)->m_TerminateThread)
  219. {
  220. result = WaitForSingleObject(((CSoundIn*)pParam)->m_WaveInEvent,INFINITE);
  221. if ((result == WAIT_OBJECT_0)&&(!((CSoundIn*)pParam)->m_TerminateThread ))
  222. {
  223. PT_S->AddBuffer();      // Toggle as changed state here !Toggle point to the just received buffer
  224.     PT_S->ComputeSamples(PT_S->InputBuffer);
  225. memcpy(PT_S->pSoundOut->OutputBuffer, PT_S->InputBuffer, sizeof(short)*PT_S->m_NbMaxSamples);
  226. //
  227. // DWORD dwFlags = SND_MEMORY | SND_SYNC | SND_NODEFAULT; 
  228. // PlaySound ((char *) (PT_S->InputBuffer) , NULL, dwFlags);
  229. }
  230. else
  231. return 0;  // 
  232. }
  233.     return 0;
  234. }