📄 wavreader.cpp
字号:
// WAVReader.cpp: implementation of the WAVReader class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "URLMon.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
WAVReader::WAVReader()
{
// Init data members
m_pwfmt = NULL;
m_hmmio = NULL;
m_nBlockAlign= 0;
m_nAvgDataRate = 0;
m_InDataSize = 0;
m_OutDataSize = 0;
m_nBytesPlayed = 0;
memset (&m_mmckiRiff, 0, sizeof (MMCKINFO));
memset (&m_mmckiFmt, 0, sizeof (MMCKINFO));
memset (&m_mmckiData, 0, sizeof (MMCKINFO));
m_Buffer = NULL;
m_BufferSize = 0;
m_BufferDataRead = 0;
m_InDataCursor = 0;
m_IsPcm = FALSE;
m_pHas = NULL;
ZeroMemory(&m_Ash,sizeof(m_Ash));
m_SubFileMem = NULL;
}
WAVReader::~WAVReader()
{
// Close file
if (m_hmmio)
mmioClose (m_hmmio, 0);
if (!m_IsPcm)
{
if(m_pHas)
acmStreamUnprepareHeader(m_pHas, &m_Ash, 0);
delete [] m_Ash.pbDst;
delete [] m_Ash.pbSrc;
if(m_pHas)
acmStreamClose( m_pHas, 0);
}
else
delete [] m_Buffer;
if (m_pwfmt)
GlobalFree (m_pwfmt);
}
CKERROR WAVReader::ReadMemory(void* memory, int size) {
if(!memory || !size)
return -1;
BOOL fRtn = CK_OK; // assume success
MMIOINFO mminfo;
memset(&mminfo,0,sizeof(MMIOINFO));
mminfo.pchBuffer = (char*) memory;
mminfo.cchBuffer = size;
mminfo.fccIOProc = FOURCC_MEM;
// Open the requested file
if ((m_hmmio = mmioOpen(NULL, &mminfo, MMIO_ALLOCBUF | MMIO_READ)) == NULL)
{
m_mmr = MMIOERR_CANNOTOPEN;
goto OPEN_ERROR;
}
return DoMMio();
OPEN_ERROR:
// Handle all errors here
fRtn = -1;
if (m_hmmio)
{
// Close file
mmioClose (m_hmmio, 0);
m_hmmio = NULL;
}
if (m_pwfmt)
{
// UNDONE: Change here if using malloc
// Free memory
GlobalFree (m_pwfmt);
m_pwfmt = NULL;
}
return -1;
}
// Opens a file
CKERROR WAVReader::OpenFile(char *file)
{
WORD cbExtra = 0;
BOOL fRtn = CK_OK; // assume success
char* CacheName= file;
/* [MAX_PATH];
if(VxURLDownloadToCacheFile(NULL,file,CacheName,_MAX_PATH,0,&wavbsc) != S_OK)
return -1;
*/
if (!CacheName) return -1;
if(strlen(CacheName) == 0)
return -1;
// Open the requested file
if ((m_hmmio = mmioOpen (CacheName, NULL, MMIO_ALLOCBUF | MMIO_READ)) == NULL)
{
m_mmr = MMIOERR_CANNOTOPEN;
goto OPEN_ERROR;
}
return DoMMio();
OPEN_ERROR:
// Handle all errors here
fRtn = -1;
if (m_hmmio)
{
// Close file
mmioClose (m_hmmio, 0);
m_hmmio = NULL;
}
if (m_pwfmt)
{
// UNDONE: Change here if using malloc
// Free memory
GlobalFree (m_pwfmt);
m_pwfmt = NULL;
}
return -1;
}
CKERROR WAVReader::DoMMio(){
WORD cbExtra = 0;
BOOL fRtn = CK_OK; // assume success
// Descend into initial chunk ('RIFF')
if (m_mmr = mmioDescend (m_hmmio, &m_mmckiRiff, NULL, 0))
{
goto OPEN_ERROR;
}
// Validate that it's a WAVE file
if ((m_mmckiRiff.ckid != FOURCC_RIFF) || (m_mmckiRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
{
m_mmr = MMIOERR_INVALIDFILE;
goto OPEN_ERROR;
}
// Find format chunk ('fmt '), allocate and fill WAVEFORMATEX structure
m_mmckiFmt.ckid = mmioFOURCC('f', 'm', 't', ' ');
if (m_mmr = mmioDescend (m_hmmio, &m_mmckiFmt, &m_mmckiRiff, MMIO_FINDCHUNK))
{
goto OPEN_ERROR;
}
// Read the format chunk into temporary structure
PCMWAVEFORMAT pcmwf;
if (mmioRead (m_hmmio, (CHAR *) &pcmwf, sizeof(PCMWAVEFORMAT)) != sizeof(PCMWAVEFORMAT))
{
m_mmr = MMIOERR_CANNOTREAD;
goto OPEN_ERROR;
}
// If format is not PCM, then there are extra bytes appended to WAVEFORMATEX
if (pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM)
{
// Read WORD specifying number of extra bytes
if (mmioRead (m_hmmio, (LPSTR) &cbExtra, sizeof (cbExtra)) != sizeof(cbExtra))
{
m_mmr = MMIOERR_CANNOTREAD;
goto OPEN_ERROR;
}
}
// Allocate memory for WAVEFORMATEX structure + extra bytes
// UNDONE: GMEM_FIXED???? use malloc?
if (m_pwfmt = (WAVEFORMATEX *) GlobalAlloc (GMEM_FIXED, sizeof(WAVEFORMATEX)+cbExtra))
{
// Copy bytes from temporary format structure
memcpy (m_pwfmt, &pcmwf, sizeof(pcmwf));
m_pwfmt->cbSize = cbExtra;
// Read those extra bytes, append to WAVEFORMATEX structure
if (cbExtra != 0)
{
if ((m_mmr = mmioRead (m_hmmio, (LPSTR) ((BYTE *)(m_pwfmt) + sizeof (WAVEFORMATEX)), cbExtra)) != cbExtra)
{
// Error reading extra bytes
m_mmr = MMIOERR_CANNOTREAD;
goto OPEN_ERROR;
}
}
}
else
{
// Error allocating memory
m_mmr = MMIOERR_OUTOFMEMORY;
goto OPEN_ERROR;
}
// Init some member data from format chunk
m_nBlockAlign = m_pwfmt->nBlockAlign;
m_nAvgDataRate = m_pwfmt->nAvgBytesPerSec;
// Ascend out of format chunk
if (m_mmr = mmioAscend (m_hmmio, &m_mmckiFmt, 0))
{
goto OPEN_ERROR;
}
// Cue for streaming
Cue();
// Init some member data from data chunk
m_InDataSize = m_mmckiData.cksize;
// Successful open!
goto OPEN_DONE;
OPEN_ERROR:
// Handle all errors here
fRtn = -1;
if (m_hmmio)
{
// Close file
mmioClose (m_hmmio, 0);
m_hmmio = NULL;
}
if (m_pwfmt)
{
// UNDONE: Change here if using malloc
// Free memory
GlobalFree (m_pwfmt);
m_pwfmt = NULL;
}
return -1;
OPEN_DONE:
// Create Decode Buffer
m_IsPcm = (m_pwfmt->wFormatTag == WAVE_FORMAT_PCM);
if(m_IsPcm)
{
m_BufferSize = min(m_pwfmt->nAvgBytesPerSec / 8, m_InDataSize);
m_Buffer = new BYTE[m_BufferSize ];
m_Wfe = *m_pwfmt;
m_OutDataSize = m_InDataSize; // Equal if PCM
}
else
{
m_Wfe.cbSize = 0;
m_Wfe.wFormatTag = WAVE_FORMAT_PCM;
m_Wfe.nChannels = m_pwfmt->nChannels;
m_Wfe.nSamplesPerSec = m_pwfmt->nSamplesPerSec;
m_Wfe.wBitsPerSample = 16;
m_Wfe.nBlockAlign = m_Wfe.nChannels * m_Wfe.wBitsPerSample / 8;
m_Wfe.nAvgBytesPerSec = m_Wfe.nSamplesPerSec * m_Wfe.nBlockAlign;
HRESULT res = acmStreamOpen( &m_pHas, NULL, m_pwfmt, &m_Wfe, NULL, NULL, NULL,ACM_STREAMOPENF_NONREALTIME);
if (!res)
{
unsigned long outsize,insize = m_pwfmt->nAvgBytesPerSec;
acmStreamSize(m_pHas, insize, &outsize, ACM_STREAMSIZEF_SOURCE);
LPBYTE inbuf=new BYTE[insize];
LPBYTE outbuf=new BYTE[outsize];
m_Ash.cbStruct= sizeof(ACMSTREAMHEADER);
m_Ash.fdwStatus= 0;
m_Ash.dwUser= 0;
m_Ash.pbSrc= inbuf;
m_Ash.cbSrcLength= insize;
m_Ash.cbSrcLengthUsed= 0;
m_Ash.dwSrcUser= insize;
m_Ash.pbDst= outbuf;
m_Ash.cbDstLength= outsize;
m_Ash.cbDstLengthUsed= 0;
m_Ash.dwDstUser= outsize;
res=acmStreamPrepareHeader( m_pHas, &m_Ash, 0);
if (res==0)
acmStreamSize(m_pHas, m_InDataSize, &m_OutDataSize, ACM_STREAMSIZEF_SOURCE);
else return -1;
} else return -1;
}
return CK_OK;
}
// Decodes next chunk of data, use get data buffer to get decoded data
CKERROR WAVReader::Decode()
{
if(m_IsPcm)
{
m_BufferDataRead = ReadPCM(m_Buffer,m_BufferSize);
if(m_BufferDataRead > 0)
return CK_OK;
else
return CKSOUND_READER_EOF;
}
else
{
MMRESULT res = -1;
if(m_InDataCursor >= m_InDataSize)
return CKSOUND_READER_EOF;
if(m_InDataCursor == 0)
{
m_Ash.cbSrcLength = DataRead(0, m_Ash.dwSrcUser, (char*)m_Ash.pbSrc);
m_Ash.cbDstLengthUsed = 0;
res = acmStreamConvert( m_pHas, &m_Ash, ACM_STREAMCONVERTF_START|ACM_STREAMCONVERTF_BLOCKALIGN);
if(!m_Ash.cbSrcLengthUsed)
res = acmStreamConvert( m_pHas, &m_Ash, ACM_STREAMCONVERTF_START);
}
else
{
m_Ash.cbSrcLength = DataRead(m_InDataCursor, m_Ash.dwSrcUser, (char*)m_Ash.pbSrc);;
m_Ash.cbDstLengthUsed = 0;
res = acmStreamConvert( m_pHas, &m_Ash,ACM_STREAMCONVERTF_BLOCKALIGN );
if(!m_Ash.cbSrcLengthUsed)
res = acmStreamConvert( m_pHas, &m_Ash,ACM_STREAMCONVERTF_END);
}
switch(res)
{
case 0:
{
m_InDataCursor += m_Ash.cbSrcLengthUsed;// ? m_Ash.cbSrcLengthUsed : m_Ash.cbSrcLength;
return CK_OK;
}
break;
}
}
return CKSOUND_READER_GENERICERR;
}
int WAVReader::DataRead(int count, char* buf)
{
int r=mmioRead(m_hmmio,(HPSTR) buf, count);
return r;
}
int WAVReader::DataRead(long pos, int count, char* buf) {
return (DataSeek(pos)!=-1) ? DataRead(count, buf) : -1;
}
int WAVReader::DataSeek(long pos) {
int p=-1;
MMRESULT error = mmioAscend(m_hmmio, &m_mmckiFmt,0);
if (error!=0)
return -1;
m_mmckiData.ckid = mmioFOURCC('d','a','t','a');
error=mmioDescend(m_hmmio, &m_mmckiData, &m_mmckiRiff, MMIO_FINDCHUNK);
if (error!=0)
return -1;
p=mmioSeek(m_hmmio,pos,SEEK_CUR);
if (p==-1)
return -1;
return p;
}
// Gets the last decoded buffer
CKERROR WAVReader::GetDataBuffer(BYTE **buf, int *size)
{
if(m_IsPcm)
{
*buf = m_Buffer;
*size = (int) m_BufferDataRead;
}
else
{
*buf = m_Ash.pbDst;
*size = m_Ash.cbDstLengthUsed;
}
return CK_OK;
}
// Gets the wave format of decoded datas
CKERROR WAVReader::GetWaveFormat(CKWaveFormat *wfe)
{
memcpy(wfe,&m_Wfe,sizeof(CKWaveFormat));
return CK_OK;
}
// Gets whole decoded data size
int WAVReader::GetDataSize()
{
return (int) m_OutDataSize;
}
// Gets the play time length
int WAVReader::GetDuration()
{
return (int)(((float)m_OutDataSize * 1000.0f ) / (float)m_Wfe.nAvgBytesPerSec);
}
CKERROR WAVReader::Seek(int pos)
{
int p=-1;
MMRESULT error = mmioAscend(m_hmmio, &m_mmckiFmt,0);
if (error!=0)
return -1;
m_mmckiData.ckid = mmioFOURCC('d','a','t','a');
error=mmioDescend(m_hmmio, &m_mmckiData, &m_mmckiRiff, MMIO_FINDCHUNK);
if (error!=0)
return -1;
p=mmioSeek(m_hmmio,pos,SEEK_CUR);
if (p==-1)
return CKSOUND_READER_GENERICERR;
if(pos == 0)
m_InDataCursor = 0;
else
m_InDataCursor = p;
return CK_OK;
}
// Play
CKERROR WAVReader::Play()
{
return CK_OK;
}
// Stop
CKERROR WAVReader::Stop()
{
return CK_OK;
}
// Cue
//
BOOL WAVReader::Cue (void)
{
BOOL fRtn = CK_OK; // assume success
// Seek to 'data' chunk from beginning of file
if (mmioSeek (m_hmmio, m_mmckiRiff.dwDataOffset + sizeof(FOURCC), SEEK_SET) != -1)
{
// Descend into 'data' chunk
m_mmckiData.ckid = mmioFOURCC('d', 'a', 't', 'a');
if ((m_mmr = mmioDescend (m_hmmio, &m_mmckiData, &m_mmckiRiff, MMIO_FINDCHUNK)) == MMSYSERR_NOERROR)
{
// Reset byte counter
m_nBytesPlayed = 0;
}
else
{
// UNDONE: set m_mmr
fRtn = -1;
}
}
else
{
// mmioSeek error
m_mmr = MMIOERR_CANNOTSEEK;
fRtn = -1;
}
return fRtn;
}
// Read
//
// Returns number of bytes actually read.
// On error, returns 0, MMIO error code in m_mmr.
//
UINT WAVReader::ReadPCM(BYTE * pbDest, UINT cbSize)
{
MMIOINFO mmioinfo;
UINT cb;
// Use direct buffer access for reads to maximize performance
if (m_mmr = mmioGetInfo (m_hmmio, &mmioinfo, 0))
{
goto READ_ERROR;
}
// Limit read size to chunk size
cbSize = (cbSize > m_mmckiData.cksize) ? m_mmckiData.cksize : cbSize;
// Adjust chunk size
m_mmckiData.cksize -= cbSize;
// Copy bytes from MMIO buffer
for (cb = 0; cb < cbSize; cb++)
{
// Advance buffer if necessary
if (mmioinfo.pchNext == mmioinfo.pchEndRead)
{
if (m_mmr = mmioAdvance (m_hmmio, &mmioinfo, MMIO_READ))
{
goto READ_ERROR;
}
if (mmioinfo.pchNext == mmioinfo.pchEndRead)
{
m_mmr = MMIOERR_CANNOTREAD;
goto READ_ERROR;
}
}
// Actual copy
// *((BYTE*)pbDest+cb) = *((BYTE*)mmioinfo.pchNext)++;
*(pbDest+cb) = *(mmioinfo.pchNext)++;
}
// End direct buffer access
if (m_mmr = mmioSetInfo (m_hmmio, &mmioinfo, 0))
{
goto READ_ERROR;
}
// Successful read, keep running total of number of data bytes read
m_nBytesPlayed += cbSize;
goto READ_DONE;
READ_ERROR:
cbSize = 0;
READ_DONE:
return (cbSize);
}
void WAVReader::Release()
{
delete this;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -