www.pudn.com > tankedazhan.rar > wavread.cpp


//----------------------------------------------------------------------------- 
// File: WavRead.cpp 
// 
// Desc: Wave file support for loading and playing Wave files using DirectSound  
//       buffers. 
// 
// Copyright (c) 1999 Microsoft Corp. All rights reserved. 
//----------------------------------------------------------------------------- 
#include  
#include "WavRead.h" 
 
 
 
 
//----------------------------------------------------------------------------- 
// Defines, constants, and global variables 
//----------------------------------------------------------------------------- 
#define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } } 
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: ReadMMIO() 
// Desc: Support function for reading from a multimedia I/O stream 
//----------------------------------------------------------------------------- 
HRESULT ReadMMIO( HMMIO hmmioIn, MMCKINFO* pckInRIFF, WAVEFORMATEX** ppwfxInfo ) 
{ 
    MMCKINFO        ckIn;           // chunk info. for general use. 
    PCMWAVEFORMAT   pcmWaveFormat;  // Temp PCM structure to load in.        
 
    *ppwfxInfo = NULL; 
 
    if( ( 0 != mmioDescend( hmmioIn, pckInRIFF, NULL, 0 ) ) ) 
        return E_FAIL; 
 
    if( (pckInRIFF->ckid != FOURCC_RIFF) || 
        (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E') ) ) 
        return E_FAIL; 
 
    // Search the input file for for the 'fmt ' chunk. 
    ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); 
    if( 0 != mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK) ) 
        return E_FAIL; 
 
    // Expect the 'fmt' chunk to be at least as large as ; 
    // if there are extra parameters at the end, we'll ignore them 
       if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) ) 
           return E_FAIL; 
 
    // Read the 'fmt ' chunk into . 
    if( mmioRead( hmmioIn, (HPSTR) &pcmWaveFormat,  
                  sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) ) 
        return E_FAIL; 
 
    // Allocate the waveformatex, but if its not pcm format, read the next 
    // word, and thats how many extra bytes to allocate. 
    if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) 
    { 
        if( NULL == ( *ppwfxInfo = new WAVEFORMATEX ) ) 
            return E_FAIL; 
 
        // Copy the bytes from the pcm structure to the waveformatex structure 
        memcpy( *ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat) ); 
        (*ppwfxInfo)->cbSize = 0; 
    } 
    else 
    { 
        // Read in length of extra bytes. 
        WORD cbExtraBytes = 0L; 
        if( mmioRead( hmmioIn, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) ) 
            return E_FAIL; 
 
        *ppwfxInfo = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; 
        if( NULL == *ppwfxInfo ) 
            return E_FAIL; 
 
        // Copy the bytes from the pcm structure to the waveformatex structure 
        memcpy( *ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat) ); 
        (*ppwfxInfo)->cbSize = cbExtraBytes; 
 
        // Now, read those extra bytes into the structure, if cbExtraAlloc != 0. 
        if( mmioRead( hmmioIn, (CHAR*)(((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(WORD)), 
                      cbExtraBytes ) != cbExtraBytes ) 
        { 
            delete *ppwfxInfo; 
            *ppwfxInfo = NULL; 
            return E_FAIL; 
        } 
    } 
 
    // Ascend the input file out of the 'fmt ' chunk. 
    if( 0 != mmioAscend( hmmioIn, &ckIn, 0 ) ) 
    { 
        delete *ppwfxInfo; 
        *ppwfxInfo = NULL; 
        return E_FAIL; 
    } 
 
    return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: WaveOpenFile() 
// Desc: This function will open a wave input file and prepare it for reading, 
//       so the data can be easily read with WaveReadFile. Returns 0 if 
//       successful, the error code if not. 
//----------------------------------------------------------------------------- 
HRESULT WaveOpenFile( CHAR* strFileName, HMMIO* phmmioIn, WAVEFORMATEX** ppwfxInfo, 
                  MMCKINFO* pckInRIFF ) 
{ 
    HRESULT hr; 
    HMMIO   hmmioIn = NULL; 
     
    if( NULL == ( hmmioIn = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF|MMIO_READ ) ) ) 
        return E_FAIL; 
 
    if( FAILED( hr = ReadMMIO( hmmioIn, pckInRIFF, ppwfxInfo ) ) ) 
    { 
        mmioClose( hmmioIn, 0 ); 
        return hr; 
    } 
 
    *phmmioIn = hmmioIn; 
 
    return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: WaveStartDataRead() 
// Desc: Routine has to be called before WaveReadFile as it searches for the 
//       chunk to descend into for reading, that is, the 'data' chunk.  For 
//       simplicity, this used to be in the open routine, but was taken out and 
//       moved to a separate routine so there was more control on the chunks 
//       that are before the data chunk, such as 'fact', etc... 
//----------------------------------------------------------------------------- 
HRESULT WaveStartDataRead( HMMIO* phmmioIn, MMCKINFO* pckIn, 
                           MMCKINFO* pckInRIFF ) 
{ 
    // Seek to the data 
    if( -1 == mmioSeek( *phmmioIn, pckInRIFF->dwDataOffset + sizeof(FOURCC), 
                        SEEK_SET ) ) 
        return E_FAIL; 
 
    // Search the input file for for the 'data' chunk. 
    pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a'); 
    if( 0 != mmioDescend( *phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK ) ) 
        return E_FAIL; 
 
    return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: WaveReadFile() 
// Desc: Reads wave data from the wave file. Make sure we're descended into 
//       the data chunk before calling this function. 
//          hmmioIn      - Handle to mmio. 
//          cbRead       - # of bytes to read.    
//          pbDest       - Destination buffer to put bytes. 
//          cbActualRead - # of bytes actually read. 
//----------------------------------------------------------------------------- 
HRESULT WaveReadFile( HMMIO hmmioIn, UINT cbRead, BYTE* pbDest, 
                      MMCKINFO* pckIn, UINT* cbActualRead ) 
{ 
    MMIOINFO mmioinfoIn;         // current status of  
 
    *cbActualRead = 0; 
 
    if( 0 != mmioGetInfo( hmmioIn, &mmioinfoIn, 0 ) ) 
        return E_FAIL; 
                 
    UINT cbDataIn = cbRead; 
    if( cbDataIn > pckIn->cksize )  
        cbDataIn = pckIn->cksize;        
 
    pckIn->cksize -= cbDataIn; 
     
    for( DWORD cT = 0; cT < cbDataIn; cT++ ) 
    { 
        // Copy the bytes from the io to the buffer. 
        if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) 
        { 
            if( 0 != mmioAdvance( hmmioIn, &mmioinfoIn, MMIO_READ ) ) 
                return E_FAIL; 
 
            if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) 
                return E_FAIL; 
        } 
 
        // Actual copy. 
        *((BYTE*)pbDest+cT) = *((BYTE*)mmioinfoIn.pchNext); 
        mmioinfoIn.pchNext++; 
    } 
 
    if( 0 != mmioSetInfo( hmmioIn, &mmioinfoIn, 0 ) ) 
        return E_FAIL; 
 
    *cbActualRead = cbDataIn; 
    return S_OK; 
} 
 
 
 
   
//----------------------------------------------------------------------------- 
// Name: CWaveSoundRead() 
// Desc: Constructs the class 
//----------------------------------------------------------------------------- 
CWaveSoundRead::CWaveSoundRead() 
{ 
    m_pwfx   = NULL; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: ~CWaveSoundRead() 
// Desc: Destructs the class 
//----------------------------------------------------------------------------- 
CWaveSoundRead::~CWaveSoundRead() 
{ 
    Close(); 
    SAFE_DELETE( m_pwfx ); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: Open() 
// Desc: Opens a wave file for reading 
//----------------------------------------------------------------------------- 
HRESULT CWaveSoundRead::Open( CHAR* strFilename ) 
{ 
    SAFE_DELETE( m_pwfx ); 
 
    HRESULT  hr; 
     
    if( FAILED( hr = WaveOpenFile( strFilename, &m_hmmioIn, &m_pwfx, &m_ckInRiff ) ) ) 
        return hr; 
 
    if( FAILED( hr = Reset() ) ) 
        return hr; 
 
    return hr; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: Reset() 
// Desc: Resets the internal m_ckIn pointer so reading starts from the  
//       beginning of the file again  
//----------------------------------------------------------------------------- 
HRESULT CWaveSoundRead::Reset() 
{ 
    return WaveStartDataRead( &m_hmmioIn, &m_ckIn, &m_ckInRiff ); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: Read() 
// Desc: Reads a wave file into a pointer and returns how much read 
//       using m_ckIn to determine where to start reading from 
//----------------------------------------------------------------------------- 
HRESULT CWaveSoundRead::Read( UINT nSizeToRead, BYTE* pbData, UINT* pnSizeRead ) 
{ 
    return WaveReadFile( m_hmmioIn, nSizeToRead, pbData, &m_ckIn, pnSizeRead ); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: Close() 
// Desc: Closes an open wave file  
//----------------------------------------------------------------------------- 
HRESULT CWaveSoundRead::Close() 
{ 
    mmioClose( m_hmmioIn, 0 ); 
    return S_OK; 
}