⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 waveodev.cpp

📁 西安电子科技大学王亚民教授所著《组态软件设计与开发》附带的源代码07章
💻 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 + -