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


// AcmCodec.cpp: implementation of the CAcmCodec class. 
// 
////////////////////////////////////////////////////////////////////// 
 
 
 
#include "stdafx.h" 
#include "AcmCodec.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CAcmCodec::CAcmCodec() 
{ 
	m_pwfxCode = NULL; 
	m_dwDstLength = 0; 
	m_dwSrcLength = 0; 
	m_bPass = FALSE; 
	m_iRawSampleRate = 8000; 
	m_iRawChannels = 1; 
} 
 
CAcmCodec::~CAcmCodec() 
{ 
 
} 
 
BOOL CAcmCodec::Init(int iType, BOOL bEncode) 
{ 
	if (iType == ACM_CODEC_PASS) 
	{ 
		m_bPass = TRUE; 
		return TRUE; 
	} 
	 
	m_bPass = FALSE; 
	int iSize = GetMaxFormatSize(); 
	m_pwfxCode = (WAVEFORMATEX *)malloc(iSize); 
	if (m_pwfxCode == NULL)		goto Error; 
	memset(m_pwfxCode, 0, iSize); 
	 
	if (SetFormat(iType) == FALSE)		goto Error; 
 
	if (OpenStream(bEncode) == FALSE)	goto Error; 
 
	return TRUE; 
 
Error: 
	Free(); 
	return FALSE; 
} 
 
BOOL CAcmCodec::Init(WAVEFORMATEX * pWfx, int iFormatSize, BOOL bEncode) 
{ 
	if (!NeedConvert(pWfx)) 
	{ 
		m_bPass = TRUE; 
		return TRUE; 
	} 
	m_bPass = FALSE; 
	m_pwfxCode = (WAVEFORMATEX *)malloc(iFormatSize); 
	memcpy(m_pwfxCode, pWfx, iFormatSize); 
 
	SetRawFormat();	 
	if (OpenStream(bEncode) == FALSE)	goto Error; 
	return TRUE; 
 
Error: 
	Free(); 
	return FALSE; 
} 
 
void CAcmCodec::Free() 
{ 
	if (m_bPass)	return; 
 
	if (acmStreamClose(m_has, 0) != 0)	 
	{ 
		OutputDebugString("acmStreamClose(m_has) failed\n"); 
	} 
	if (m_pwfxCode != NULL) 
	{ 
		free(m_pwfxCode); 
		m_pwfxCode = NULL; 
	} 
} 
 
int CAcmCodec::Convert(unsigned char * pSrc, unsigned char * pDst) 
{ 
	MMRESULT mmr; 
	int iDataLength = 0; 
	 
	if (!PrepareHeader(pSrc, pDst))	 
		goto Error; 
 
	mmr = acmStreamConvert(m_has, &m_asHeader, ACM_STREAMCONVERTF_BLOCKALIGN); 
    if (mmr != 0) 
	{ 
		OutputDebugString("acmStreamConvert() failed\n"); 
		goto Error; 
	} 
 
	iDataLength = m_asHeader.cbDstLengthUsed; 
 
	mmr = acmStreamUnprepareHeader(m_has, &m_asHeader, 0); 
	if (mmr != 0) 
	{ 
		OutputDebugString("CACMStream::Stop()::acmStreamUnprepareHeader failed\n"); 
		goto Error; 
	} 
	return iDataLength; 
 
Error: 
	return -1; 
} 
 
 
int CAcmCodec::Encode(char * pData, char * pCode, int iLength) 
{ 
	if (m_bPass) 
	{ 
		memcpy(pCode, pData, iLength); 
		return iLength; 
	} 
	else 
	{ 
		if (!GetStreamSize(iLength))	return -1; 
		memset(pCode, 0, m_dwDstLength); 
		return Convert((unsigned char *)pData, (unsigned char *)pCode); 
	} 
} 
 
int CAcmCodec::Decode(char * pData, char * pCode, int iLength) 
{ 
	return Encode(pCode, pData, iLength); 
} 
 
BOOL CAcmCodec::PrepareHeader(unsigned char * pSrc, unsigned char * pDst) 
{ 
	MMRESULT mmr; 
 
	memset(&m_asHeader, 0, sizeof(m_asHeader)); 
	m_asHeader.cbStruct = sizeof(m_asHeader); 
	m_asHeader.cbSrcLength = m_dwSrcLength; 
	m_asHeader.cbDstLength = m_dwDstLength; 
	m_asHeader.pbSrc = pSrc; 
	m_asHeader.pbDst = pDst; 
	mmr = acmStreamPrepareHeader(m_has, &m_asHeader, 0); 
	if (mmr != 0) 
	{ 
		OutputDebugString("CACMStream::Convert()::acmStreamPrepareHeader() failed\n"); 
		if (mmr == MMSYSERR_INVALFLAG) 
			OutputDebugString("At least one flag is invalid. \n"); 
		else if (mmr == MMSYSERR_INVALHANDLE) 
			OutputDebugString("The specified handle is invalid. \n"); 
		else if (mmr == MMSYSERR_INVALPARAM) 
			OutputDebugString("At least one parameter is invalid.\n"); 
		else if (mmr == MMSYSERR_NOMEM) 
			OutputDebugString("The system is unable to allocate resources. \n"); 
		return FALSE; 
	} 
	return TRUE; 
} 
 
BOOL CAcmCodec::NeedConvert(WAVEFORMATEX * pWfx) 
{ 
	if (pWfx->wFormatTag == WAVE_FORMAT_PCM && pWfx->nChannels == 1 && 
		pWfx->nSamplesPerSec == 8000 && pWfx->nAvgBytesPerSec == 16000 && 
		pWfx->nBlockAlign == 2 && pWfx->wBitsPerSample == 16 && pWfx->cbSize == 0) 
		return FALSE; 
	return TRUE; 
 
} 
void CAcmCodec::SetRawFormat() 
{ 
	m_wfxRaw.wFormatTag = WAVE_FORMAT_PCM;   	  
	m_wfxRaw.nChannels = m_iRawChannels; // = 1; 
	m_wfxRaw.nSamplesPerSec = m_iRawSampleRate; // = 8000; 
	m_wfxRaw.nAvgBytesPerSec = m_iRawSampleRate * m_iRawChannels * 2; 
	m_wfxRaw.nBlockAlign = m_iRawChannels * 2; 
	m_wfxRaw.wBitsPerSample = 16; 
	m_wfxRaw.cbSize = 0; 
 
} 
 
BOOL CAcmCodec::SetFormat(int iType) 
{ 
	char *cbExtra; 
	cbExtra = (char *)(m_pwfxCode) + sizeof(WAVEFORMATEX); 
 
	SetRawFormat(); 
 
	m_pwfxCode->nChannels = 1; 
	m_pwfxCode->nSamplesPerSec = 8000; 
	switch (iType) 
	{ 
	case ACM_CODEC_ALAW: 
		m_pwfxCode->wFormatTag = WAVE_FORMAT_ALAW; 
		m_pwfxCode->nAvgBytesPerSec = 8000; 
		m_pwfxCode->nBlockAlign = 1; 
		m_pwfxCode->wBitsPerSample = 8; 
		m_pwfxCode->cbSize = 0; 
		break; 
 
	case ACM_CODEC_MULAW: 
		m_pwfxCode->wFormatTag = WAVE_FORMAT_MULAW; 
		m_pwfxCode->nAvgBytesPerSec = 8000; 
		m_pwfxCode->nBlockAlign = 1; 
		m_pwfxCode->wBitsPerSample = 8; 
		m_pwfxCode->cbSize = 0; 
		break; 
 
	case ACM_CODEC_ADPCM: 
		m_pwfxCode->wFormatTag = WAVE_FORMAT_ADPCM; 
		m_pwfxCode->nAvgBytesPerSec = 4096; 
		m_pwfxCode->nBlockAlign = 256; 
		m_pwfxCode->wBitsPerSample = 4; 
		m_pwfxCode->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 ACM_CODEC_GSM610: 
		m_pwfxCode->wFormatTag = WAVE_FORMAT_GSM610; 
		m_pwfxCode->nAvgBytesPerSec = 1625; 
		m_pwfxCode->nBlockAlign = 65; 
		m_pwfxCode->wBitsPerSample = 0; 
		m_pwfxCode->cbSize = 2; 
		cbExtra[0] = 64; 
		cbExtra[1] = 1; 
		break; 
 
	case ACM_CODEC_G729CP: 
		m_pwfxCode->wFormatTag = WAVE_FORMAT_GFDVR; 
		m_pwfxCode->nAvgBytesPerSec = 1100; 
		m_pwfxCode->nBlockAlign = 11; 
		m_pwfxCode->wBitsPerSample = 0; 
		m_pwfxCode->cbSize = 0; 
		break; 
 
	case ACM_CODEC_G723_1: 
		m_pwfxCode->wFormatTag = 66; 
		m_pwfxCode->nAvgBytesPerSec = 800; 
		m_pwfxCode->nBlockAlign = 24; 
		m_pwfxCode->wBitsPerSample = 0; 
		m_pwfxCode->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"); 
		return FALSE; 
	} 
	return TRUE; 
} 
 
int CAcmCodec::GetMaxFormatSize() 
{ 
	ACMFORMATTAGDETAILS aftd; 
	MMRESULT mmr; 
 
	aftd.cbStruct = sizeof(aftd); 
	aftd.dwFormatTag = WAVE_FORMAT_UNKNOWN; 
	aftd.dwFormatTagIndex = 0; 
	mmr = acmFormatTagDetails(NULL, &aftd, ACM_FORMATTAGDETAILSF_LARGESTSIZE);                
	if (mmr != 0) 
	{ 
		OutputDebugString("CAcmCodec: GetMaxFormatSize failed, assure value 256\n"); 
		return 256; 
	} 
	return aftd.cbFormatSize; 
} 
 
BOOL CAcmCodec::OpenStream(BOOL bEncode) 
{ 
	MMRESULT mmr; 
	WAVEFORMATEX *	pSrcWfx; 
	WAVEFORMATEX *	pDstWfx; 
 
	if (bEncode) 
	{ 
		pSrcWfx = &m_wfxRaw; 
		pDstWfx = m_pwfxCode; 
	} 
	else 
	{ 
		pDstWfx = &m_wfxRaw; 
		pSrcWfx = m_pwfxCode; 
	} 
	mmr = acmStreamOpen(&m_has, NULL, pSrcWfx, pDstWfx, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME);           
	if (mmr != 0) 
	{ 
		switch (mmr) 
		{ 
		case ACMERR_NOTPOSSIBLE: 
			OutputDebugString("The requested operation cannot be performed. \n"); 
			break; 
 
		case MMSYSERR_INVALFLAG: 
			OutputDebugString("At least one flag is invalid. \n"); 
			break; 
 
		case MMSYSERR_INVALHANDLE: 
			OutputDebugString("The specified handle is invalid. \n"); 
			break; 
 
		case MMSYSERR_INVALPARAM: 
			OutputDebugString("At least one parameter is invalid. \n"); 
			break; 
 
		case MMSYSERR_NOMEM: 
			OutputDebugString("The system is unable to allocate resources. \n"); 
			break; 
		} 
		return FALSE; 
	} 
	return TRUE; 
} 
 
int CAcmCodec::GetMaxCodeLength(int iSrcLength) 
{ 
	if (m_bPass)	return iSrcLength; 
 
	if (GetStreamSize(iSrcLength)) 
		return m_dwDstLength;	 
	else  
		return -1; 
} 
 
BOOL CAcmCodec::GetStreamSize(int iLength) 
{ 
	MMRESULT mmr; 
 
	m_dwSrcLength = iLength; 
	mmr = acmStreamSize(m_has, m_dwSrcLength, &m_dwDstLength, ACM_STREAMSIZEF_SOURCE);   
	if (mmr != 0) 
	{ 
		OutputDebugString("acmStreamSize() failed\n"); 
		return FALSE; 
	} 
 
	return TRUE; 
}