www.pudn.com > AudioCodec.rar > WaveFile.cpp


// WaveFile.cpp: implementation of the CWaveFile class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "WaveFile.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CWaveFile::CWaveFile() 
{ 
	m_pWaveFormat = NULL; 
	m_iDataSize = 0; 
} 
 
CWaveFile::~CWaveFile() 
{ 
 
} 
 
//iMode could be: MMIO_READ, MMIO_WRITE, MMIO_CREATE     
 
BOOL CWaveFile::Open(CString strFileName, int iMode) 
{ 
	char szFileName[256]; 
 
	lstrcpy(szFileName, strFileName); 
	m_iMode = iMode; 
	if (m_iMode == MMIO_READ) 
	{ 
		if(!(m_hMmio = mmioOpen(szFileName, NULL, m_iMode|MMIO_ALLOCBUF)))  
		{  
			OutputDebugString("Failed to open file.");  
			return FALSE; 
		} 
		if (!ReadChunk())	return FALSE; 
	} 
	else if (m_iMode == MMIO_WRITE || m_iMode == (MMIO_WRITE|MMIO_CREATE)) 
	{ 
		if(!(m_hMmio = mmioOpen(szFileName, NULL, m_iMode|MMIO_ALLOCBUF)))  
		{  
			OutputDebugString("Failed to open file.");  
			return FALSE; 
		} 
	} 
	else 
	{ 
		OutputDebugString("Invalid mode\n"); 
		return FALSE; 
	} 
	return TRUE; 
} 
 
void CWaveFile::Close() 
{ 
	if (m_iMode == MMIO_WRITE || m_iMode == (MMIO_WRITE|MMIO_CREATE)) 
	{ 
		m_mmckinfoSubchunk.dwFlags = MMIO_DIRTY;  
		if (mmioAscend(m_hMmio, &m_mmckinfoSubchunk, 0) != 0) 
		{ 
			OutputDebugString("Ascend out of 'data' chunk failed!\n"); 
			goto Error; 
		} 
		m_mmckinfoParent.dwFlags = MMIO_DIRTY;  
		if (mmioAscend(m_hMmio, &m_mmckinfoParent, 0) != 0) 
		{ 
			OutputDebugString("Ascend out of 'RIFF' chunk failed!\n"); 
			goto Error; 
		} 
	} 
Error: 
	if (mmioClose(m_hMmio, 0) != 0) 
		OutputDebugString(" Wave file close error!"); 
	if (m_pWaveFormat != NULL) 
	{ 
		free(m_pWaveFormat); 
		m_pWaveFormat = NULL; 
	} 
} 
 
 
int CWaveFile::Read(unsigned char * pData, int iLength) 
{ 
    return mmioRead(m_hMmio, (HPSTR) pData, iLength); 
} 
 
BOOL CWaveFile::Write(unsigned char * pData, int iLength) 
{ 
	if (mmioWrite(m_hMmio, (HPSTR) pData, iLength) != iLength) 
	{ 
		OutputDebugString("Write Error!\n"); 
		goto Error; 
	} 
	return TRUE; 
 
Error: 
	Close(); 
	return FALSE; 
} 
 
BOOL CWaveFile::SetFormat(int iType) 
{ 
	int iFormatSize = sizeof(WAVEFORMATEX); 
	char *cbExtra; 
	 
	m_pWaveFormat = (WAVEFORMATEX *)malloc(256); 
	memset(m_pWaveFormat, 0, 256); 
	cbExtra = (char *)(m_pWaveFormat) + sizeof(WAVEFORMATEX); 
 
	m_pWaveFormat->nChannels = 1; 
	m_pWaveFormat->nSamplesPerSec = 8000; 
	switch (iType) 
	{ 
	case WAVE_FILE_PCM: 
		m_pWaveFormat->wFormatTag = WAVE_FORMAT_PCM; 
		m_pWaveFormat->nAvgBytesPerSec = 16000; 
		m_pWaveFormat->nBlockAlign = 2; 
		m_pWaveFormat->wBitsPerSample = 16; 
		m_pWaveFormat->cbSize = 0; 
 
	case WAVE_FILE_ALAW: 
		m_pWaveFormat->wFormatTag = WAVE_FORMAT_ALAW; 
		m_pWaveFormat->nAvgBytesPerSec = 8000; 
		m_pWaveFormat->nBlockAlign = 1; 
		m_pWaveFormat->wBitsPerSample = 8; 
		m_pWaveFormat->cbSize = 0; 
		break; 
 
	case WAVE_FILE_MULAW: 
		m_pWaveFormat->wFormatTag = WAVE_FORMAT_MULAW; 
		m_pWaveFormat->nAvgBytesPerSec = 8000; 
		m_pWaveFormat->nBlockAlign = 1; 
		m_pWaveFormat->wBitsPerSample = 8; 
		m_pWaveFormat->cbSize = 0; 
		break; 
 
	case WAVE_FILE_ADPCM: 
		m_pWaveFormat->wFormatTag = WAVE_FORMAT_ADPCM; 
		m_pWaveFormat->nAvgBytesPerSec = 4096; 
		m_pWaveFormat->nBlockAlign = 256; 
		m_pWaveFormat->wBitsPerSample = 4; 
		m_pWaveFormat->cbSize = 32; 
		cbExtra[0] = -12;	cbExtra[1] = 1;		cbExtra[2] = 7; 
		cbExtra[5] = 1;		cbExtra[9] = 2;		cbExtra[11] = -1; 
		cbExtra[16] = -64;	cbExtra[18] = 64;	cbExtra[20] = -16; 
		cbExtra[24] = -52;	cbExtra[25] = 1;	cbExtra[26] = 48; 
		cbExtra[27] = -1;	cbExtra[28] = -120;	cbExtra[29] = 1; 
		cbExtra[30] = 24;	cbExtra[31] = -1; 
		break; 
 
	case WAVE_FILE_GSM610: 
		m_pWaveFormat->wFormatTag = WAVE_FORMAT_GSM610; 
		m_pWaveFormat->nAvgBytesPerSec = 1625; 
		m_pWaveFormat->nBlockAlign = 65; 
		m_pWaveFormat->wBitsPerSample = 0; 
		m_pWaveFormat->cbSize = 2; 
		cbExtra[0] = 64; 
		cbExtra[1] = 1; 
		break; 
 
	case WAVE_FILE_G729: 
		m_pWaveFormat->wFormatTag = WAVE_FORMAT_GFDVR; 
		m_pWaveFormat->nAvgBytesPerSec = 1100; 
		m_pWaveFormat->nBlockAlign = 11; 
		m_pWaveFormat->wBitsPerSample = 0; 
		m_pWaveFormat->cbSize = 0; 
		break; 
 
	case WAVE_FILE_G723_1: 
		m_pWaveFormat->wFormatTag = 66; 
		m_pWaveFormat->nChannels = 1; 
		m_pWaveFormat->nSamplesPerSec = 8000; 
		m_pWaveFormat->nAvgBytesPerSec = 800; 
		m_pWaveFormat->nBlockAlign = 24; 
		m_pWaveFormat->wBitsPerSample = 0; 
		m_pWaveFormat->cbSize = 10; 
 
		cbExtra[0] = 2; cbExtra[1] = 0; cbExtra[2] = (char)0xce; 
		cbExtra[3] = (char)0x9a; cbExtra[4] = (char)0x32; cbExtra[5] = (char)0xf7; 
		cbExtra[6] = (char)0xa2; cbExtra[7] = (char)0xae; cbExtra[8] = (char)0xde; 
		cbExtra[9] = (char)0xac; 
		break; 
 
	default: 
		OutputDebugString("format not supported!\n"); 
		break; 
	} 
 
	iFormatSize += m_pWaveFormat->cbSize; 
 
	if (!WriteChunk(iFormatSize))	return FALSE; 
	else				return TRUE; 
} 
 
BOOL CWaveFile::SetFormat(WAVEFORMATEX * pFormat, int iFormatSize) 
{ 
	m_pWaveFormat = (WAVEFORMATEX *)malloc(iFormatSize); 
	memcpy(m_pWaveFormat, pFormat, iFormatSize); 
	 
	if (!WriteChunk(iFormatSize))	return FALSE; 
	else				return TRUE; 
} 
 
BOOL CWaveFile::ReadChunk() 
{ 
    // Locate a "RIFF" chunk with a "WAVE" form type to make  
    // sure the file is a waveform-audio file.  
    m_mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');  
    if (mmioDescend(m_hMmio, (LPMMCKINFO) &m_mmckinfoParent, NULL, MMIO_FINDRIFF))  
    {  
        OutputDebugString("This is not a waveform-audio file.");  
		goto Error; 
    }  
    // Find the "FMT" chunk (form type "FMT"); it must be  
    // a subchunk of the "RIFF" chunk.  
    m_mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' ');  
    if (mmioDescend(m_hMmio, &m_mmckinfoSubchunk, &m_mmckinfoParent, MMIO_FINDCHUNK))  
    {  
		OutputDebugString("Waveform-audio file has no FMT chunk.\n");  
		goto Error; 
    }  
 
    // Get the size of the "FMT" chunk. Allocate  
    // and lock memory for it.  
	m_dwFormatSize = m_mmckinfoSubchunk.cksize;  
	m_pWaveFormat = (WAVEFORMATEX *)malloc(m_dwFormatSize); 
    // Read the "FMT" chunk.  
	if (mmioRead(m_hMmio, (HPSTR) m_pWaveFormat, m_dwFormatSize) != (int)m_dwFormatSize) 
	{  
		OutputDebugString("Failed to read format chunk.");  
		goto Error; 
    }  
  
    // Ascend out of the "FMT" subchunk.  
    mmioAscend(m_hMmio, &m_mmckinfoSubchunk, 0);  
  
    // Find the data subchunk. The current file position should be at  
    // the beginning of the data chunk; however, you should not make  
    // this assumption. Use mmioDescend to locate the data chunk.  
    m_mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a');  
    if (mmioDescend(m_hMmio, &m_mmckinfoSubchunk, &m_mmckinfoParent, MMIO_FINDCHUNK))  
    {  
		OutputDebugString("Waveform-audio file has no data chunk.");  
		goto Error; 
    }  
  
    // Get the size of the data subchunk.  
    m_iDataSize = m_mmckinfoSubchunk.cksize;  
    if (m_iDataSize == 0L) 
	{  
        OutputDebugString("The data chunk contains no data.");  
		goto Error; 
    }  
	return TRUE; 
 
Error: 
	Close(); 
	return FALSE; 
} 
 
BOOL CWaveFile::WriteChunk(int iFormatSize) 
{ 
	m_mmckinfoParent.fccType = mmioFOURCC('W', 'A', 'V', 'E');  
	m_mmckinfoParent.cksize = 0; 
	if (mmioCreateChunk(m_hMmio, &m_mmckinfoParent, MMIO_CREATERIFF)) 
	{ 
		OutputDebugString("Create RIFF chunk failed!\n"); 
		goto Error; 
	} 
 
	m_mmckinfoSubchunk.ckid = mmioFOURCC('f', 'm', 't', ' '); 
	m_mmckinfoSubchunk.cksize = iFormatSize;		// we know the size of this ck. 
	if (mmioCreateChunk(m_hMmio, &m_mmckinfoSubchunk, 0)) 
	{ 
		OutputDebugString("Create 'fmt' chunk failed!\n"); 
		goto Error; 
	} 
	if (mmioWrite(m_hMmio, (HPSTR) m_pWaveFormat, iFormatSize) != iFormatSize) 
	{ 
		OutputDebugString("Write Format data failed!\n"); 
		goto Error; 
	} 
	// ascend out of the 'fmt' chunk, back into 'RIFF' chunk  
	if (mmioAscend(m_hMmio, &m_mmckinfoSubchunk, 0) != 0) 
	{ 
		OutputDebugString("Ascend out of 'fmt' chunk failed!\n"); 
		goto Error; 
	} 
	// create the 'data' chunk that holds the waveform samples  
	m_mmckinfoSubchunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); 
	m_mmckinfoSubchunk.cksize = 0; 
	if (mmioCreateChunk(m_hMmio, &m_mmckinfoSubchunk, 0) != 0) 
	{ 
		OutputDebugString("Create 'data' chunk failed!\n"); 
		goto Error; 
	} 
	return TRUE; 
 
Error: 
	Close(); 
	return FALSE; 
}