www.pudn.com > fftanalysis > SoundOut.cpp, change:2003-04-15,size:5301b


#include "stdafx.h" 
#include "math.h" 
#include "SoundOut.h" 
 
#pragma comment(lib, "winmm") 
////////////////////////////////////////////////////// 
//			以下决定是采用回调函数还是线程			// 
////////////////////////////////////////////////////// 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
#define real double 
 
UINT WaveOutThreadProc(void * pParam); 
void CALLBACK WaveOutProc(HWAVEOUT hwo,UINT uMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2); 
 
CSoundOut::CSoundOut() 
{ 
	DspCallBack=NULL; 
	m_Toggle = 0; 
	WaveInitFormat(1,11025,16); 
} 
 
CSoundOut::~CSoundOut() 
{ 
	CloseOutput(); 
} 
/////////////////////////////////////////////////////////////////// 
MMRESULT CSoundOut::OpenOutput() 
{ 
	MMRESULT result; 
    result=waveOutGetNumDevs();  
	if (result == 0) 
	{ 
        AfxMessageBox("找不到声音输出设备!"); 
		return result; 
	} 
	result=waveOutGetDevCaps (0, &m_WaveOutDevCaps, sizeof(WAVEOUTCAPS)); 
	if ( result!= MMSYSERR_NOERROR) 
	{ 
		AfxMessageBox(_T("无法确定声卡输出能力!")); 
	} 
	m_Terminate = FALSE; 
 
	//************************* 
	//打开输出设备,设定回调函数 
	result = waveOutOpen( &m_WaveOut,0, &m_WaveFormat,(DWORD)WaveOutProc ,(ULONG)this ,CALLBACK_FUNCTION);  
	if ( result!= MMSYSERR_NOERROR) 
	{ 
        AfxMessageBox(_T("声音输出设备打开失败!")); 
	    return result; 
	} 
 
    m_WaveHeader[0].lpData = m_WaveBuffer[0]; 
    m_WaveHeader[0].dwBufferLength = WAVEOUT_LENGTH; 
	m_WaveHeader[0].dwFlags = 0; 
	//准备音频数据块 
    result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader[0], sizeof(WAVEHDR) );  
	if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader[0].dwFlags != WHDR_PREPARED) ) 
	{ 
        AfxMessageBox(_T("无法准备数据")); 
	    return result; 
	} 
	//写数据 
	result = waveOutWrite( m_WaveOut, &m_WaveHeader[0], sizeof(WAVEHDR) ); 
	if  (result!= MMSYSERR_NOERROR)  
	{ 
        AfxMessageBox(_T("写数据输出缓冲失败")); 
	    return result; 
	} 
	//为了让播放连续,继续注册第二帧数据。 
	//注意若继续注册第一帧数据,则第二帧数据将立即播放 
    m_WaveHeader[1].lpData = m_WaveBuffer[1]; 
    m_WaveHeader[1].dwBufferLength = WAVEOUT_LENGTH; 
	m_WaveHeader[1].dwFlags = 0; 
	//准备音频数据块 
    result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader[1], sizeof(WAVEHDR) );  
	if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader[1].dwFlags != WHDR_PREPARED) ) 
	{ 
        AfxMessageBox(_T("无法准备数据2")); 
	    return result; 
	} 
	//写数据 
	result = waveOutWrite( m_WaveOut, &m_WaveHeader[1], sizeof(WAVEHDR) ); 
	if  (result!= MMSYSERR_NOERROR)  
	{ 
        AfxMessageBox(_T("写数据输出缓冲失败")); 
	    return result; 
	} 
	m_Toggle=1; 
	return result; 
} 
 
void CSoundOut::AddBuffer() 
{	 
	MMRESULT result; 
 
	m_Toggle^=1; 
	result = waveOutUnprepareHeader( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR)); 
	if  (result!= MMSYSERR_NOERROR)  
	{ 
       	AfxMessageBox(_T("清除缓冲失败!")); 
   		return; 
	}; 
	m_WaveHeader[m_Toggle].lpData = m_WaveBuffer[m_Toggle]; 
   	m_WaveHeader[m_Toggle].dwBufferLength =  WAVEOUT_LENGTH; 
	m_WaveHeader[m_Toggle].dwLoops = 0; 
	m_WaveHeader[m_Toggle].dwFlags = 0; 
	//WHDR_BEGINLOOP ; 
	//准备数据块 
    result = waveOutPrepareHeader( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) );  
	if ( (result!= MMSYSERR_NOERROR) || ( m_WaveHeader[m_Toggle].dwFlags != WHDR_PREPARED) ) 
        AfxMessageBox(_T("无法准备数据")); 
	//写数据 
	result = waveOutWrite( m_WaveOut, &m_WaveHeader[m_Toggle], sizeof(WAVEHDR) ); 
	if  (result!= MMSYSERR_NOERROR)  
        AfxMessageBox(_T("写数据输出缓冲失败")); 
} 
 
void CSoundOut:: WaveInitFormat(WORD    nChannel,			//声道数(mono, stereo) 
								DWORD   nSampleRate,	//采样率 
								WORD    nBitsPerSample) 
{ 
	//分配内存 
	m_WaveFormat.wFormatTag = WAVE_FORMAT_PCM; 
	m_WaveFormat.nChannels = nChannel; 
	m_WaveFormat.nSamplesPerSec = nSampleRate; 
	m_WaveFormat.nAvgBytesPerSec = nSampleRate * nChannel * nBitsPerSample/8; 
	m_WaveFormat.nBlockAlign = m_WaveFormat.nChannels * nBitsPerSample/8; 
	m_WaveFormat.wBitsPerSample = nBitsPerSample; 
	m_WaveFormat.cbSize = 0; 
	m_Toggle = 0; 
}    
 
void CSoundOut::SetCallBack(PFCALLBACK fback,DWORD param) 
{ 
	DspCallBack=fback; 
	lparam=param; 
} 
 
void CSoundOut::ComputeSamples(int *pt) 
{ 
	if(DspCallBack!=NULL) 
	{ 
		DspCallBack(m_Toggle,lparam); 
	} 
}  
  
//关闭放音 
void CSoundOut::CloseOutput() 
{ 
	if (m_WaveOut)  
		waveOutPause(m_WaveOut); 
    Sleep(50); 
	//CloseHandle(m_WaveOut); 
	m_Terminate = TRUE; 
    if (m_WaveOutEvent ) 
		SetEvent(m_WaveOutEvent); 
    Sleep(50); 
	if (m_WaveOut)  
	{ 
		waveOutReset(m_WaveOut); 
		waveOutClose(m_WaveOut); 
	} 
} 
 
void CSoundOut::StopOutput() 
{ 
	waveOutPause(m_WaveOut); 
} 
 
void CSoundOut::StartOutput() 
{ 
	waveOutRestart(m_WaveOut); 
} 
 
#define PT_S ((CSoundOut*)pParam)  
////////////////////////////////////////////////////////////// 
//							回调函数						// 
//////////////////////////////////////////////////////////////  
void CALLBACK WaveOutProc(HWAVEOUT hwo,UINT uMsg,DWORD pParam,DWORD dwParam1,DWORD dwParam2) 
{ 
	if (!PT_S->m_Terminate ) 
	switch (uMsg) 
	{ 
	case WOM_DONE: 
		PT_S->AddBuffer(); 
	    PT_S->ComputeSamples(&PT_S->m_Toggle); 
		break; 
	case WOM_OPEN: 
		break; 
	case WOM_CLOSE: 
		break; 
	} 
}