www.pudn.com > AudioWave.rar > SOUND.CPP


// Sound.cpp: implementation of the CSoundIn class. 
// 
///////////////////////////////////////////////////////////////////////////////////////// 
/* 
    
	    This program is Copyright  Developped by Yannick Sustrac 
                   yannstrc@mail.dotcom.fr 
		        http://www.mygale.org/~yannstrc 
  
 
This program is free software; you can redistribute it and/or modify it under the terms 
of the GNU General Public License as published by the Free Software Foundation; either 
version 2 of the License, or (at your option) any later version. 
 
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details. 
 
You should have received a copy of the GNU General Public License along with this program; 
if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 
*/ 
//////////////////////////////////////////////////////////////////////////////////////////     
 
 
 
#include "stdafx.h" 
#include "Sound.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
#define real double 
 
UINT WaveThreadProc(void * pParam); 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CSound::CSound() 
{ 
  m_NbMaxSamples = 1024; 
  m_CalOffset = DEFAULT_CAL_OFFSET; 
  m_CalGain = DEFAULT_CAL_GAIN; 
  m_psSoundData = new short[m_NbMaxSamples]; 
  bRec = false; 
} 
 
CSound::~CSound() 
{ 
	CloseMic(); 
	CloseOutput(); 
} 
/////////////////////////////////////////////////////////////////// 
MMRESULT CSound::OpenMic(int nChannel, int nSamplesPerSec, int nBitPerPoint, int nMaxSamples) 
{ 
    MMRESULT result; 
	m_WaveInSampleRate = nSamplesPerSec; 
	m_NbMaxSamples = nMaxSamples; 
    result=waveInGetNumDevs();  
	if (result == 0) 
	{ 
        AfxMessageBox("No Sound Device"); 
		return result; 
	} 
 
   // test for Mic available    
	result=waveInGetDevCaps (0, &m_WaveInDevCaps, sizeof(WAVEINCAPS)); 
 
	if ( result!= MMSYSERR_NOERROR) 
	{ 
	   AfxMessageBox(_T("Cannot determine sound card capabilities !")); 
	} 
 
	// The Sound Devive is OK now we can create an Event  and start the Thread 
	m_WaveEvent = CreateEvent(NULL,FALSE,FALSE,"WaveInThreadEvent"); 
	m_TerminateThread = FALSE; 
	m_WaveInThread= AfxBeginThread(WaveThreadProc,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);    
	m_WaveInThread->m_bAutoDelete = TRUE; 
	m_WaveInThread->ResumeThread(); 
 
	// init format  
	 
	WaveInitFormat(nChannel/* mono*/,nSamplesPerSec /* khz */,nBitPerPoint /* bits */);  
	 
	// Open Input  
	result = waveInOpen( &m_WaveIn,0, &m_WaveFormat,(DWORD)m_WaveEvent ,NULL ,CALLBACK_EVENT);  
	if ( result!= MMSYSERR_NOERROR) 
	{ 
        AfxMessageBox(_T("Cannot Open Sound Input Device!")); 
	    return result; 
	} 
    // prepare header 
    /* 
    typedef struct {     LPSTR  lpData;      
					 DWORD  dwBufferLength;  
					DWORD  dwBytesRecorded;   
					DWORD  dwUser;  
					DWORD  dwFlags;  
					DWORD  dwLoops; 
					struct wavehdr_tag * lpNext;   
					DWORD  reserved;  
	} WAVEHDR;  
	*/ 
	m_SizeRecord = m_NbMaxSamples; 
    m_WaveHeader.lpData = (CHAR *)&InputBuffer[0]; 
    m_WaveHeader.dwBufferLength = m_SizeRecord*2; 
	m_WaveHeader.dwFlags = 0; 
 
    result = waveInPrepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) );  
	if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) ) 
	{ 
		AfxMessageBox(_T("Cannot Prepare Header !")); 
		return result; 
	} 
 
 
	result = waveInAddBuffer( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
	if  (result!= MMSYSERR_NOERROR)  
	{ 
		AfxMessageBox(_T("Cannot Add Buffer !")); 
		return result; 
	} 
 
	result = waveInStart( m_WaveIn ); 
	if  (result!= MMSYSERR_NOERROR)  
	{ 
		AfxMessageBox(_T("Cannot Start Wave In !")); 
		return result; 
	} 
 
    /////////////////////////////////////////////// 
    /////////////////////////////////////////////// 
    /////////////////////////////////////////////// 
    result = waveOutOpen( &m_WaveOut,0, &m_WaveFormat,(DWORD)m_WaveEvent ,NULL ,CALLBACK_EVENT);  
	if ( result!= MMSYSERR_NOERROR) 
	{ 
        AfxMessageBox(_T("Sound output Cannot Open Device!")); 
	    return result; 
	} 
 
    result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );  
 
	if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader.dwFlags != WHDR_PREPARED) ) 
	{ 
		AfxMessageBox(_T(" Sound Output Cannot Prepare Header !")); 
		return result; 
	} 
 
	result = waveOutWrite( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
	if  (result!= MMSYSERR_NOERROR)  
	{ 
		AfxMessageBox(_T(" Sound Output Cannot Write Buffer !")); 
		return result; 
	} 
 
	// all is correct now we can start the process 
	result = waveOutRestart( m_WaveOut ); 
	if  (result!= MMSYSERR_NOERROR)  
	{ 
		AfxMessageBox(_T(" Sound Output Cannot Start Wave Out !")); 
		return result; 
	} 
	return result; 
} 
 
void CSound::SetMaxSamples(int nMaxSamples) 
{ 
	m_NbMaxSamples = nMaxSamples; 
} 
 
void CSound::AddBuffer() 
{ 
	 
    MMRESULT result; 
 
    result = waveInUnprepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) );  
 
 	m_SizeRecord = m_NbMaxSamples; 
    m_WaveHeader.lpData = (CHAR *)&InputBuffer[0]; 
    m_WaveHeader.dwBufferLength = m_SizeRecord *2; 
	m_WaveHeader.dwFlags = 0; 
	 
    result = waveInPrepareHeader( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) );  
	result = waveInAddBuffer( m_WaveIn, &m_WaveHeader, sizeof(WAVEHDR) ); 
    result = waveInStart( m_WaveIn ); 
   
	result = waveOutUnprepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );  
	m_SizeRecord = m_NbMaxSamples; 
    m_WaveHeader.lpData = (CHAR *)&InputBuffer[0]; 
    m_WaveHeader.dwBufferLength = m_SizeRecord *2; 
	m_WaveHeader.dwFlags = 0; 
	 
    result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) );  
 
//    result = waveOutWrite( m_WaveOut, &m_WaveHeader, sizeof(WAVEHDR) ); 
    result = waveOutRestart( m_WaveOut ); 
} 
 
/* 
WAVE_FORMAT_1M08  11.025 kHz, mono, 8-bit  
WAVE_FORMAT_1M16  11.025 kHz, mono, 16-bit  
WAVE_FORMAT_1S08  11.025 kHz, stereo, 8-bit  
WAVE_FORMAT_1S16  11.025 kHz, stereo, 16-bit  
WAVE_FORMAT_2M08  22.05 kHz, mono, 8-bit  
WAVE_FORMAT_2M16  22.05 kHz, mono, 16-bit  
WAVE_FORMAT_2S08  22.05 kHz, stereo, 8-bit  
WAVE_FORMAT_2S16  22.05 kHz, stereo, 16-bit  
WAVE_FORMAT_4M08  44.1 kHz, mono, 8-bit  
WAVE_FORMAT_4M16  44.1 kHz, mono, 16-bit  
WAVE_FORMAT_4S08  44.1 kHz, stereo, 8-bit  
WAVE_FORMAT_4S16  44.1 kHz, stereo, 16-bit  
*/  
 
void CSound:: WaveInitFormat(    WORD    nCh, // number of channels (mono, stereo) 
								DWORD   nSampleRate, // sample rate 
								WORD    BitsPerSample) 
{ 
	m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM; 
	m_WaveFormat.nChannels = nCh; 
	m_WaveFormat.nSamplesPerSec = nSampleRate; 
	m_WaveFormat.nAvgBytesPerSec = nSampleRate * nCh * BitsPerSample/8; 
	m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * BitsPerSample/8; 
	m_WaveFormat.wBitsPerSample = BitsPerSample; 
	m_WaveFormat.cbSize = 0; 
}    
 
 
/////////////////////////////////////////////////////////////////////////// 
// the comutation for the input samples need to be calibrated according 
// to the sound board  add an Offset and a Mult coef. 
 
void CSound::ComputeSamples(SHORT *pt) 
{ 
	int i; 
	for ( i = 0 ; im_WaveEvent,INFINITE); 
	FirstPass = FALSE; 
     
	while (!((CSound*)pParam)->m_TerminateThread) 
	{ 
		result = WaitForSingleObject(((CSound*)pParam)->m_WaveEvent,INFINITE); 
		if ((result == WAIT_OBJECT_0)&&(!((CSound*)pParam)->m_TerminateThread )) 
		{ 
			PT_S->AddBuffer();      // Toggle as changed state here !Toggle point to the just received buffer 
		    PT_S->ComputeSamples(PT_S->InputBuffer); 
		} 
		else 
			return 0;  //  
	} 
    return 0; 
}