#include <stdio.h> #include <windows.h> #include <mmreg.h> #include <mmsystem.h> #include <msacm.h> #pragma comment(lib, "Msacm32.lib") WAVEFORMATEX *pwfSrc; WAVEFORMATEX *pwfDrv; HACMDRIVERID hadid_GSM610 = NULL; int n = 0; #define ADDHEADER //遍历驱动,寻找Windows GSM 6.10驱动 BOOL CALLBACK CodecsEnumProc(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport) { DWORD dwSize = 0; ACMDRIVERDETAILS acmdd; HACMDRIVER had = NULL; acmdd.cbStruct = sizeof(acmdd); MMRESULT mmr = acmDriverDetails(hadid, &acmdd, 0); if (mmr) { printf("acmDriverDetails Error!/n"); } if (strcmp(acmdd.szLongName, "Microsoft GSM 6.10 Audio CODEC") == 0) { //将GSM驱动的DRIVERID储存起来 hadid_GSM610 = hadid; return TRUE; } return TRUE; } //Windows GSM 6.10文件头格式 struct WAVEFILEHEADER { char chRIFF[4]; //4 DWORD dwRIFFLen; //4 char WAVEfmt[8]; //8 long ngsmFlag; //4 short fmttag; //2 short nchannel; //2 long samplespersec; //4 long bytepersec; //4 char szTemp[8]; //8 char szTemp2[8]; //8 char szTemp3[4]; //4 char szTemp4[4]; //4 long dwDataLen; //4 }; WAVEFILEHEADER wfh; void WriteHeader(WAVEFILEHEADER &wfh, DWORD &dwLen, DWORD dwSrcLen) { //添加文件头 memset(&wfh, 0, sizeof(wfh)); memcpy(wfh.chRIFF, "RIFF", 4); wfh.dwRIFFLen = dwLen + 60 - 8; memcpy(wfh.WAVEfmt, "WAVEfmt ", 8); wfh.ngsmFlag = 0x14; wfh.fmttag = 0x31; wfh.nchannel = 1; wfh.samplespersec = 8000; wfh.bytepersec = 1625; //41 00 00 00 02 00 40 01H wfh.szTemp[0] = 0x41; wfh.szTemp[4] = 0x02; wfh.szTemp[6] = 0x40; wfh.szTemp[7] = 0x01; //66 61 63 74 04 00 00 00H wfh.szTemp2[0] = 0x66; wfh.szTemp2[1] = 0x61; wfh.szTemp2[2] = 0x63; wfh.szTemp2[3] = 0x74; wfh.szTemp2[4] = 0x04; //源音频文件,纯音频数据流的大小,不包含原来音频文件的文件头 memcpy(wfh.szTemp3, &dwSrcLen, 2); memcpy(wfh.szTemp4, "data", 4); wfh.dwDataLen = dwLen; } void Test(HACMDRIVERID hadid) { BYTE byteSrc[100]; BYTE byteDst[100]; memset(byteDst, 0, sizeof(byteDst)); memset(byteSrc, 0, sizeof(byteSrc)); pwfSrc = (LPWAVEFORMATEX)byteSrc; pwfDrv = (LPWAVEFORMATEX)byteDst; HACMDRIVER had = NULL; MMRESULT mmr; pwfSrc->wFormatTag = WAVE_FORMAT_PCM; pwfSrc->nChannels = 1; pwfSrc->nSamplesPerSec = 8000; pwfSrc->nAvgBytesPerSec = 8000; pwfSrc->nBlockAlign = 1; pwfSrc->wBitsPerSample = 8; pwfSrc->cbSize = 0; HACMSTREAM hstr = NULL; memset(pwfDrv, 0, sizeof(WAVEFORMATEX)); pwfDrv->wFormatTag = WAVE_FORMAT_GSM610; DWORD dwfxDst = 100; mmr = acmDriverOpen(&had, hadid_GSM610, 0); //就是这个函数,弄了两天,死活搞不出来,加了这个,用他自带的函数调用获得的pwfDrv参数才有效 mmr = acmFormatSuggest(had, pwfSrc, pwfDrv, dwfxDst, ACM_FORMATSUGGESTF_WFORMATTAG); mmr = acmStreamOpen(&hstr,had, //驱动程序句柄 pwfSrc, //指向源音频格式的指针 pwfDrv, //指向目标音频格式的指针 NULL, //无过滤器 0, //无回调函数 0,ACM_STREAMOPENF_NONREALTIME); switch(mmr) { case ACMERR_NOTPOSSIBLE: printf("The requested operation cannot be performed./n"); break; case MMSYSERR_INVALFLAG: printf("At least one flag is invalid. /n"); break; case MMSYSERR_INVALHANDLE: printf("The specified handle is invalid. /n"); break; case MMSYSERR_INVALPARAM: printf("At least one parameter is invalid. /n"); break; case MMSYSERR_NOMEM: printf("The system is unable to allocate resources./n"); break; } DWORD dwOutputBytes = 0; BYTE *pSrcData = NULL; FILE *fp = fopen("1.wav", "rb"); fseek(fp, 0, SEEK_END); DWORD dwSrcLen = ftell(fp) - 44;//除去文件头 fseek(fp, 44, SEEK_SET); pSrcData = new BYTE[dwSrcLen]; fread(pSrcData, 1, dwSrcLen, fp); fclose(fp); DWORD cbSrcReadBytes = pwfSrc->nAvgBytesPerSec - pwfSrc->nAvgBytesPerSec % pwfSrc->nBlockAlign; mmr = acmStreamSize(hstr, dwSrcLen, &dwOutputBytes, ACM_STREAMSIZEF_SOURCE); dwOutputBytes += 60;//加上文件头 BYTE* pDst2Data = new BYTE [dwOutputBytes]; memset(pDst2Data, 0, sizeof(dwOutputBytes)); ACMSTREAMHEADER pash; pash.cbStruct = sizeof(pash); pash.fdwStatus = 0L; pash.dwUser = 0L; pash.pbSrc = pSrcData; pash.cbSrcLength = dwSrcLen; pash.cbSrcLengthUsed = 0L; pash.dwSrcUser = dwSrcLen; pash.pbDst = pDst2Data; pash.cbDstLength = dwOutputBytes; pash.cbDstLengthUsed = 0L; pash.dwDstUser = dwOutputBytes; mmr = acmStreamPrepareHeader(hstr, &pash, 0); printf("Converting to final format.../n"); mmr = acmStreamConvert(hstr, &pash, 0); if (mmr) { printf("Failed to do PCM to driver format conversion/n"); return; } fp = fopen("2.wav", "wb"); fwrite(&wfh, 1, 60, fp); fwrite(pDst2Data, 1, pash.cbDstLengthUsed, fp); WriteHeader(wfh, pash.cbDstLengthUsed, dwSrcLen); fseek(fp, 0, SEEK_SET); fwrite(&wfh, 1, 60, fp); fclose(fp); printf("Converted OK/n"); acmStreamClose(hstr, 0); acmDriverClose(had, 0); delete []pSrcData; pSrcData = NULL; delete []pDst2Data; pDst2Data = NULL; return; } void main() { MMRESULT mmr = acmDriverEnum(CodecsEnumProc, 0, 0); Test(hadid_GSM610); }