Re: Loading wave from resource.

From: Chris P. [MVP] (msdn_at_chrisnet.net)
Date: 09/14/04


Date: Tue, 14 Sep 2004 09:51:21 -0400

Patrick Waugh MA wrote:
> If I want to do this:
>
> See:
>
http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dx8_c/directx_cpp/audio_using_9oz3.asp
>
> That is to say, I've "imported" a wave resource named
>
> IDR_WAVE_ROTOR_LOW_WARNING
>
> how do I then use this class.method:
>
> CWaveFile waveFile;
>
> if (FAILED(waveFile.Open("mywave", NULL, WAVEFILE_READ)))
> {
> waveFile.Close();
> }
>
> to open/load the wave into the buffer?

You won't be able to use that class, as the name suggests it is designed for
files. You will need to create your own class similar to CWaveFile, or
modify the class - if you want to continue to use that interface.

See for example this modified CWaveFile class bits, you will need to already
have the memory pointer if your using a resource. See LoadResource() and
LockResource(). You of course could dispense with this class entirely and
simply create a secondary buffer large enough for the sample and copy the
data into the buffer in its entirety.

class CWaveFile
{
public:
    WAVEFORMATEX* m_pwfx; // Pointer to WAVEFORMATEX structure
    HMMIO m_hmmio; // MM I/O handle for the WAVE
    MMCKINFO m_ck; // Multimedia RIFF chunk
    MMCKINFO m_ckRiff; // Use in opening a WAVE file
    DWORD m_dwSize; // The size of the wave file
    MMIOINFO m_mmioinfoOut;
    DWORD m_dwFlags;
    BOOL m_bIsReadingFromMemory;
    BYTE* m_pbData;
    BYTE* m_pbDataCur;
    ULONG m_ulDataSize;
    CHAR* m_pResourceBuffer;

protected:
    HRESULT ReadMMIO();
    HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest );

public:
    CWaveFile();
    ~CWaveFile();

    HRESULT Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags );
    HRESULT OpenFromMemory( BYTE* pbData, ULONG ulDataSize, WAVEFORMATEX*
pwfx, DWORD dwFlags );
    HRESULT Close();

    HRESULT Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead );
    HRESULT Write( UINT nSizeToWrite, BYTE* pbData, UINT* pnSizeWrote );

    DWORD GetSize();
    HRESULT ResetFile();
    WAVEFORMATEX* GetFormat() { return m_pwfx; };
};

//--------------------------------------------------------------------------

---
// Name: CWaveFile::CWaveFile()
// Desc: Constructs the class.  Call Open() to open a wave file for reading.
//       Then call Read() as needed.  Calling the destructor or Close()
//       will close the file.
//--------------------------------------------------------------------------
---
CWaveFile::CWaveFile()
{
    m_pwfx    = NULL;
    m_hmmio   = NULL;
    m_pResourceBuffer = NULL;
    m_dwSize  = 0;
    m_bIsReadingFromMemory = FALSE;
}
//--------------------------------------------------------------------------
---
// Name: CWaveFile::~CWaveFile()
// Desc: Destructs the class
//--------------------------------------------------------------------------
---
CWaveFile::~CWaveFile()
{
    Close();
    if( !m_bIsReadingFromMemory )
        SAFE_DELETE_ARRAY( m_pwfx );
}
//--------------------------------------------------------------------------
---
// Name: CWaveFile::OpenFromMemory()
// Desc: copy data to CWaveFile member variable from memory
//--------------------------------------------------------------------------
---
HRESULT CWaveFile::OpenFromMemory( BYTE* pbData, ULONG ulDataSize,
                                   WAVEFORMATEX* pwfx, DWORD dwFlags )
{
    m_pwfx       = pwfx;
    m_ulDataSize = ulDataSize;
    m_pbData     = pbData;
    m_pbDataCur  = m_pbData;
    m_bIsReadingFromMemory = TRUE;
    if( dwFlags != WAVEFILE_READ )
        return E_NOTIMPL;
    return S_OK;
}
//--------------------------------------------------------------------------
---
// Name: CWaveFile::ResetFile()
// Desc: Resets the internal m_ck pointer so reading starts from the
//       beginning of the file again
//--------------------------------------------------------------------------
---
HRESULT CWaveFile::ResetFile()
{
    if( m_bIsReadingFromMemory )
    {
        m_pbDataCur = m_pbData;
    }
    else
    {
        if( m_hmmio == NULL )
            return CO_E_NOTINITIALIZED;
        if( m_dwFlags == WAVEFILE_READ )
        {
            // Seek to the data
            if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset +
sizeof(FOURCC),
                            SEEK_SET ) )
                return DXTRACE_ERR( TEXT("mmioSeek"), E_FAIL );
            // Search the input file for the 'data' chunk.
            m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
            if( 0 != mmioDescend( m_hmmio, &m_ck, &m_ckRiff,
MMIO_FINDCHUNK ) )
              return DXTRACE_ERR( TEXT("mmioDescend"), E_FAIL );
        }
        else
        {
            // Create the 'data' chunk that holds the waveform samples.
            m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
            m_ck.cksize = 0;
            if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) )
                return DXTRACE_ERR( TEXT("mmioCreateChunk"), E_FAIL );
            if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
                return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL );
        }
    }
    return S_OK;
}
//--------------------------------------------------------------------------
---
// Name: CWaveFile::Read()
// Desc: Reads section of data from a wave file into pBuffer and returns
//       how much read in pdwSizeRead, reading not more than dwSizeToRead.
//       This uses m_ck to determine where to start reading from.  So
//       subsequent calls will be continue where the last left off unless
//       Reset() is called.
//--------------------------------------------------------------------------
---
HRESULT CWaveFile::Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD*
pdwSizeRead )
{
    if( m_bIsReadingFromMemory )
    {
        if( m_pbDataCur == NULL )
            return CO_E_NOTINITIALIZED;
        if( pdwSizeRead != NULL )
            *pdwSizeRead = 0;
        if( (BYTE*)(m_pbDataCur + dwSizeToRead) >
            (BYTE*)(m_pbData + m_ulDataSize) )
        {
            dwSizeToRead = m_ulDataSize - (DWORD)(m_pbDataCur - m_pbData);
   // reset to beginning
   m_pbDataCur = m_pbData;
        }
        CopyMemory( pBuffer, m_pbDataCur, dwSizeToRead );
  m_pbDataCur += dwSizeToRead;
  if (m_pbDataCur >= m_pbData + m_ulDataSize)
   m_pbDataCur = m_pbData;
        if( pdwSizeRead != NULL )
            *pdwSizeRead = dwSizeToRead;
        return S_OK;
    }
    else
    {
        MMIOINFO mmioinfoIn; // current status of m_hmmio
        if( m_hmmio == NULL )
            return CO_E_NOTINITIALIZED;
        if( pBuffer == NULL || pdwSizeRead == NULL )
            return E_INVALIDARG;
        if( pdwSizeRead != NULL )
            *pdwSizeRead = 0;
        if( 0 != mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ) )
            return DXTRACE_ERR( TEXT("mmioGetInfo"), E_FAIL );
        UINT cbDataIn = dwSizeToRead;
        if( cbDataIn > m_ck.cksize )
            cbDataIn = m_ck.cksize;
        m_ck.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( m_hmmio, &mmioinfoIn, MMIO_READ ) )
                    return DXTRACE_ERR( TEXT("mmioAdvance"), E_FAIL );
                if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
                    return DXTRACE_ERR( TEXT("mmioinfoIn.pchNext"),
E_FAIL );
            }
            // Actual copy.
            *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext);
            mmioinfoIn.pchNext++;
        }
        if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) )
            return DXTRACE_ERR( TEXT("mmioSetInfo"), E_FAIL );
        if( pdwSizeRead != NULL )
            *pdwSizeRead = cbDataIn;
        return S_OK;
    }
}