151 lines
4.5 KiB
C++
151 lines
4.5 KiB
C++
#include <sample/waveout.hpp>
|
|
|
|
WaveOutDevice::WaveOutDevice(UINT waveDeviceID,Window &windowHandler)
|
|
: mWaveDeviceID(waveDeviceID), mhWaveOut(0),
|
|
mGlobalWaveHeader(1,GMEM_MOVEABLE|GMEM_ZEROINIT),
|
|
mWindowHandler(windowHandler), DeviceHandler(windowHandler),
|
|
mDisposition(InClose)
|
|
{
|
|
::waveOutGetDevCaps(mWaveDeviceID,&((WAVEOUTCAPS&)mWaveOutCaps),sizeof(mWaveOutCaps));
|
|
}
|
|
|
|
WaveOutDevice::WaveOutDevice(const WaveOutDevice &someWaveOutDevice)
|
|
: mWindowHandler(someWaveOutDevice.mWindowHandler), mhWaveOut(0),
|
|
mGlobalWaveHeader(1,GMEM_MOVEABLE|GMEM_ZEROINIT),
|
|
mWaveDeviceID(someWaveOutDevice.mWaveDeviceID),
|
|
DeviceHandler(someWaveOutDevice.mWindowHandler),
|
|
mDisposition(someWaveOutDevice.mDisposition)
|
|
{
|
|
*this=someWaveOutDevice;
|
|
}
|
|
|
|
WaveOutDevice::~WaveOutDevice()
|
|
{
|
|
closeDevice();
|
|
}
|
|
|
|
WaveOutDevice &WaveOutDevice::operator=(const WaveOutDevice &someWaveOutDevice)
|
|
{
|
|
mWaveOutCaps=someWaveOutDevice.mWaveOutCaps;
|
|
return *this;
|
|
}
|
|
|
|
BOOL WaveOutDevice::openDevice(WaveFormatPCM &waveFormatPCM)
|
|
{
|
|
MMRESULT mmResult;
|
|
|
|
closeDevice();
|
|
mmResult=::waveOutOpen(&mhWaveOut,mWaveDeviceID,(LPWAVEFORMATEX)&waveFormatPCM,(UINT)((HWND)mWindowHandler),0L,WAVE_ALLOWSYNC|CALLBACK_WINDOW);
|
|
if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;}
|
|
mDisposition=InOpen;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WaveOutDevice::closeDevice(void)
|
|
{
|
|
MMRESULT mmResult;
|
|
|
|
if(!mhWaveOut||InClose==mDisposition)return TRUE;
|
|
if(InPlay==mDisposition)
|
|
{
|
|
mmResult=::waveOutReset(mhWaveOut);
|
|
if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;}
|
|
}
|
|
while(InPlay==mDisposition)mWindowHandler.yieldTask();
|
|
mmResult=::waveOutClose(mhWaveOut);
|
|
if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;}
|
|
mDisposition=InClose;
|
|
mhWaveOut=0;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WaveOutDevice::pause(void)
|
|
{
|
|
MMRESULT mmResult;
|
|
|
|
if(InPlay!=mDisposition)return FALSE;
|
|
if(0!=(mmResult=::waveOutPause(mhWaveOut))){mmSystemErrorMessage(mmResult);return FALSE;}
|
|
mDisposition=InPause;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WaveOutDevice::restart(void)
|
|
{
|
|
MMRESULT mmResult;
|
|
|
|
if(InPause!=mDisposition)return FALSE;
|
|
if(0!=(mmResult=::waveOutRestart(mhWaveOut))){mmSystemErrorMessage(mmResult);return FALSE;}
|
|
mDisposition=InPlay;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WaveOutDevice::play(WaveForm &someWaveForm,DeviceHandler::PlayMode playMode)
|
|
{
|
|
MMRESULT mmResult;
|
|
DWORD bufferLength;
|
|
|
|
bufferLength=someWaveForm.getPureSample().getNumSamples() * (someWaveForm.getFormatChunk().bitsPerSample()/8); // bits per sample * 8 bits in a byte
|
|
WaveFormatPCM waveFormatPCM(someWaveForm.getFormatChunk());
|
|
|
|
if(WaveFormatEx::PulseCodeModulation!=waveFormatPCM.formatTag() &&
|
|
WaveFormatEx::AdPulseCodeModulation!=waveFormatPCM.formatTag())
|
|
{
|
|
genericErrorMessage(InvalidFormat);
|
|
return FALSE;
|
|
}
|
|
if(!openDevice(waveFormatPCM))return FALSE;
|
|
((WaveHeader*)&mGlobalWaveHeader[0])->setData((char*)(someWaveForm.getPureSample().getSampleData()));
|
|
// ((WaveHeader*)&mGlobalWaveHeader[0])->setBufferLength(someWaveForm.getPureSample().getNumSamples());
|
|
((WaveHeader*)&mGlobalWaveHeader[0])->setBufferLength(bufferLength);
|
|
((WaveHeader*)&mGlobalWaveHeader[0])->userData((DWORD)this);
|
|
mmResult=::waveOutPrepareHeader(mhWaveOut,(WAVEHDR*)((WaveHeader*)&mGlobalWaveHeader[0]),sizeof(WAVEHDR));
|
|
if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;}
|
|
mmResult=::waveOutWrite(mhWaveOut,(WAVEHDR*)((WaveHeader*)&mGlobalWaveHeader[0]),sizeof(WAVEHDR));
|
|
if(mmResult){mmSystemErrorMessage(mmResult);return FALSE;}
|
|
mDisposition=InPlay;
|
|
if(mmResult){mmSystemErrorMessage(mmResult);unprepareHeader();return FALSE;}
|
|
if(DeviceHandler::Wait==playMode)
|
|
{
|
|
while(InPlay==mDisposition)mWindowHandler.yieldTask();
|
|
closeDevice();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void WaveOutDevice::unprepareHeader(void)
|
|
{
|
|
if(!mhWaveOut){genericErrorMessage(DeviceHandler::InvalidDeviceHandle);return;}
|
|
if(!mGlobalWaveHeader.isOkay()){genericErrorMessage(DeviceHandler::InvalidHeader);return;}
|
|
::waveOutUnprepareHeader(mhWaveOut,(WAVEHDR*)((WaveHeader*)&mGlobalWaveHeader[0]),sizeof(WaveHeader));
|
|
}
|
|
|
|
// virtuals
|
|
|
|
void WaveOutDevice::openHandler(CallbackData &/*someCallbackData*/)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void WaveOutDevice::closeHandler(CallbackData &/*someCallbackData*/)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void WaveOutDevice::doneHandler(CallbackData &someCallbackData)
|
|
{
|
|
WaveHeader &waveHeader=(*((WaveHeader*)someCallbackData.lParam()));
|
|
|
|
if(waveHeader.userData()==(DWORD)this)
|
|
{
|
|
unprepareHeader();
|
|
mDisposition=InIdle;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void WaveOutDevice::message(const String &strErrorMessage)const
|
|
{
|
|
::OutputDebugString((String&)strErrorMessage+String("\n"));
|
|
}
|
|
|