www.pudn.com > ÓïÒôAudioCap.rar > WaveOut.cpp


// WaveOut.cpp: implementation of the CWaveOut class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
 
#include "WaveForm.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CWaveOut::CWaveOut() 
{ 
	m_iPlayDeviceNumber = waveOutGetNumDevs(); 
	m_hWaveOut = NULL; 
} 
 
CWaveOut::~CWaveOut() 
{ 
} 
 
BOOL CWaveOut::Init(HWND hWnd, int iTime, int iPlayDeviceID, int iSamplingRate, int iChannel, int iBits) 
{ 
	int i; 
 
	m_hWnd = hWnd; 
	m_iPlayDeviceID = iPlayDeviceID; 
	m_bPlay = (m_iPlayDeviceID >= 0) ? TRUE : FALSE; 
 
	m_wavFormat.wFormatTag = WAVE_FORMAT_PCM; 
	m_wavFormat.nChannels = iChannel; 
	m_wavFormat.nSamplesPerSec = iSamplingRate; 
	m_wavFormat.nAvgBytesPerSec = iSamplingRate * iChannel * iBits / 8; 
	m_wavFormat.nBlockAlign = iChannel * iBits / 8; 
	m_wavFormat.wBitsPerSample = iBits; 
 
	m_iWaveLength = iSamplingRate * iChannel * (iBits / 8) * iTime / 1000; 
 
	for (i = 0; i < WAVE_FORM_BUFFER_NUMBER; i ++) 
	{ 
		m_hWaveOutHeader[i] = m_hWaveOutData[i] = NULL; 
		m_pWaveOutHeader[i] = NULL; 
		m_pWaveOutData[i] = NULL; 
	} 
 
	if (m_bPlay) 
	{ 
		if (m_iPlayDeviceNumber < m_iPlayDeviceID + 1) 
		{ 
			OutputDebugString("WaveOut: No device available\n"); 
			goto Error; 
		} 
 
		// return 0 is supported; device is NOT opened after calling; 
		if (waveOutOpen(NULL, m_iPlayDeviceID, &m_wavFormat, NULL, NULL, WAVE_FORMAT_QUERY) != 0) 
		{ 
			OutputDebugString("WaveOut: Format not surportted\n"); 
			goto Error; 
		} 
 
		for (i = 0; i < WAVE_FORM_BUFFER_NUMBER; i ++) 
		{ 
			m_hWaveOutData[i] = GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE, m_iWaveLength); 
			if (m_hWaveOutData[i] == NULL) goto Error; 
			m_pWaveOutData[i] = (LPSTR)GlobalLock(m_hWaveOutData[i]); 
			if (m_pWaveOutData[i] == NULL) goto Error; 
 
			m_hWaveOutHeader[i] = GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE, sizeof(WAVEHDR)); 
			if (m_hWaveOutHeader[i] == NULL) goto Error; 
			m_pWaveOutHeader[i] = (LPWAVEHDR)GlobalLock(m_hWaveOutHeader[i]); 
			if (m_pWaveOutHeader[i] == NULL) goto Error; 
		} 
	} 
	return TRUE; 
 
Error: 
	Free(); 
	return FALSE; 
} 
 
void CWaveOut::Free() 
{ 
	int i; 
 
	if (m_hWaveOut != NULL)  
	{ 
		Stop(); 
	} 
 
	for (i = 0; i < WAVE_FORM_BUFFER_NUMBER; i ++) 
	{ 
		if (m_pWaveOutHeader[i] != NULL) 
			GlobalUnlock(m_hWaveOutHeader[i]); 
		if (m_hWaveOutHeader[i] != NULL) 
		{ 
			GlobalFree(m_hWaveOutHeader[i]); 
			m_hWaveOutHeader[i] = NULL; 
		} 
		if (m_pWaveOutData[i] != NULL)  
			GlobalUnlock(m_hWaveOutData[i]); 
		if (m_hWaveOutData[i] != NULL) 
		{ 
			GlobalFree(m_hWaveOutData[i]); 
			m_hWaveOutData[i] = NULL; 
		} 
	} 
	m_hWaveOut = NULL; 
	m_hWnd = NULL; 
} 
 
BOOL CWaveOut::Start() 
{ 
	int i; 
 
	if (m_hWnd == NULL || m_hWaveOut != NULL) 
	{ 
		return FALSE; 
	} 
 
	m_iWaveOutIdleBuffer = WAVE_FORM_BUFFER_NUMBER;//3¸öidle buffer 
	m_iWaveOutNextBuffer = 0;//the buffer to be used is the buffer 0 
 
	if (m_bPlay) 
	{ 
		m_bPlay = FALSE; 
		if (waveOutOpen(&m_hWaveOut, m_iPlayDeviceID, &m_wavFormat, (DWORD)m_hWnd, NULL, CALLBACK_WINDOW) != 0) 
		{ 
			OutputDebugString("WaveOut: Open device failed\n"); 
			m_hWaveOut = NULL; 
			goto Error; 
		} 
 
		for (i = 0; i < WAVE_FORM_BUFFER_NUMBER; i ++)//prepare buffer from 0 to 2 leaving buffer 3 
		{ 
			m_pWaveOutHeader[i]->lpData = m_pWaveOutData[i]; 
			m_pWaveOutHeader[i]->dwBufferLength = m_iWaveLength; 
			m_pWaveOutHeader[i]->dwFlags = 0; 
			m_pWaveOutHeader[i]->dwLoops = 0; 
 
			if (waveOutPrepareHeader(m_hWaveOut, m_pWaveOutHeader[i], sizeof(WAVEHDR)) != 0) 
			{ 
				OutputDebugString("WaveOut: Prepare head failed\n"); 
				goto Error; 
			} 
		} 
 
		for (i = WAVE_FORM_BUFFER_NUMBER - 2; i < WAVE_FORM_BUFFER_NUMBER; i ++) 
		{ 
			memset(m_pWaveOutData[i], 0, m_iWaveLength);//set value in buffer 1 and 2 to be 0 
			if (waveOutWrite(m_hWaveOut, m_pWaveOutHeader[i], sizeof(WAVEHDR)) != 0)//why write to driver 
			{ 
				OutputDebugString("WaveOut: Write data failed\n"); 
				goto Error; 
			} 
			m_iWaveOutIdleBuffer --;//set idle buffer to be 1 
			m_bPlay = TRUE;//why change state of m_bPlay 
		} 
	} 
 
	OutputDebugString("WaveOut started ok\n"); 
	return TRUE; 
 
Error: 
	Stop(); 
	return FALSE; 
} 
 
void CWaveOut::Stop() 
{ 
	int i; 
 
	if (m_bPlay) 
	{ 
		m_bPlay = FALSE; 
		if (m_hWaveOut != NULL) 
		{ 
			waveOutReset(m_hWaveOut); 
			for (i = 0; i < WAVE_FORM_BUFFER_NUMBER; i ++) 
			{ 
				waveOutUnprepareHeader(m_hWaveOut, m_pWaveOutHeader[i], sizeof(WAVEHDR)); 
			} 
			waveOutClose(m_hWaveOut); 
			m_hWaveOut = NULL; 
			m_bPlay = TRUE; 
		} 
	} 
 
	OutputDebugString("WaveOut stopped\n"); 
} 
 
BOOL CWaveOut::Play(char * pData, int iLength) 
{ 
	if (m_hWaveOut == NULL || m_bPlay == FALSE) 
	{ 
		OutputDebugString("Playing not ready\n"); 
		return FALSE; 
	} 
 
	if (m_iWaveOutIdleBuffer > 0) 
	{ 
		if (waveOutUnprepareHeader(m_hWaveOut, m_pWaveOutHeader[m_iWaveOutNextBuffer], sizeof(WAVEHDR)) != 0)	 
		{ 
			OutputDebugString("WaveOut: Unprepare head failed\n"); 
			return FALSE; 
		} 
 
		memcpy(m_pWaveOutData[m_iWaveOutNextBuffer], pData, iLength); 
		 
		m_pWaveOutHeader[m_iWaveOutNextBuffer]->lpData = m_pWaveOutData[m_iWaveOutNextBuffer]; 
		m_pWaveOutHeader[m_iWaveOutNextBuffer]->dwBufferLength = iLength; 
		m_pWaveOutHeader[m_iWaveOutNextBuffer]->dwFlags = 0; 
		m_pWaveOutHeader[m_iWaveOutNextBuffer]->dwLoops = 0; 
 
	    if (waveOutPrepareHeader(m_hWaveOut, m_pWaveOutHeader[m_iWaveOutNextBuffer], sizeof(WAVEHDR)) == 0) 
		{ 
			if (waveOutWrite(m_hWaveOut, m_pWaveOutHeader[m_iWaveOutNextBuffer], sizeof(WAVEHDR)) != 0) 
			{ 
				OutputDebugString("WaveOut: Write data failed\n"); 
				return FALSE; 
			} 
			else 
			{ 
				TRACE("play the sound indeed!\n"); 
			} 
		} 
		else 
		{ 
			OutputDebugString("WaveOut: Prepare head failed\n"); 
			return FALSE; 
		} 
 
		m_iWaveOutIdleBuffer --; 
		m_iWaveOutNextBuffer ++; 
		if (m_iWaveOutNextBuffer == WAVE_FORM_BUFFER_NUMBER) m_iWaveOutNextBuffer = 0; 
 
		//????????????????Ñ­»·µ÷Óã¿ 
		if (m_iWaveOutIdleBuffer > WAVE_FORM_BUFFER_NUMBER - 2)	// Keep at least 3 sound buffers working 
		{ 
			TRACE("Audio data be put in the play buffer again!\n"); 
			return Play(pData, iLength); 
		} 
	} 
	else 
	{ 
		OutputDebugString("WaveOut Buffer full\n"); 
//		waveOutReset(m_hWaveOut); 
		return FALSE; 
	} 
	return TRUE; 
} 
 
 
BOOL CWaveOut::ContinuePlaying() 
{ 
	m_iWaveOutIdleBuffer ++; 
	return TRUE; 
} 
 
void CWaveOut::GetPlayDeviceNames(CStringList& strList) 
{ 
	int i; 
	WAVEOUTCAPS cap; 
 
	for (i = 0; i < m_iPlayDeviceNumber; i++) 
	{ 
		waveOutGetDevCaps(i, &cap, sizeof(WAVEOUTCAPS));  
		if(cap.dwFormats) 
		{	 
			CString index; 
			index.Format("number %d: \t",i); 
			strList.AddTail(index+cap.szPname); 
		} 
	} 
}