📄 waveodev.cpp
字号:
// waveodev.cpp : implementation file
//
#include "stdafx.h"
#include "wave.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
// Global items
CWaveOutDevice theDefaultWaveOutDevice;
/////////////////////////////////////////////////////////////////////////////
// CWaveOutDevice
CWaveOutDevice::CWaveOutDevice()
{
m_hOutDev = NULL;
m_iBlockCount = 0;
m_pCallbackWnd = NULL;
}
CWaveOutDevice::~CWaveOutDevice()
{
}
#ifndef _DEBUG
#define MMERR(n) 0
#else
void MMERR(MMRESULT mmr)
{
switch (mmr) {
case WAVERR_BADFORMAT:
TRACE("No wave device supports format");
break;
case MMSYSERR_NOMEM:
TRACE("Out of memory");
break;
case MMSYSERR_ALLOCATED:
TRACE("Resource is already allocated");
break;
case MMSYSERR_BADDEVICEID:
TRACE("Bad device id");
break;
case MMSYSERR_INVALHANDLE:
TRACE("Invalid device handle");
break;
case MMSYSERR_HANDLEBUSY:
TRACE("Device in use by another thread");
break;
case WAVERR_UNPREPARED:
TRACE("Header not prepared");
break;
default:
TRACE("Unknown error");
break;
}
}
#endif // _DEBUG
/////////////////////////////////////////////////////////////////////////////
// CWaveOutDevice message handlers
BOOL CWaveOutDevice::IsOpen()
{
return m_hOutDev ? TRUE : FALSE;
}
BOOL CWaveOutDevice::Open(WAVEFORMATEX* pFormat)
{
MMRESULT mmr;
// Make sure we have a callback window.
if (!m_pCallbackWnd) {
m_pCallbackWnd = new CWaveDevWnd;
ASSERT(m_pCallbackWnd);
if (!m_pCallbackWnd->Create(this)) {
TRACE("Failed to create callback window");
delete m_pCallbackWnd;
m_pCallbackWnd = NULL;
return FALSE;
}
}
// See if already open for this format.
if (IsOpen()) {
// See if it can handle this format.
if (CanDoFormat(pFormat)) {
return TRUE;
} else {
TRACE("Open for different format");
return FALSE;
}
}
// See if we can open for this format.
mmr = waveOutOpen(&m_hOutDev,
WAVE_MAPPER,
pFormat,
(DWORD)(m_pCallbackWnd->GetSafeHwnd()),
0,
CALLBACK_WINDOW);
if (mmr != 0) {
MMERR(mmr);
return FALSE;
}
return TRUE;
}
BOOL CWaveOutDevice::CanDoFormat(WAVEFORMATEX* pFormat)
{
MMRESULT mmr;
if (!IsOpen()) {
TRACE("Not open");
return FALSE;
}
HWAVEOUT hDev = NULL;
mmr = waveOutOpen(&hDev,
WAVE_MAPPER,
pFormat,
NULL,
0,
WAVE_FORMAT_QUERY);
if (mmr != 0) {
MMERR(mmr);
return FALSE;
}
return TRUE;
}
BOOL CWaveOutDevice::Close()
{
if (m_hOutDev) {
// Close the device.
waveOutReset(m_hOutDev);
MMRESULT mmr = waveOutClose(m_hOutDev);
if (mmr != 0) {
MMERR(mmr);
}
m_hOutDev = NULL;
}
if (m_pCallbackWnd) {
// Remove the callback window since it's such a hassle
// to delete it at app death time.
m_pCallbackWnd->DestroyWindow();
delete m_pCallbackWnd;
m_pCallbackWnd = NULL;
}
return TRUE;
}
BOOL CWaveOutDevice::Play(CWave* pWave)
{
if (!Open(pWave->GetFormat())) {
return FALSE;
}
// Allocate a header.
WAVEHDR* phdr = (WAVEHDR*)malloc(sizeof(WAVEHDR));
ASSERT(phdr);
// Fill out the wave header.
memset(phdr, 0, sizeof(WAVEHDR));
phdr->lpData = (char*) pWave->GetSamples();
phdr->dwBufferLength = pWave->GetSize();
phdr->dwUser = (DWORD)(void*)pWave; // So that we can find the object.
// Prepare the header.
MMRESULT mmr = waveOutPrepareHeader(m_hOutDev,
phdr,
sizeof(WAVEHDR));
if (mmr) {
MMERR(mmr);
return FALSE;
}
// Mark the wave as busy.
pWave->SetBusy(TRUE);
// Start the wave playing.
mmr = waveOutWrite(m_hOutDev,
phdr,
sizeof(WAVEHDR));
if (mmr) {
MMERR(mmr);
return FALSE;
}
// Add one to the block count.
m_iBlockCount++;
return TRUE;
}
void CWaveOutDevice::Stop()
{
ASSERT(m_hOutDev);
waveOutReset(m_hOutDev);
}
void CWaveOutDevice::WaveOutDone(CWave* pWave, WAVEHDR* pHdr)
{
// Unprepare the header.
MMRESULT mmr = waveOutUnprepareHeader(m_hOutDev,
pHdr,
sizeof(WAVEHDR));
if (mmr) {
MMERR(mmr);
}
// Free the header.
free(pHdr);
// Decrement the block count.
ASSERT(m_iBlockCount > 0);
m_iBlockCount--;
if (m_iBlockCount == 0) {
// Close the device.
Close();
}
// Notify the object it is done.
pWave->SetBusy(FALSE);
pWave->OnWaveOutDone();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -