⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wavreader.cpp

📁 wav文件读取插件
💻 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 + -