谢谢!
4 个解决方案
#1
头文件:
[/code]
#ifndef CLASS_WAV_FILE_H_
#define CLASS_WAV_FILE_H_
#define WAVEFILE_READ 1
#define WAVEFILE_WRITE 2
#include <Windows.h>
#include <MMSystem.h>
#pragma comment(lib,"winmm.lib")
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 flag_;
BYTE* m_pbData;
BYTE* m_pbDataCur;
ULONG m_ulDataSize;
CHAR* m_pResourceBuffer;
WAVEFORMATEX wave_format_;
protected:
HRESULT ReadMMIO();
HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest );
public:
CWaveFile();
~CWaveFile();
HRESULT Open(
LPTSTR filename,
DWORD flag,
UINT channels,
ULONG samples_per_sec,
UINT bits_per_sample);
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; };
};
#endif // ! CLASS_WAV_FILE_H_
[/code]
#2
cpp文件:
#include "stdafx.h"
#include "common-header.h"
#include "WavFile.h"
CWaveFile::CWaveFile()
{
m_pwfx = NULL;
m_hmmio = NULL;
m_pResourceBuffer = NULL;
m_dwSize = 0;
}
CWaveFile::~CWaveFile()
{
Close();
SAFE_DELETE_ARRAY( m_pwfx );
}
HRESULT CWaveFile::Open( LPTSTR filename, DWORD flag, UINT channels, ULONG samples_per_sec, UINT bits_per_sample )
{
wave_format_.cbSize = 0;
wave_format_.wFormatTag = WAVE_FORMAT_PCM;
wave_format_.nChannels = channels;
wave_format_.nSamplesPerSec = samples_per_sec;
wave_format_.wBitsPerSample = bits_per_sample;
wave_format_.nBlockAlign = wave_format_.nChannels * ( wave_format_.wBitsPerSample / 8 );
wave_format_.nAvgBytesPerSec = wave_format_.nBlockAlign * wave_format_.nSamplesPerSec;
HRESULT hr;
flag_ = flag;
if( flag_ == WAVEFILE_READ ) {
if( filename == NULL )
return E_INVALIDARG;
SAFE_DELETE_ARRAY( m_pwfx );
m_hmmio = mmioOpen( filename, NULL, MMIO_ALLOCBUF | MMIO_READ );
if( NULL == m_hmmio ) {
HRSRC hResInfo;
HGLOBAL hResData;
DWORD dwSize;
VOID *pvRes;
// Loading it as a file failed, so try it as a resource
if( NULL == ( hResInfo = FindResource( NULL, filename, TEXT("WAVE") ) ) ) {
if( NULL == ( hResInfo = FindResource( NULL, filename, TEXT("WAV") ) ) )
return E_FAIL;
}
if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) )
return E_FAIL;
if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) )
return E_FAIL;
if( NULL == ( pvRes = LockResource( hResData ) ) )
return E_FAIL;
m_pResourceBuffer = new CHAR[ dwSize ];
memcpy( m_pResourceBuffer, pvRes, dwSize );
MMIOINFO mmioInfo;
ZeroMemory( &mmioInfo, sizeof(mmioInfo) );
mmioInfo.fccIOProc = FOURCC_MEM;
mmioInfo.cchBuffer = dwSize;
mmioInfo.pchBuffer = (CHAR *) m_pResourceBuffer;
m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ );
}
if( FAILED( hr = ReadMMIO() ) ) {
// ReadMMIO will fail if its an not a wave file
mmioClose( m_hmmio, 0 );
return hr;
}
if( FAILED( hr = ResetFile() ) )
return hr;
// After the reset, the size of the wav file is m_ck.cksize so store it now
m_dwSize = m_ck.cksize;
} else {
m_hmmio = mmioOpen( filename, NULL, MMIO_ALLOCBUF |
MMIO_READWRITE |
MMIO_CREATE );
if( NULL == m_hmmio )
return E_FAIL;
if( FAILED( hr = WriteMMIO( &wave_format_ ) ) ) {
mmioClose( m_hmmio, 0 );
return hr;
}
if( FAILED( hr = ResetFile() ) )
return hr;
}
return hr;
}
HRESULT CWaveFile::ReadMMIO()
{
MMCKINFO ckIn; // chunk info. for general use.
PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in.
m_pwfx = NULL;
if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) )
return E_FAIL;
// Check to make sure this is a valid wave file
if( (m_ckRiff.ckid != FOURCC_RIFF) ||
(m_ckRiff.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( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) )
return E_FAIL;
// Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
// 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 <pcmWaveFormat>.
if( mmioRead( m_hmmio, (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 ) {
m_pwfx = (WAVEFORMATEX *)new CHAR[ sizeof(WAVEFORMATEX) ];
if( NULL == m_pwfx )
return E_FAIL;
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
m_pwfx->cbSize = 0;
} else {
// Read in length of extra bytes.
WORD cbExtraBytes = 0L;
if( mmioRead( m_hmmio, (CHAR *)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) )
return E_FAIL;
m_pwfx = (WAVEFORMATEX *)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ];
if( NULL == m_pwfx )
return E_FAIL;
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
m_pwfx->cbSize = cbExtraBytes;
// Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
if( mmioRead( m_hmmio, (CHAR *)(((BYTE *) & (m_pwfx->cbSize)) + sizeof(WORD)),
cbExtraBytes ) != cbExtraBytes ) {
SAFE_DELETE( m_pwfx );
return E_FAIL;
}
}
// Ascend the input file out of the 'fmt ' chunk.
if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) {
SAFE_DELETE( m_pwfx );
return E_FAIL;
}
return S_OK;
}
HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest )
{
DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile.
MMCKINFO ckOut1;
dwFactChunk = (DWORD) - 1;
// Create the output file RIFF chunk of form type 'WAVE'.
m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E');
m_ckRiff.cksize = 0;
if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) )
return E_FAIL;
// We are now descended into the 'RIFF' chunk we just created.
// Now create the 'fmt ' chunk. Since we know the size of this chunk,
// specify it in the MMCKINFO structure so MMIO doesn't have to seek
// back and set the chunk size after ascending from the chunk.
m_ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
m_ck.cksize = sizeof(PCMWAVEFORMAT);
if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) )
return E_FAIL;
// Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type.
if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) {
if( mmioWrite( m_hmmio, (HPSTR) pwfxDest,
sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
return E_FAIL;
} else {
// Write the variable length size.
if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest,
sizeof(*pwfxDest) + pwfxDest->cbSize ) !=
( sizeof(*pwfxDest) + pwfxDest->cbSize ) )
return E_FAIL;
}
// Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk.
if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
return E_FAIL;
// Now create the fact chunk, not required for PCM but nice to have. This is filled
// in when the close routine is called.
ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't');
ckOut1.cksize = 0;
if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) )
return E_FAIL;
if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) !=
sizeof(dwFactChunk) )
return E_FAIL;
// Now ascend out of the fact chunk...
if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) )
return E_FAIL;
return S_OK;
}
DWORD CWaveFile::GetSize()
{
return m_dwSize;
}
HRESULT CWaveFile::ResetFile()
{
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( flag_ == WAVEFILE_READ ) {
// Seek to the data
if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET ) )
return 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 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 E_FAIL;
if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
return E_FAIL;
}
return S_OK;
}
#3
HRESULT CWaveFile::Read( BYTE *pBuffer, DWORD dwSizeToRead, DWORD *pdwSizeRead )
{
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 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 E_FAIL;
if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
return E_FAIL;
}
// Actual copy.
*((BYTE *)pBuffer + cT) = *((BYTE *)mmioinfoIn.pchNext);
mmioinfoIn.pchNext++;
}
if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) )
return E_FAIL;
if( pdwSizeRead != NULL )
*pdwSizeRead = cbDataIn;
return S_OK;
}
HRESULT CWaveFile::Close()
{
if( flag_ == WAVEFILE_READ ) {
mmioClose( m_hmmio, 0 );
m_hmmio = NULL;
SAFE_DELETE_ARRAY( m_pResourceBuffer );
} else {
m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
return E_FAIL;
// Ascend the output file out of the 'data' chunk -- this will cause
// the chunk size of the 'data' chunk to be written.
if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
return E_FAIL;
// Do this here instead...
if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
return E_FAIL;
mmioSeek( m_hmmio, 0, SEEK_SET );
if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) )
return E_FAIL;
m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't');
if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) {
DWORD dwSamples = 0;
mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) );
mmioAscend( m_hmmio, &m_ck, 0 );
}
// Ascend the output file out of the 'RIFF' chunk -- this will cause
// the chunk size of the 'RIFF' chunk to be written.
if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
return E_FAIL;
mmioClose( m_hmmio, 0 );
m_hmmio = NULL;
}
return S_OK;
}
HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE *pbSrcData, UINT *pnSizeWrote )
{
UINT cT;
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( pnSizeWrote == NULL || pbSrcData == NULL )
return E_INVALIDARG;
*pnSizeWrote = 0;
for( cT = 0; cT < nSizeToWrite; cT++ ) {
if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) {
m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) )
return E_FAIL;
}
*((BYTE *)m_mmioinfoOut.pchNext) = *((BYTE *)pbSrcData + cT);
(BYTE *)m_mmioinfoOut.pchNext++;
(*pnSizeWrote)++;
}
return S_OK;
}
#4
thanks.
#1
头文件:
[/code]
#ifndef CLASS_WAV_FILE_H_
#define CLASS_WAV_FILE_H_
#define WAVEFILE_READ 1
#define WAVEFILE_WRITE 2
#include <Windows.h>
#include <MMSystem.h>
#pragma comment(lib,"winmm.lib")
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 flag_;
BYTE* m_pbData;
BYTE* m_pbDataCur;
ULONG m_ulDataSize;
CHAR* m_pResourceBuffer;
WAVEFORMATEX wave_format_;
protected:
HRESULT ReadMMIO();
HRESULT WriteMMIO( WAVEFORMATEX *pwfxDest );
public:
CWaveFile();
~CWaveFile();
HRESULT Open(
LPTSTR filename,
DWORD flag,
UINT channels,
ULONG samples_per_sec,
UINT bits_per_sample);
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; };
};
#endif // ! CLASS_WAV_FILE_H_
[/code]
#2
cpp文件:
#include "stdafx.h"
#include "common-header.h"
#include "WavFile.h"
CWaveFile::CWaveFile()
{
m_pwfx = NULL;
m_hmmio = NULL;
m_pResourceBuffer = NULL;
m_dwSize = 0;
}
CWaveFile::~CWaveFile()
{
Close();
SAFE_DELETE_ARRAY( m_pwfx );
}
HRESULT CWaveFile::Open( LPTSTR filename, DWORD flag, UINT channels, ULONG samples_per_sec, UINT bits_per_sample )
{
wave_format_.cbSize = 0;
wave_format_.wFormatTag = WAVE_FORMAT_PCM;
wave_format_.nChannels = channels;
wave_format_.nSamplesPerSec = samples_per_sec;
wave_format_.wBitsPerSample = bits_per_sample;
wave_format_.nBlockAlign = wave_format_.nChannels * ( wave_format_.wBitsPerSample / 8 );
wave_format_.nAvgBytesPerSec = wave_format_.nBlockAlign * wave_format_.nSamplesPerSec;
HRESULT hr;
flag_ = flag;
if( flag_ == WAVEFILE_READ ) {
if( filename == NULL )
return E_INVALIDARG;
SAFE_DELETE_ARRAY( m_pwfx );
m_hmmio = mmioOpen( filename, NULL, MMIO_ALLOCBUF | MMIO_READ );
if( NULL == m_hmmio ) {
HRSRC hResInfo;
HGLOBAL hResData;
DWORD dwSize;
VOID *pvRes;
// Loading it as a file failed, so try it as a resource
if( NULL == ( hResInfo = FindResource( NULL, filename, TEXT("WAVE") ) ) ) {
if( NULL == ( hResInfo = FindResource( NULL, filename, TEXT("WAV") ) ) )
return E_FAIL;
}
if( NULL == ( hResData = LoadResource( NULL, hResInfo ) ) )
return E_FAIL;
if( 0 == ( dwSize = SizeofResource( NULL, hResInfo ) ) )
return E_FAIL;
if( NULL == ( pvRes = LockResource( hResData ) ) )
return E_FAIL;
m_pResourceBuffer = new CHAR[ dwSize ];
memcpy( m_pResourceBuffer, pvRes, dwSize );
MMIOINFO mmioInfo;
ZeroMemory( &mmioInfo, sizeof(mmioInfo) );
mmioInfo.fccIOProc = FOURCC_MEM;
mmioInfo.cchBuffer = dwSize;
mmioInfo.pchBuffer = (CHAR *) m_pResourceBuffer;
m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ );
}
if( FAILED( hr = ReadMMIO() ) ) {
// ReadMMIO will fail if its an not a wave file
mmioClose( m_hmmio, 0 );
return hr;
}
if( FAILED( hr = ResetFile() ) )
return hr;
// After the reset, the size of the wav file is m_ck.cksize so store it now
m_dwSize = m_ck.cksize;
} else {
m_hmmio = mmioOpen( filename, NULL, MMIO_ALLOCBUF |
MMIO_READWRITE |
MMIO_CREATE );
if( NULL == m_hmmio )
return E_FAIL;
if( FAILED( hr = WriteMMIO( &wave_format_ ) ) ) {
mmioClose( m_hmmio, 0 );
return hr;
}
if( FAILED( hr = ResetFile() ) )
return hr;
}
return hr;
}
HRESULT CWaveFile::ReadMMIO()
{
MMCKINFO ckIn; // chunk info. for general use.
PCMWAVEFORMAT pcmWaveFormat; // Temp PCM structure to load in.
m_pwfx = NULL;
if( ( 0 != mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) ) )
return E_FAIL;
// Check to make sure this is a valid wave file
if( (m_ckRiff.ckid != FOURCC_RIFF) ||
(m_ckRiff.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( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) )
return E_FAIL;
// Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
// 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 <pcmWaveFormat>.
if( mmioRead( m_hmmio, (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 ) {
m_pwfx = (WAVEFORMATEX *)new CHAR[ sizeof(WAVEFORMATEX) ];
if( NULL == m_pwfx )
return E_FAIL;
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
m_pwfx->cbSize = 0;
} else {
// Read in length of extra bytes.
WORD cbExtraBytes = 0L;
if( mmioRead( m_hmmio, (CHAR *)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) )
return E_FAIL;
m_pwfx = (WAVEFORMATEX *)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ];
if( NULL == m_pwfx )
return E_FAIL;
// Copy the bytes from the pcm structure to the waveformatex structure
memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) );
m_pwfx->cbSize = cbExtraBytes;
// Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
if( mmioRead( m_hmmio, (CHAR *)(((BYTE *) & (m_pwfx->cbSize)) + sizeof(WORD)),
cbExtraBytes ) != cbExtraBytes ) {
SAFE_DELETE( m_pwfx );
return E_FAIL;
}
}
// Ascend the input file out of the 'fmt ' chunk.
if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) {
SAFE_DELETE( m_pwfx );
return E_FAIL;
}
return S_OK;
}
HRESULT CWaveFile::WriteMMIO( WAVEFORMATEX *pwfxDest )
{
DWORD dwFactChunk; // Contains the actual fact chunk. Garbage until WaveCloseWriteFile.
MMCKINFO ckOut1;
dwFactChunk = (DWORD) - 1;
// Create the output file RIFF chunk of form type 'WAVE'.
m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E');
m_ckRiff.cksize = 0;
if( 0 != mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) )
return E_FAIL;
// We are now descended into the 'RIFF' chunk we just created.
// Now create the 'fmt ' chunk. Since we know the size of this chunk,
// specify it in the MMCKINFO structure so MMIO doesn't have to seek
// back and set the chunk size after ascending from the chunk.
m_ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
m_ck.cksize = sizeof(PCMWAVEFORMAT);
if( 0 != mmioCreateChunk( m_hmmio, &m_ck, 0 ) )
return E_FAIL;
// Write the PCMWAVEFORMAT structure to the 'fmt ' chunk if its that type.
if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) {
if( mmioWrite( m_hmmio, (HPSTR) pwfxDest,
sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
return E_FAIL;
} else {
// Write the variable length size.
if( (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest,
sizeof(*pwfxDest) + pwfxDest->cbSize ) !=
( sizeof(*pwfxDest) + pwfxDest->cbSize ) )
return E_FAIL;
}
// Ascend out of the 'fmt ' chunk, back into the 'RIFF' chunk.
if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
return E_FAIL;
// Now create the fact chunk, not required for PCM but nice to have. This is filled
// in when the close routine is called.
ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't');
ckOut1.cksize = 0;
if( 0 != mmioCreateChunk( m_hmmio, &ckOut1, 0 ) )
return E_FAIL;
if( mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)) !=
sizeof(dwFactChunk) )
return E_FAIL;
// Now ascend out of the fact chunk...
if( 0 != mmioAscend( m_hmmio, &ckOut1, 0 ) )
return E_FAIL;
return S_OK;
}
DWORD CWaveFile::GetSize()
{
return m_dwSize;
}
HRESULT CWaveFile::ResetFile()
{
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( flag_ == WAVEFILE_READ ) {
// Seek to the data
if( -1 == mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET ) )
return 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 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 E_FAIL;
if( 0 != mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
return E_FAIL;
}
return S_OK;
}
#3
HRESULT CWaveFile::Read( BYTE *pBuffer, DWORD dwSizeToRead, DWORD *pdwSizeRead )
{
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 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 E_FAIL;
if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
return E_FAIL;
}
// Actual copy.
*((BYTE *)pBuffer + cT) = *((BYTE *)mmioinfoIn.pchNext);
mmioinfoIn.pchNext++;
}
if( 0 != mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ) )
return E_FAIL;
if( pdwSizeRead != NULL )
*pdwSizeRead = cbDataIn;
return S_OK;
}
HRESULT CWaveFile::Close()
{
if( flag_ == WAVEFILE_READ ) {
mmioClose( m_hmmio, 0 );
m_hmmio = NULL;
SAFE_DELETE_ARRAY( m_pResourceBuffer );
} else {
m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( 0 != mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ) )
return E_FAIL;
// Ascend the output file out of the 'data' chunk -- this will cause
// the chunk size of the 'data' chunk to be written.
if( 0 != mmioAscend( m_hmmio, &m_ck, 0 ) )
return E_FAIL;
// Do this here instead...
if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
return E_FAIL;
mmioSeek( m_hmmio, 0, SEEK_SET );
if( 0 != (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ) )
return E_FAIL;
m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't');
if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) {
DWORD dwSamples = 0;
mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) );
mmioAscend( m_hmmio, &m_ck, 0 );
}
// Ascend the output file out of the 'RIFF' chunk -- this will cause
// the chunk size of the 'RIFF' chunk to be written.
if( 0 != mmioAscend( m_hmmio, &m_ckRiff, 0 ) )
return E_FAIL;
mmioClose( m_hmmio, 0 );
m_hmmio = NULL;
}
return S_OK;
}
HRESULT CWaveFile::Write( UINT nSizeToWrite, BYTE *pbSrcData, UINT *pnSizeWrote )
{
UINT cT;
if( m_hmmio == NULL )
return CO_E_NOTINITIALIZED;
if( pnSizeWrote == NULL || pbSrcData == NULL )
return E_INVALIDARG;
*pnSizeWrote = 0;
for( cT = 0; cT < nSizeToWrite; cT++ ) {
if( m_mmioinfoOut.pchNext == m_mmioinfoOut.pchEndWrite ) {
m_mmioinfoOut.dwFlags |= MMIO_DIRTY;
if( 0 != mmioAdvance( m_hmmio, &m_mmioinfoOut, MMIO_WRITE ) )
return E_FAIL;
}
*((BYTE *)m_mmioinfoOut.pchNext) = *((BYTE *)pbSrcData + cT);
(BYTE *)m_mmioinfoOut.pchNext++;
(*pnSizeWrote)++;
}
return S_OK;
}
#4
thanks.