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

  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.  
  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. #include "stdafx.h"
  26. #include "math.h"
  27. #include "snd.h"
  28. #include "SoundOut.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. //void CALLBACK waveOutProc( HWAVEOut hwi,  UINT uMsg,   DWORD dwInstance,   DWORD dwParam1, DWORD dwParam2 );
  41.  
  42. UINT WaveOutThreadProc(void * pParam);
  43.  
  44. //////////////////////////////////////////////////////////////////////
  45. // Construction/Destruction
  46. //////////////////////////////////////////////////////////////////////
  47.  
  48. CSoundOut::CSoundOut()
  49. {
  50.   int i;
  51.   double k;
  52.   m_NbMaxSamples = MAX_OUTPUT_SAMPLES;
  53.   m_WaveOutSampleRate = 11025;
  54.  
  55.   /* init the sound Ouutput buffer with a signal noise */
  56.   k =2.0*3.1416*(double)500.0/(double)m_WaveOutSampleRate;
  57.   for (i = 0 ; i< m_NbMaxSamples; i++)
  58.        OutputBuffer[i] = (SHORT)(10000.0*sin(k*(double)i++)) ;
  59. }
  60.  
  61. CSoundOut::~CSoundOut()
  62. {
  63.     CloseOutput();
  64. }
  65. ///////////////////////////////////////////////////////////////////
  66. MMRESULT CSoundOut::OpenOutput()
  67. {
  68.      MMRESULT result;
  69.  
  70.     result=waveOutGetNumDevs(); 
  71.     if (result == 0)
  72.     {
  73.         AfxMessageBox("No Sound Output Device");
  74.         return result;
  75.     }
  76.  
  77.    // test for Mic available   
  78.    result=waveOutGetDevCaps (0, &m_WaveOutDevCaps, sizeof(WAVEOUTCAPS));
  79.    
  80.    if ( result!= MMSYSERR_NOERROR)
  81.    {
  82.        AfxMessageBox(_T("Sound output Cannot determine card capabilities !"));
  83.    }
  84.  
  85.     // The SoundOut Devive is OK now we can create an Event  and start the Thread
  86.     m_WaveOutEvent = CreateEvent(NULL,FALSE,FALSE,"WaveOutThreadEvent");
  87.     m_TerminateThread = FALSE;
  88.     m_WaveOutThread= AfxBeginThread(WaveOutThreadProc,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);   
  89.     m_WaveOutThread->m_bAutoDelete = TRUE;
  90.     m_WaveOutThread->ResumeThread();
  91.  
  92.     // init format 
  93.     WaveInitFormat(1/* mono*/,m_WaveOutSampleRate /* khz */,16 /* bits */); 
  94.  
  95.     
  96.     // Open Output 
  97.     result = waveOutOpen( &m_WaveOut,0, &m_WaveFormat,(DWORD)m_WaveOutEvent ,NULL ,CALLBACK_EVENT); 
  98.     if ( result!= MMSYSERR_NOERROR)
  99.     {
  100.         AfxMessageBox(_T("Sound output Cannot Open Device!"));
  101.         return result;
  102.     }
  103.   // prepare header
  104.    /*
  105.     typedef struct {     LPSTR  lpData;     
  106.                      DWORD  dwBufferLength; 
  107.                     DWORD  dwBytesRecorded;  
  108.                     DWORD  dwUser; 
  109.                     DWORD  dwFlags; 
  110.                     DWORD  dwLoops;
  111.                     struct wavehdr_tag * lpNext;  
  112.                     DWORD  reserved; 
  113.     } WAVEHDR; 
  114.     */
  115. //    m_Toggle = FALSE;
  116.     m_SizeRecord = m_NbMaxSamples;
  117.     m_WaveHeader.lpData = (CHAR *)&OutputBuffer[0];
  118.     m_WaveHeader.dwBufferLength = m_SizeRecord*2;
  119.     m_WaveHeader.dwFlags = 0;
  120.  
  121.     result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  122.   //MMRESULT waveOutPrepareHeader( HWAVEOUT hwi, LPWAVEHDR pwh, UINT cbwh ); 
  123.    if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  124.    {
  125.         AfxMessageBox(_T(" Sound Output Cannot Prepare Header !"));
  126.         return result;
  127.    }
  128.  
  129.    result = waveOutWrite( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );
  130.    if  (result!= MMSYSERR_NOERROR) 
  131.    {
  132.         AfxMessageBox(_T(" Sound Output Cannot Write Buffer !"));
  133.         return result;
  134.    }
  135.  
  136.    // all is correct now we can start the process
  137.    result = waveOutRestart( m_WaveOut );
  138.    if  (result!= MMSYSERR_NOERROR) 
  139.    {
  140.         AfxMessageBox(_T(" Sound Output Cannot Start Wave Out !"));
  141.         return result;
  142.    }
  143.    return result;
  144. }
  145.  
  146.  
  147.  
  148. void CSoundOut::AddBuffer()
  149. {
  150.     
  151.     MMRESULT result;
  152.  
  153.     result = waveOutUnprepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  154.    if  (result!= MMSYSERR_NOERROR) 
  155.    {
  156.         //AfxMessageBox(_T("Sound output Cannot UnPrepareHeader !"));
  157.         return;
  158.    };
  159.      m_SizeRecord = m_NbMaxSamples;
  160.     m_WaveHeader.lpData = (CHAR *)&OutputBuffer[0];
  161.     m_WaveHeader.dwBufferLength = m_SizeRecord *2;
  162.     m_WaveHeader.dwFlags = 0;
  163.     result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
  164.   //MMRESULT waveOutPrepareHeader( HWAVEOUT hwi, LPWAVEHDR pwh, UINT cbwh ); 
  165.    if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) )
  166.         AfxMessageBox(_T("Sound output Cannot Prepare Header !"));
  167.  
  168.    result = waveOutWrite( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );
  169.    if  (result!= MMSYSERR_NOERROR) 
  170.         AfxMessageBox(_T("Sound output Cannot Add Buffer !"));
  171.  
  172.    result = waveOutRestart( m_WaveOut );
  173.    if  (result!= MMSYSERR_NOERROR) 
  174.         AfxMessageBox(_T(" Sound Output Cannot Start Wave Out !"));
  175. }
  176.  
  177. /*
  178. WAVE_FORMAT_1M08  11.025 kHz, mono, 8-bit 
  179. WAVE_FORMAT_1M16  11.025 kHz, mono, 16-bit 
  180. WAVE_FORMAT_1S08  11.025 kHz, stereo, 8-bit 
  181. WAVE_FORMAT_1S16  11.025 kHz, stereo, 16-bit 
  182. WAVE_FORMAT_2M08  22.05 kHz, mono, 8-bit 
  183. WAVE_FORMAT_2M16  22.05 kHz, mono, 16-bit 
  184. WAVE_FORMAT_2S08  22.05 kHz, stereo, 8-bit 
  185. WAVE_FORMAT_2S16  22.05 kHz, stereo, 16-bit 
  186. WAVE_FORMAT_4M08  44.1 kHz, mono, 8-bit 
  187. WAVE_FORMAT_4M16  44.1 kHz, mono, 16-bit 
  188. WAVE_FORMAT_4S08  44.1 kHz, stereo, 8-bit 
  189. WAVE_FORMAT_4S16  44.1 kHz, stereo, 16-bit 
  190. */ 
  191.  
  192. void CSoundOut:: WaveInitFormat(    WORD    nCh, // number of channels (mono, stereo)
  193.                                 DWORD   nSampleRate, // sample rate
  194.                                 WORD    BitsPerSample)
  195. {
  196.         m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM;
  197.         m_WaveFormat.nChannels = nCh;
  198.         m_WaveFormat.nSamplesPerSec = nSampleRate;
  199.         m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8;
  200.         m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * BitsPerSample/8;
  201.         m_WaveFormat.wBitsPerSample = BitsPerSample;
  202.         m_WaveFormat.cbSize = 0;
  203. }   
  204.  
  205.  
  206. ///////////////////////////////////////////////////////////////////////////
  207. // the comutation for the Output samples need to be calibrated according
  208. // to the SoundOut board  add an Offset and a Mult coef.
  209.  
  210. void CSoundOut::ComputeSamples(SHORT *pt)
  211. {
  212. }  
  213.  
  214.  
  215. void CSoundOut::CloseOutput()
  216. {
  217.     if (m_WaveOut) 
  218.         waveOutPause(m_WaveOut);
  219.     Sleep(50);  // wait for the pause
  220.     //    CloseHandle(m_WaveOut);
  221.     m_TerminateThread = TRUE;
  222.     if (m_WaveOutEvent )
  223.         SetEvent(m_WaveOutEvent);
  224.     Sleep(50);  // wait for the thread to terminate
  225.  
  226.    if (m_WaveOut) 
  227.    {
  228.         waveOutReset(m_WaveOut);
  229.         waveOutClose(m_WaveOut);
  230.    }
  231. }
  232.  
  233. void CSoundOut::RazBuffers()
  234. {
  235.         for (int i=0;i<MAX_OUTPUT_SAMPLES;i++)
  236.         {
  237.             OutputBuffer[i] = 0;
  238.         }
  239. }
  240.  
  241. void CSoundOut::StopOutput()
  242. {
  243.     waveOutPause(m_WaveOut);
  244. }
  245.  
  246. void CSoundOut::StartOutput()
  247. {
  248.     waveOutRestart(m_WaveOut);
  249. }
  250.  
  251.  
  252.  
  253. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  254. //    Glogal Thread procedure for the CSoundOut class
  255. //    It cannot be included inside the Class
  256. //   
  257. // The LPARAM is the Class pointer it can be the base class CSoundOut
  258. // or a drived class like CFft 
  259. // The value of this parametre can change according because 
  260. //  OpenMic() call a virtual funtion 
  261. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  262. #define PT_S ((CSoundOut*)pParam) 
  263.  
  264. UINT WaveOutThreadProc(void * pParam)
  265. {
  266. //   CSoundOut * SoundOut = (class CSoundOut *)pParam;
  267.    UINT result;
  268.    UINT FirstPass = TRUE;
  269.  
  270.  
  271.     if ( FirstPass)
  272.         result = WaitForSingleObject(((CSoundOut*)pParam)->m_WaveOutEvent,INFINITE);
  273.     FirstPass = FALSE;
  274.     
  275.     while (!((CSoundOut*)pParam)->m_TerminateThread)
  276.     {
  277.         result = WaitForSingleObject(((CSoundOut*)pParam)->m_WaveOutEvent,INFINITE);
  278.         if ((result == WAIT_OBJECT_0)&&(!((CSoundOut*)pParam)->m_TerminateThread ))
  279.         {
  280.             PT_S->AddBuffer();      // Toggle as changed state here !Toggle point to the just received buffer
  281.             PT_S->ComputeSamples(PT_S->OutputBuffer);
  282.         }
  283.         else
  284.             return 0;  // 
  285.     }
  286.     return 0;
  287. }
  288.  
  289.  
  290.  
  291.  
  292.