/**************************************************************************
* file: vtPlayWave.h *
* create: June 10, 2000 *
* copyright: @ 2000, by Zhaohui Xing *
* e-mail: xinghh@yahoo.com *
* description: implementation of VTPlayWave class *
**************************************************************************/
#include "stdafx.h"
#include "vtWave.h"
/**************************************************************************
* Default constructor *
**************************************************************************/
VTPlayWave::VTPlayWave() : VTWave()
{
}
/**************************************************************************
* Constructor *
**************************************************************************/
VTPlayWave::VTPlayWave(HWND hwnd, int iFormat)
:VTWave(hwnd, iFormat)
{
}
/**************************************************************************
* Destructor *
**************************************************************************/
VTPlayWave::~VTPlayWave()
{
// If wave output device still open
// close it
if(m_hwOut)
waveOutClose(m_hwOut);
// Release the memory for wave header
if(m_pWhdrOut)
CleanMemory();
}
/**************************************************************************
* Allocate memory for the header structure of wave output *
**************************************************************************/
BOOL VTPlayWave::AllocMemory(void)
{
// Allocated buffer for WAVEHDR structure
m_pWhdrOut = (WAVEHDR*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(WAVEHDR));
// Success
if(m_pWhdrOut)
{
// Allocate buffer of wave data in wave header structure
m_pWhdrOut->lpData = (char*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
VT_MAX);
// Set wave data buffer length
m_pWhdrOut->dwBufferLength = VT_MAX;
// Set the flag of wave header structure
m_pWhdrOut->dwFlags = 0;
}
else // An error ocurred
{
MessageBox(m_hWnd, "Failed to allocate memory for output device",
"Error in allocating output device memory", MB_OK);
return FALSE;
}
// OK
return TRUE;
}
/**************************************************************************
* Clearn the memory of the header structure of wave output *
**************************************************************************/
void VTPlayWave::CleanMemory(void)
{
// If not clean the buffer
if(m_pWhdrOut)
{
// First clean the buffer of wave data
if(m_pWhdrOut->lpData)
HeapFree(GetProcessHeap(), 0, m_pWhdrOut->lpData);
// Clean all
HeapFree(GetProcessHeap(), 0, m_pWhdrOut);
m_pWhdrOut = NULL;
}
}
/**************************************************************************
* Initialize and open the wave output device *
**************************************************************************/
BOOL VTPlayWave::Initialize(void)
{
WAVEOUTCAPS woc;
WAVEFORMATEX wfx;
UINT uiDevID;
MMRESULT rc;
UINT nMaxDevices = waveOutGetNumDevs();
char sError[129];
m_hwOut = NULL;
// Check the correct wave output device to open
for(uiDevID = 0; uiDevID < nMaxDevices; uiDevID++)
{
// Get output device caps
rc = waveOutGetDevCaps(uiDevID, &woc, sizeof(woc));
if(rc == MMSYSERR_NOERROR)
{
// Set the correct format for wave output device
wfx.nChannels = VTWAVECHANNEL[m_iFormat]; //1: mono, 2, stereo
wfx.nSamplesPerSec = VTWAVEFREQ[m_iFormat];
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.wBitsPerSample = VTWAVEBITS[m_iFormat];
wfx.nBlockAlign = wfx.nChannels*wfx.wBitsPerSample/8;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.cbSize = 0;
// Open the wave output device
rc = waveOutOpen(&m_hwOut, uiDevID, &wfx, (DWORD)m_hWnd, 0,
CALLBACK_WINDOW);
// If failed
if(rc != MMSYSERR_NOERROR)
{
// Get the error information
waveOutGetErrorText(rc, sError, 128),
MessageBox(m_hWnd, sError, "Error in output device opening",
MB_OK);
// Return false
return FALSE;
}
break;
}
}
// Device not found
if(m_hwOut == NULL)
{
MessageBox(m_hWnd, "Can't find correct output device to open",
"Error in e open playing device", MB_OK);
return FALSE;
}
// OK
return TRUE;
}
/**************************************************************************
* Start to play the sound *
**************************************************************************/
BOOL VTPlayWave::StartPlay(void)
{
MMRESULT rc;
char sError[129];
// Initialize and open the wave output device
Initialize();
// Pause the device for preparing the data
waveOutPause(m_hwOut);
// prepare the buffers
rc = waveOutPrepareHeader(m_hwOut, m_pWhdrOut, sizeof(WAVEHDR));
// write buffers to the queue
if(rc == MMSYSERR_NOERROR)
rc = waveOutWrite(m_hwOut, m_pWhdrOut, sizeof(WAVEHDR));
else // Failed
{
// Get error information
waveOutGetErrorText(rc, sError, 128),
MessageBox(m_hWnd, sError, "Error in preparing output buffer", MB_OK);
// Stop
StopPlay();
return FALSE;
}
// Start playback (device currently paused)
rc = waveOutRestart(m_hwOut);
// Failed
if(rc != MMSYSERR_NOERROR)
{
// Get error information
waveOutGetErrorText(rc, sError, 128),
MessageBox(m_hWnd, sError, "Error in starting output device", MB_OK);
// Stop
StopPlay();
return FALSE;
}
// OK
return TRUE;
}
/**************************************************************************
* Stop playing the sound *
**************************************************************************/
void VTPlayWave::StopPlay(void)
{
if(m_hwOut)
{
// Pause the output device
waveOutPause(m_hwOut);
// Unprepare headers
waveOutUnprepareHeader(m_hwOut, m_pWhdrOut, sizeof(WAVEHDR));
//Close the wave output device
waveOutClose(m_hwOut);
m_hwOut = NULL;
}
}
/**************************************************************************
* Reset wave data buffer to read new sound data *
**************************************************************************/
void VTPlayWave::ResetPlay(void)
{
// Pause the output device
waveOutPause(m_hwOut);
// Reset the wave header buffer
waveOutUnprepareHeader(m_hwOut, m_pWhdrOut, sizeof(WAVEHDR));
}
/**************************************************************************
* After reset wave data buffer and read new sound data,restart to play *
* the sound *
**************************************************************************/
BOOL VTPlayWave::RestartPlay(void)
{
MMRESULT rc;
char sError[129];
// Prepare the buffers
rc = waveOutPrepareHeader(m_hwOut, m_pWhdrOut, sizeof(WAVEHDR));
// Write buffers to the queue
if(rc == MMSYSERR_NOERROR)
rc = waveOutWrite(m_hwOut, m_pWhdrOut, sizeof(WAVEHDR));
else // Failed
{
// Get error information
waveOutGetErrorText(rc, sError, 128),
MessageBox(m_hWnd, sError, "Error in preparing output \
buffer for re-play", MB_OK);
// Not continus
StopPlay();
return FALSE;
}
// Restart playback device currently paused
rc = waveOutRestart(m_hwOut);
// Failed
if(rc != MMSYSERR_NOERROR)
{
// Get the error information
waveOutGetErrorText(rc, sError, 128),
MessageBox(m_hWnd, sError, "Error in starting output \
device for re-play", MB_OK);
// Not continus
StopPlay();
return FALSE;
}
// OK
return TRUE;
}
/**************************************************************************
* Set new sound data to the output header structure *
**************************************************************************/
void VTPlayWave::SetPlayData(void* pWaveData, unsigned int lBufSize)
{
unsigned int lRealSize;
// Limited the data buffer length
if(lBufSize > VT_MAX)
lRealSize = VT_MAX;
else
lRealSize = lBufSize;
// Clean buffer
memset((void*)m_pWhdrOut->lpData, 0, VT_MAX);
// Copy buffer
memcpy((void*)m_pWhdrOut->lpData, pWaveData, lRealSize);
m_pWhdrOut->dwBufferLength = lRealSize;
}