C++写的
//压缩/解压的入口函数
DWORD DecodeSound:
ecodeAcmSound(char* in, int inLen, WAVEFORMATEX* inFormat, char* out, int* outLen, WAVEFORMATEX* OutFormat)
{
WORD wFormatTag = inFormat->wFormatTag;
// Now we locate a CODEC that supports the destination format tag
HACMDRIVERID hadid = find_driver(wFormatTag, inFormat->nSamplesPerSec, inFormat->wBitsPerSample);
if (hadid == NULL) {
MessageBox(NULL,"No driver found","find_driver ERROR",MB_OK);
return ET_SOUND;
}
// open the driver
HACMDRIVER had = NULL;
// MMSYSERR_INVALPARAM
MMRESULT mmr;
// open the driver
mmr = acmDriverOpen(&had, hadid, 0);
if (mmr) {
MessageBox(NULL,"Failed to open driver","acmDriverOpen ERROR",MB_OK);
return ET_SOUND;
}
// open the conversion stream
// Note the use of the ACM_STREAMOPENF_NONREALTIME flag. Without this
// some software compressors will report error 512 - not possible
HACMSTREAM hstr1;
mmr = acmStreamOpen(&hstr1,
had, // driver handle ??NULL
inFormat, // source format
OutFormat, // destination format
NULL, // no filter
NULL, // no callback
0, // instance data (not used)
ACM_STREAMOPENF_NONREALTIME);
// flags
//MMSYSERR_NOTSUPPORTED = 8;
if (mmr) {
MessageBox(NULL,"Failed to open acmstream","acmStreamOpen ERROR",MB_OK);
//printf("Failed to open a stream todo
PCM to driver format conversion/n"
;
return ET_SOUND;
}
DWORD dwDstBytes = inFormat->nAvgBytesPerSec * OutFormat->nSamplesPerSec / OutFormat->nSamplesPerSec;
dwDstBytes = dwDstBytes ;
// add a little room
// fill in the conversion info
ACMSTREAMHEADER strhdr1;
memset(&strhdr1, 0, sizeof(strhdr1));
strhdr1.cbStruct = sizeof(strhdr1);
strhdr1.pbSrc = (BYTE*)in;//pDstData;
//?? the source data to convert
strhdr1.cbSrcLength = inLen;
strhdr1.pbDst = (BYTE*)out;
//??test
strhdr1.cbDstLength = *outLen;//OutFormat->nAvgBytesPerSec;
// prep the header
mmr = acmStreamPrepareHeader(hstr1, &strhdr1, 0);
if (mmr)
{
return ET_SOUND;
}
// convert the data
mmr = acmStreamConvert(hstr1, &strhdr1, ACM_STREAMCONVERTF_BLOCKALIGN);// 0
if (mmr) {
return ET_SOUND;
}
acmStreamUnprepareHeader(hstr1, &strhdr1, 0);
//Close Stream
mmr = acmStreamClose(hstr1, 0);
//Close Driver
mmr = acmDriverClose(had, 0);
*outLen = strhdr1.cbDstLengthUsed;
//转化后的长度
// g_kAudioOut.write(out,*outLen); //logo add for test
return NO_ERR;
}
// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
BOOL CALLBACK find_format_enum(HACMDRIVERID hadid, LPACMFORMATDETAILS pafd, DWORD dwInstance, DWORD fdwSupport)
{
FIND_DRIVER_INFO* pdi = (FIND_DRIVER_INFO*) dwInstance;
if ((pafd->dwFormatTag == (DWORD)pdi->wFormatTag) &&
(pafd->pwfx->nSamplesPerSec == pdi->nSamplesPerSec)&&
(pafd->pwfx->wBitsPerSample == pdi->wBitsPerSample)){ //
// found it
pdi->hadid = hadid;
printf("
%4.4lXH, %s/n", pafd->dwFormatTag, pafd->szFormat);
return FALSE;
// stop enumerating
}
return TRUE;
// continue enumerating
}
// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
BOOL CALLBACK find_driver_enum(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport)
{
FIND_DRIVER_INFO* pdi = (FIND_DRIVER_INFO*) dwInstance;
if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC)
printf("多格式转换/n"
;
// open the driver
HACMDRIVER had = NULL;
HRESULT mmr = acmDriverOpen(&had, hadid, 0);
if (mmr) {
// some error
MessageBox(NULL,"Failed to open driver","acmStreamConvert ERROR",MB_OK);
return FALSE;
// stop enumerating
}
// enumerate the formats it supports
DWORD dwSize = 0;
mmr = acmMetrics((HACMOBJ)had, ACM_METRIC_MAX_SIZE_FORMAT, &dwSize);
if (mmr)
{
MessageBox(NULL,"acmMetrics ERROR","acmMetrics ERROR",MB_OK);
return FALSE;
}
if (dwSize < sizeof(WAVEFORMATEX)){
dwSize = sizeof(WAVEFORMATEX);
// for MS-PCM
}
WAVEFORMATEX* pwf = (WAVEFORMATEX*) malloc(dwSize);
memset(pwf, 0, dwSize);
pwf->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX);
pwf->wFormatTag = pdi->wFormatTag;
pwf->nSamplesPerSec = pdi->nSamplesPerSec;
pwf->wBitsPerSample = pdi->wBitsPerSample;
ACMFORMATDETAILS fd;
memset(&fd, 0, sizeof(fd));
fd.cbStruct = sizeof(fd);
fd.pwfx = pwf;
fd.cbwfx = dwSize;
fd.dwFormatTag = pdi->wFormatTag;
mmr = acmFormatEnum(had, &fd, find_format_enum, (DWORD)(VOID*)pdi, 0);
//ACM_FORMATENUMF_WFORMATTAG
free(pwf);
acmDriverClose(had, 0);
if (pdi->hadid || mmr) {
// found it or some error
return FALSE;
// stop enumerating
}
return TRUE;
// continue enumeration
}
// ----------------------------------------------------------------------------
//
// ----------------------------------------------------------------------------
HACMDRIVERID DecodeSound::find_driver(WORD wFormatTag, DWORD nSamplesPerSec, WORD wBitsPerSample)
{
FIND_DRIVER_INFO fdi;
fdi.hadid = NULL;
fdi.wFormatTag = wFormatTag;
fdi.nSamplesPerSec = nSamplesPerSec;
fdi.wBitsPerSample = wBitsPerSample;
MMRESULT mmr = acmDriverEnum(find_driver_enum, (DWORD)(VOID*)&fdi, 0);
if (mmr) return NULL;
return fdi.hadid;
}
//调用压缩/解压(我的是解压ADPCM to PCM)
//标准格式
dstFormat = (WAVEFORMATEX*)new char[18];
dstFormat->cbSize = 0;
dstFormat->wFormatTag = WAVE_FORMAT_PCM;
// pcm
dstFormat->nChannels = 1; // mono
dstFormat->nSamplesPerSec = 8000; // 11.025 kHz
dstFormat->wBitsPerSample = 8; // 8 bit
dstFormat->nBlockAlign = dstFormat->nChannels * dstFormat->wBitsPerSample / 8;
dstFormat->nAvgBytesPerSec = dstFormat->nSamplesPerSec * dstFormat->nBlockAlign;
//解压后的格式
dwDataLen = dwG72x * 4; // 压缩率为 4
srcFormat = (WAVEFORMATEX*)new char[20];
srcFormat->nChannels = 1;
srcFormat->wFormatTag = WAVE_FORMAT_DVI_ADPCM;
srcFormat->nSamplesPerSec = 8000;
srcFormat->wBitsPerSample = 4;
srcFormat->nBlockAlign = 256;
srcFormat->nAvgBytesPerSec = 4055;
srcFormat->cbSize = 2;
//注意,不同格式 不同
unsigned char extra060[2] = { 0xF9, 0x01 };
for(i=0;i<srcFormat->cbSize;i++) {
*((unsigned char *)srcFormat+18+i) = extra060
;
}
//压缩或解压
m_DecodeSound->DecodeAcmSound(
(char*)pbG72x, dwG72x, srcFormat,
(char*)pbDataBuf, (int*) &dwDataLen, dstFormat);