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);
}
}
}