home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / SOUND.ZIP / SoundIn.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-11-22  |  8.0 KB  |  280 lines

  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.  
  11. This program is free software; you can redistribute it and/or modify it under the terms
  12. of the GNU General Public License as published by the Free Software Foundation; either
  13. version 2 of the License, or (at your option) any later version.
  14.  
  15. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  16. without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. See the GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License along with this program;
  20. if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23. //////////////////////////////////////////////////////////////////////////////////////////    
  24.  
  25.  
  26.  
  27. #include "stdafx.h"
  28. #include "SoundIn.h"
  29.  
  30. #pragma comment(lib, "winmm")
  31.  
  32.  
  33. #ifdef _DEBUG
  34. #undef THIS_FILE
  35. static char THIS_FILE[]=__FILE__;
  36. #define new DEBUG_NEW
  37. #endif
  38.  
  39. #define real double
  40.  
  41. UINT WaveInThreadProc(void * pParam);
  42.  
  43. //////////////////////////////////////////////////////////////////////
  44. // Construction/Destruction
  45. //////////////////////////////////////////////////////////////////////
  46.  
  47. CSoundIn::CSoundIn()
  48. {
  49.   m_NbMaxSamples = 2048;
  50.   m_CalOffset = DEFAULT_CAL_OFFSET;
  51.   m_CalGain = DEFAULT_CAL_GAIN;
  52.   m_WaveInSampleRate = 11025;
  53. }
  54.  
  55. CSoundIn::~CSoundIn()
  56. {
  57.     CloseMic();
  58. }
  59. ///////////////////////////////////////////////////////////////////
  60. MMRESULT CSoundIn::OpenMic()
  61. {
  62.      MMRESULT result;
  63.  
  64.     result=waveInGetNumDevs(); 
  65.     if (result == 0)
  66.     {
  67.         AfxMessageBox("No Sound Device");
  68.         return result;
  69.     }
  70.  
  71.    // test for Mic available   
  72.    result=waveInGetDevCaps (0, &m_WaveInDevCaps, sizeof(WAVEINCAPS));
  73.    
  74.    if ( result!= MMSYSERR_NOERROR)
  75.    {
  76.        AfxMessageBox(_T("Cannot determine sound card capabilities !"));
  77.    }
  78.  
  79.     // The Sound Devive is OK now we can create an Event  and start the Thread
  80.     m_WaveInEvent = CreateEvent(NULL,FALSE,FALSE,"WaveInThreadEvent");
  81.     m_TerminateThread = FALSE;
  82.     m_WaveInThread= AfxBeginThread(WaveInThreadProc,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);   
  83.     m_WaveInThread->m_bAutoDelete = TRUE;
  84.     m_WaveInThread->ResumeThread();
  85.  
  86.     // init format 
  87.     WaveInitFormat(1/* mono*/,m_WaveInSampleRate /* khz */,16 /* bits */); 
  88.  
  89.     
  90.     // Open Input 
  91.     result = waveInOpen( &m_WaveIn,0, &m_WaveFormat,(DWORD)m_WaveInEvent ,NULL ,CALLBACK_EVENT); 
  92.     if ( result!= MMSYSERR_NOERROR)
  93.     {
  94.         AfxMessageBox(_T("Cannot Open Sound Input Device!"));
  95.         return result;
  96.     }
  97.   // prepare header
  98.    /*
  99.     typedef struct {     LPSTR  lpData;     
  100.                      DWORD  dwBufferLength; 
  101.                     DWORD  dwBytesRecorded;  
  102.                     DWORD  dwUser; 
  103.                     DWORD  dwFlags; 
  104.                     DWORD  dwLoops;
  105.                     struct wavehdr_tag * lpNext;  
  106.                     DWORD  reserved; 
  107.     } WAVEHDR; 
  108.     */
  109.     m_SizeRecord = m_NbMaxSamples;
  110.     m_WaveHeader.lpData = (CHAR *)&InputBuffer[0];
  111.     m_WaveHeader.dwBufferLength = m_SizeRecord*2;
  112.     m_WaveHeader.dwFlags = 0;
  113.  
  114.     result = waveInPrepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
  115.    if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  116.    {
  117.         AfxMessageBox(_T("Cannot Prepare Header !"));
  118.         return result;
  119.    }
  120.  
  121.    result = waveInAddBuffer( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) );
  122.    if  (result!= MMSYSERR_NOERROR) 
  123.    {
  124.         AfxMessageBox(_T("Cannot Add Buffer !"));
  125.         return result;
  126.    }
  127.  
  128.    // all is correct now we can start the process
  129.    result = waveInStart( m_WaveIn );
  130.    if  (result!= MMSYSERR_NOERROR) 
  131.    {
  132.         AfxMessageBox(_T("Cannot Start Wave In !"));
  133.         return result;
  134.    }
  135.    return result;
  136. }
  137.  
  138.  
  139.  
  140. void CSoundIn::AddBuffer()
  141. {
  142.     
  143.     MMRESULT result;
  144.  
  145.     result = waveInUnprepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
  146.    if  (result!= MMSYSERR_NOERROR) 
  147.    {
  148.         AfxMessageBox(_T("Cannot UnPrepareHeader !"));
  149.         return;
  150.    };
  151.      m_SizeRecord = m_NbMaxSamples;
  152.     m_WaveHeader.lpData = (CHAR *)&InputBuffer[0];
  153.     m_WaveHeader.dwBufferLength = m_SizeRecord *2;
  154.     m_WaveHeader.dwFlags = 0;
  155.     result = waveInPrepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
  156.    if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  157.         AfxMessageBox(_T("Cannot Prepare Header !"));
  158.  
  159.    result = waveInAddBuffer( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) );
  160.    if  (result!= MMSYSERR_NOERROR) 
  161.         AfxMessageBox(_T("Cannot Add Buffer !"));
  162.  
  163.    result = waveInStart( m_WaveIn );
  164.    if  (result!= MMSYSERR_NOERROR) 
  165.         AfxMessageBox(_T("Cannot Start Wave In !"));
  166. }
  167.  
  168. /*
  169. WAVE_FORMAT_1M08  11.025 kHz, mono, 8-bit 
  170. WAVE_FORMAT_1M16  11.025 kHz, mono, 16-bit 
  171. WAVE_FORMAT_1S08  11.025 kHz, stereo, 8-bit 
  172. WAVE_FORMAT_1S16  11.025 kHz, stereo, 16-bit 
  173. WAVE_FORMAT_2M08  22.05 kHz, mono, 8-bit 
  174. WAVE_FORMAT_2M16  22.05 kHz, mono, 16-bit 
  175. WAVE_FORMAT_2S08  22.05 kHz, stereo, 8-bit 
  176. WAVE_FORMAT_2S16  22.05 kHz, stereo, 16-bit 
  177. WAVE_FORMAT_4M08  44.1 kHz, mono, 8-bit 
  178. WAVE_FORMAT_4M16  44.1 kHz, mono, 16-bit 
  179. WAVE_FORMAT_4S08  44.1 kHz, stereo, 8-bit 
  180. WAVE_FORMAT_4S16  44.1 kHz, stereo, 16-bit 
  181. */ 
  182.  
  183. void CSoundIn:: WaveInitFormat(    WORD    nCh, // number of channels (mono, stereo)
  184.                                 DWORD   nSampleRate, // sample rate
  185.                                 WORD    BitsPerSample)
  186. {
  187.         m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
  188.         m_WaveFormat.nChannels = nCh;
  189.         m_WaveFormat.nSamplesPerSec = nSampleRate;
  190.         m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
  191.         m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * BitsPerSample/8;
  192.         m_WaveFormat.wBitsPerSample = BitsPerSample;
  193.         m_WaveFormat.cbSize = 0;
  194. }   
  195.  
  196.  
  197. ///////////////////////////////////////////////////////////////////////////
  198. // the comutation for the input samples need to be calibrated according
  199. // to the sound board  add an Offset and a Mult coef.
  200.  
  201. void CSoundIn::ComputeSamples(SHORT *pt)
  202. {
  203.         int i;
  204.         for ( i = 0 ; i<m_NbMaxSamples; i++) // scaling the input samples du to the sound card
  205.         {
  206. //            InputBuffer[i] += m_CalOffset;
  207. //            InputBuffer[i] *=m_CalGain;
  208.         }
  209. }  
  210.  
  211.  
  212. void CSoundIn::CloseMic()
  213. {
  214.     m_TerminateThread = TRUE;
  215.     if (m_WaveInEvent )
  216.         SetEvent(m_WaveInEvent);
  217.     Sleep(50);  // wait for the thread to terminate
  218.  
  219.     if (m_WaveIn) 
  220.     {
  221.         waveInReset(m_WaveIn);
  222.         waveInStop(m_WaveIn);
  223.         waveInClose(m_WaveIn);
  224.     }
  225. }
  226.  
  227. void CSoundIn::RazBuffers()
  228. {
  229.         for (int i=0;i<MAX_SAMPLES;i++)
  230.         {
  231.             InputBuffer[i] = 0;
  232.             InputBuffer[i] = 0;
  233.         }
  234. }
  235.  
  236. void CSoundIn::StopMic()
  237. {
  238.     waveInStop(m_WaveIn);
  239.     waveInReset(m_WaveIn);
  240. }
  241.  
  242. void CSoundIn::StartMic()
  243. {
  244.     waveInStart(m_WaveIn);
  245. }
  246.  
  247.  
  248. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  249. //    Glogal Thread procedure for the CSoundIn class
  250. //    It cannot be included inside the Class
  251. //   
  252. // The LPARAM is the Class pointer (this) it can be the base class CSoundIn ptr or a derived new class
  253. // The value of this parametre can change according the Topmost class of the process 
  254. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255. #define PT_S ((CSoundIn*)pParam) 
  256.  
  257. UINT WaveInThreadProc(void * pParam)
  258. {
  259.    UINT result;
  260.    UINT FirstPass = TRUE;
  261.  
  262.     if ( FirstPass)
  263.         result = WaitForSingleObject(((CSoundIn*)pParam)->m_WaveInEvent,INFINITE);
  264.     FirstPass = FALSE;
  265.     
  266.     while (!((CSoundIn*)pParam)->m_TerminateThread)
  267.     {
  268.         result = WaitForSingleObject(((CSoundIn*)pParam)->m_WaveInEvent,INFINITE);
  269.         if ((result == WAIT_OBJECT_0)&&(!((CSoundIn*)pParam)->m_TerminateThread ))
  270.         {
  271.             PT_S->AddBuffer();      // Toggle as changed state here !Toggle point to the just received buffer
  272.             PT_S->ComputeSamples(PT_S->InputBuffer);
  273.         }
  274.         else
  275.             return 0;  // 
  276.     }
  277.     return 0;
  278. }
  279.  
  280.