| 
 | 
 
想要查看内容赶紧注册登陆吧!
您需要 登录 才可以下载或查看,没有账号?立即注册  
 
x
 
  ///////////////////////////////////////////////////////////////////////////// 
// Copyright (C) 1998 by J鰎g K鰊ig 
// All rights reserved 
// 
// This file is part of the completely free tetris clone "CGTetris". 
// 
// This is free software. 
// You may redistribute it by any means providing it is not sold for profit 
// without the authors written consent. 
// 
// No warrantee of any kind, expressed or implied, is included with this 
// software; use at your own risk, responsibility for damages (if any) to 
// anyone resulting from the use of this software rests entirely with the 
// user. 
// 
// Send bug reports, bug fixes, enhancements, requests, flames, etc., and 
// I'll try to keep a version up to date.  I can be reached as follows: 
//    J.Koenig@adg.de                 (company site) 
//    Joerg.Koenig@rhein-neckar.de    (private site) 
///////////////////////////////////////////////////////////////////////////// 
 
 
// DirectSound.cpp: implementation of the CDirectSound class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "DirectSound.h" 
 
// The following macro is defined since DirectX 5, but will work with 
// older versions too. 
#ifndef DSBLOCK_ENTIREBUFFER 
    #define DSBLOCK_ENTIREBUFFER        0x00000002 
#endif 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
static void DSError( HRESULT hRes ) { 
    switch(hRes) { 
        case DS_OK: TRACE0("NO ERROR\n"); break; 
        case DSERR_ALLOCATED: TRACE0("ALLOCATED\n"); break; 
        case DSERR_INVALIDPARAM: TRACE0("INVALIDPARAM\n"); break; 
        case DSERR_OUTOFMEMORY: TRACE0("OUTOFMEMORY\n"); break; 
        case DSERR_UNSUPPORTED: TRACE0("UNSUPPORTED\n"); break; 
        case DSERR_NOAGGREGATION: TRACE0("NOAGGREGATION\n"); break; 
        case DSERR_UNINITIALIZED: TRACE0("UNINITIALIZED\n"); break; 
        case DSERR_BADFORMAT: TRACE0("BADFORMAT\n"); break; 
        case DSERR_ALREADYINITIALIZED: TRACE0("ALREADYINITIALIZED\n"); break; 
        case DSERR_BUFFERLOST: TRACE0("BUFFERLOST\n"); break; 
        case DSERR_CONTROLUNAVAIL: TRACE0("CONTROLUNAVAIL\n"); break; 
        case DSERR_GENERIC: TRACE0("GENERIC\n"); break; 
        case DSERR_INVALIDCALL: TRACE0("INVALIDCALL\n"); break; 
        case DSERR_OTHERAPPHASPRIO: TRACE0("OTHERAPPHASPRIO\n"); break; 
        case DSERR_PRIOLEVELNEEDED: TRACE0(" RIOLEVELNEEDED\n"); break; 
        default: TRACE1("%lu\n",hRes);break; 
    } 
} 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
LPDIRECTSOUND CDirectSound::m_lpDirectSound; 
DWORD CDirectSound::m_dwInstances; 
 
 
CDirectSound::CDirectSound() 
{ 
    m_lpDirectSound = 0; 
    m_pDsb = 0; 
    m_pTheSound = 0; 
    m_dwTheSound = 0; 
    m_bEnabled = TRUE; 
 
    ++m_dwInstances; 
} 
 
CDirectSound::~CDirectSound() 
{ 
    if( m_pDsb ) 
        m_pDsb->Release(); 
 
    if( !--m_dwInstances && m_lpDirectSound ) { 
        m_lpDirectSound->Release(); 
        m_lpDirectSound = 0; 
    } 
} 
 
BOOL CDirectSound::Create(LPCTSTR pszResource, CWnd * pWnd) 
{ 
    ////////////////////////////////////////////////////////////////// 
    // load resource 
    HINSTANCE hApp = ::GetModuleHandle(0); 
    ASSERT(hApp); 
 
    HRSRC hResInfo = ::FindResource(hApp, pszResource, TEXT("WAVE")); 
    if(hResInfo == 0) 
        return FALSE; 
 
    HGLOBAL hRes = : oadResource(hApp, hResInfo); 
    if(hRes == 0) 
        return FALSE; 
 
    LPVOID pTheSound = : ockResource(hRes); 
    if(pTheSound == 0) 
        return FALSE; 
 
    return Create(pTheSound, pWnd); 
} 
 
 
BOOL CDirectSound :: Create(LPVOID pSoundData, CWnd * pWnd) { 
    if(pWnd == 0) 
        pWnd = AfxGetApp()->GetMainWnd(); 
 
    ASSERT(pWnd != 0); 
    ASSERT(::IsWindow(pWnd->GetSafeHwnd())); 
 
    ASSERT(pSoundData != 0); 
 
    ////////////////////////////////////////////////////////////////// 
    // create direct sound object 
     
    if( m_lpDirectSound == 0 ) { 
        // Someone might use sounds for starting apps. This may cause 
        // DirectSoundCreate() to fail because the driver is used by 
        // anyone else. So wait a little before starting with the work ... 
        HRESULT hRes = DS_OK; 
        short nRes = 0; 
 
        do { 
            if( nRes ) 
                ::Sleep(500); 
            hRes = : irectSoundCreate(0, &m_lpDirectSound, 0); 
            ++nRes; 
        } while( nRes < 10 && (hRes == DSERR_ALLOCATED || hRes == DSERR_NODRIVER) ); 
 
        if( hRes != DS_OK ) 
            return FALSE; 
     
        m_lpDirectSound->SetCooperativeLevel(pWnd->GetSafeHwnd(), DSSCL_NORMAL); 
    } 
 
    ASSERT(m_lpDirectSound != 0); 
 
    WAVEFORMATEX * pcmwf; 
    if( ! GetWaveData(pSoundData, pcmwf, m_pTheSound, m_dwTheSound) || 
        ! CreateSoundBuffer(pcmwf) || 
        ! SetSoundData(m_pTheSound, m_dwTheSound) ) 
        return FALSE; 
 
    return TRUE; 
} 
 
 
BOOL CDirectSound :: GetWaveData(void * pRes, WAVEFORMATEX * & pWaveHeader, void * & pbWaveData, DWORD & cbWaveSize) { 
    pWaveHeader = 0; 
    pbWaveData = 0; 
    cbWaveSize = 0; 
 
    DWORD * pdw = (DWORD *)pRes; 
    DWORD dwRiff = *pdw++; 
    DWORD dwLength = *pdw++; 
    DWORD dwType = *pdw++; 
 
    if( dwRiff != mmioFOURCC('R', 'I', 'F', 'F') ) 
        return FALSE;      // not even RIFF 
 
    if( dwType != mmioFOURCC('W', 'A', 'V', 'E') ) 
        return FALSE;      // not a WAV 
 
    DWORD * pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4); 
 
    while( pdw < pdwEnd ) { 
        dwType = *pdw++; 
        dwLength = *pdw++; 
 
        switch( dwType ) { 
            case mmioFOURCC('f', 'm', 't', ' '): 
                if( !pWaveHeader ) { 
                    if( dwLength < sizeof(WAVEFORMAT) ) 
                        return FALSE;      // not a WAV 
 
                    pWaveHeader = (WAVEFORMATEX *)pdw; 
 
                    if( pbWaveData && cbWaveSize ) 
                        return TRUE; 
                } 
                break; 
 
            case mmioFOURCC('d', 'a', 't', 'a'): 
                pbWaveData = LPVOID(pdw); 
                cbWaveSize = dwLength; 
 
                if( pWaveHeader ) 
                    return TRUE; 
                break; 
        } 
        pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1)); 
    } 
 
    return FALSE; 
} 
 
 
BOOL CDirectSound::CreateSoundBuffer(WAVEFORMATEX * pcmwf) 
{ 
    DSBUFFERDESC dsbdesc; 
 
    // Set up DSBUFFERDESC structure. 
    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out. 
    dsbdesc.dwSize = sizeof(DSBUFFERDESC); 
    // Need no controls (pan, volume, frequency). 
    dsbdesc.dwFlags = DSBCAPS_STATIC;        // assumes that the sound is played often 
    dsbdesc.dwBufferBytes = m_dwTheSound; 
    dsbdesc.lpwfxFormat = pcmwf;    // Create buffer. 
    HRESULT hRes; 
    if( DS_OK != (hRes = m_lpDirectSound->CreateSoundBuffer(&dsbdesc, &m_pDsb, 0)) ) { 
        // Failed. 
        DSError(hRes); 
        m_pDsb = 0; 
        return FALSE; 
    } 
 
    return TRUE; 
} 
 
 
BOOL CDirectSound::SetSoundData(void * pSoundData, DWORD dwSoundSize) { 
    LPVOID lpvPtr1; 
    DWORD dwBytes1; 
    // Obtain write pointer. 
    HRESULT hr = m_pDsb->Lock(0, 0, &lpvPtr1, &dwBytes1, 0, 0, DSBLOCK_ENTIREBUFFER);     
    // If DSERR_BUFFERLOST is returned, restore and retry lock. 
    if(DSERR_BUFFERLOST == hr) { 
        m_pDsb->Restore(); 
        hr = m_pDsb->Lock(0, 0, &lpvPtr1, &dwBytes1, 0, 0, DSBLOCK_ENTIREBUFFER); 
    } 
    if(DS_OK == hr) { 
        // Write to pointers. 
        ::CopyMemory(lpvPtr1, pSoundData, dwBytes1); 
        // Release the data back to DirectSound. 
        hr = m_pDsb->Unlock(lpvPtr1, dwBytes1, 0, 0); 
        if(DS_OK == hr) 
            return TRUE; 
    } 
    // Lock, Unlock, or Restore failed. 
    return FALSE; 
} 
 
void CDirectSound: lay(DWORD dwStartPosition, BOOL bLoop) 
{ 
    if( ! IsValid() || ! IsEnabled() ) 
        return;        // no chance to play the sound ... 
 
    if( dwStartPosition > m_dwTheSound ) 
        dwStartPosition = m_dwTheSound; 
    m_pDsb->SetCurrentPosition(dwStartPosition); 
    if( DSERR_BUFFERLOST == m_pDsb-> lay(0, 0, bLoop ? DSBPLAY_LOOPING : 0) ) { 
        // another application had stolen our buffer 
        // Note that a "Restore()" is not enough, because 
        // the sound data is invalid after Restore(). 
        SetSoundData(m_pTheSound, m_dwTheSound); 
 
        // Try playing again 
        m_pDsb-> lay(0, 0, bLoop ? DSBPLAY_LOOPING : 0); 
    } 
} 
 
void CDirectSound::Stop() 
{ 
    if( IsValid() ) 
        m_pDsb->Stop(); 
} 
 
void CDirectSound: ause() 
{ 
    Stop(); 
} 
 
void CDirectSound::Continue() 
{ 
    if( IsValid() ) { 
        DWORD dwPlayCursor, dwWriteCursor; 
        m_pDsb->GetCurrentPosition(&dwPlayCursor, &dwWriteCursor); 
        Play(dwPlayCursor); 
    } 
} 
 
BOOL CDirectSound::IsValid() const 
{ 
    return (m_lpDirectSound && m_pDsb && m_pTheSound && m_dwTheSound) ? TRUE : FALSE; 
} 
  
 |   
 
 
 
 |