以文本方式查看主题 - 计算机科学论坛 (http://bbs.xml.org.cn/index.asp) -- 『 C/C++编程思想 』 (http://bbs.xml.org.cn/list.asp?boardid=61) ---- VC调用ACM音频压缩编程接口的方法 (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=27011) |
-- 作者:卷积内核 -- 发布时间:2/7/2006 9:09:00 AM -- VC调用ACM音频压缩编程接口的方法 音频和视频数据是大多数多媒体应用程序向用户提供信息的主要方式,这些数据一般具有较高的采样速率,如果不经过压缩的话,保存它们需要消耗大量的存贮空间,在网络上进行传输的效率也很低,因此音频视频数字压缩编码在多媒体技术中占有很重要的地位。就音频数据而言,目前常用的压缩方法有很多种,不同的方法具有不同的压缩比和还原音质,编码的格式和算法也各不相同,其中某些压缩算法相当复杂,普通程序不可能去实现其编解码算法。所幸的是,与Windows3.x相比,Windows95/NT4.0为多媒体应用程序提供了更强的支持,引入了ACM(Audio Compression Manager,音频压缩管理器)和VCM(Video Compressio nManager,视频压缩管理器),它们负责管理系统中所有音频和视频编解码器(Coder-Decoder,简称CODEC,是实现音频视频数据编解码的驱动程序),应用程序可以通过ACM或VCM提供的编程接口调用这些系统中现成的编解码器来实现音频或视频数据的压缩和解压缩。95/NT4.0系统自带的音频CODECs支持一些早期的音频数据压缩标准,如ADPCM等,InternetExplorer4.0等应用程序包含的音频CODECs支持一些比较新的压缩标准,如MPEGLayer3等。在控制面板的多媒体组件中选择“高级”,打开“音频压缩的编码解码器”,就可列出系统中安装的所有音频CODECs。本文所要介绍的就是ACM音频压缩接口的编程方法,所用编程工具为VC++5.0。 获取CODECs的信息 ----ACM的API函数定义在头文件msacm.h中,除此之外,对ACM编程还必须包含头文件mmsystem.h,mmreg.h,这两个头文件定义了多媒体编程中最基本的常量和数据结构。为了避免有些高版本ACM才提供的函数和功能在较低版本的ACM中上不可用,程序中应调用acmGetVersion函数查询用户机器中ACM的版本信息。 ----前面提到,在控制面板中可以查看系统中CODECs的信息,而在应用程序中也常常需要知道某种音频CODECs是否存在,并获取其编解码参数等信息,这一点可以通过调用下面两个函数来实现。 ---- MMRESULT mmr=acmMetrics(NULL, ACM_METRIC_COUNT_CODECS, &dwCodecs); ---- mmr = acmDriverEnum(CodecsEnumProc, 0, 0); ----acmMetrics()函数可以获取许多ACM对象的有用信息,例如向其中传递ACM_METRIC_COUNT_CODECS可以查询系统中安装的音频CODECs总数。函数acmDriverEnum()的功能是枚举所有的音频CODECs,在acmDriverEnum()的参数中指定回调函数CodecsEnumProc()可以进一步查询每个CODEC的信息。Windows编程中经常要用到回调函数,下面是枚举音频CODECs的一个回调函数的示例。
BOOL CALLBACK CodecsEnumProc(HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport) { DWORD dwSize = 0; if (fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC) printf("多格式转换\n"); ACMDRIVERDETAILS add; acmdd.cbStruct = sizeof(acmdd); MMRESULT mmr = acmDriverDetails(hadid, &acmdd, 0); if (mmr) error_msg(mmr); else { printf(" 全称: %s\n", acmdd.szLongName); printf(" 描述: %s\n", acmdd.szFeatures); } HACMDRIVER had = NULL; mmr = acmDriverOpen(&had, hadid, 0); //打开驱动程序 if (mmr) error_msg(mmr); else { mmr = acmMetrics(had, ACM_METRIC_ MAX_SIZE_FORMAT, &dwSize); WAVEFORMATEX* pwf = (WAVEFORMATEX*) malloc(dwSize); memset(pwf, 0, dwSize); pwf->cbSize = LOWORD(dwSize) - sizeof(WAVEFORMATEX); pwf->wFormatTag = WAVE_FORMAT_UNKNOWN; ACMFORMATDETAILS fd; memset(&fd, 0, sizeof(fd)); fd.cbStruct = sizeof(fd); fd.pwfx = pwf; fd.cbwfx = dwSize; fd.dwFormatTag = WAVE_FORMAT_UNKNOWN; mmr = acmFormatEnum(had, &fd, FormatEnumProc, 0, 0); if (mmr) error_msg(mmr); free(pwf); acmDriverClose(had, 0); } return TRUE; } BOOL CALLBACK FormatEnumProc (HACMDRIVERID hadid, LPACMFORMATDETAILS pafd, DWORD dwInstance, DWORD fdwSupport) { printf("%4.4lXH, %s\n", pafd- >dwFormatTag, pafd- >szFormat); return TRUE; } 音频数据的压缩 ----根据查询的结果,设hadID为TrueSpeechCODEC的ID值,pwfDrv为指向目标WAVEFORMATEX结构的指针,接下来利用获得的ID值打开相应的驱动程序。 HACMDRIVER had = NULL; mmr = acmDriverOpen(&had, hadID, 0); if(mmr) { printf(" 打开驱动程序失败\n"); exit(1); } HACMSTREAM hstr = NULL; DWORD dwSrcBytes = dwSrcSamples * wfSrc.wBitsPerSample / 8; mmr = acmStreamOpen(&hstr,had, //驱动程序句柄 pwfSrc, //指向源音频格式的指针 pwfDrv, //指向目标音频格式的指针 NULL, //无过滤器 NULL, //无回调函数 0,ACM_STREAMOPENF_NONREALTIME); ---- DWORD dwDstBytes=pwfDrv->nAvgBytesPerSec*dwSrcSamples/wfSrc.nSamplesPerSec; ---- dwDstBytes = dwDstBytes*3/2; // 计 算 压 缩 后 音 频 数 据 大 小, 并 依 此 适 当 增 加 输 出 缓 冲 区 的 大 小。 BYTE* pDstData = new BYTE [dwDstBytes]; ACMSTREAMHEADER shdr; memset(&strhdr, 0, sizeof(shdr)); shdr.cbStruct = sizeof(shdr); shdr.pbSrc = pSrcData; //源音频数据区 shdr.cbSrcLength = dwSrcBytes; shdr.pbDst = pDstData; //压缩后音频数据缓冲区 shdr.cbDstLength = dwDstBytes; mmr = acmStreamPrepareHeader(hstr, &shdr, 0); ----mmr=acmStreamConvert(hstr,&shdr,0); ----数据压缩完毕后,应用程序就可以把缓冲区中的数据写入目标文件中。 ----最后,必须关闭转换流和驱动程序。 mmr=acmStreamClose(hstr,0); mmr=acmDriverClose(had,0);
|
-- 作者:卷积内核 -- 发布时间:9/21/2006 10:21:00 AM -- Up |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
46.875ms |