📄 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -