基于VC的ACM音频编程接口压缩Wave音频(三)
(三)音 频 数 据 的 压 缩
下 面 说 明 使 用 CODEC 实 现 音 频 压 缩 的 过 程;假 设 源 信 号 为8K 采 样、16bits PCM 编 码、 单 声 道、 长 度 为1 秒 的 音 频 信 号。 驱 动 程 序 采 用Windows 95 自 带 的TrueSpeech 音 频CODEC, 它 能 实 现 大 约10:1 的 压 缩。 在 此 例 中,TrueSpeech CODEC 支 持 从 源 音 频 格 式 到 目 标 格 式 的 转 换, 而 在 实 际 应 用 中, 可 能 某 种CODEC 不 支 持 直 接 将 源 音 频 格 式 转 换 成 目 标 格 式, 这 时 可 以 采 取 两 步 转 换 法, 即 先 将 源 格 式 转 换 成 一 种 中 间 格 式, 再 将 此 中 间 格 式 转 换 成 目 标 格 式, 因 为 线 性PCM 编 码 最 为 简 单, 且 为 绝 大 多 数CODEC 所 支 持, 所 以 一 般 中 间 格 式 都 选 为 线 性PCM 格 式 的 一 种。
1.在 进 行 压 缩 之 前 首 先 需 要 确 定TrueSpeech 驱 动 程 序 的ID 值: 为 此 需 要 用 到acmDriverEnum() 函 数, 对 枚 举 到 的 每 一 个 驱 动 程 序, 由acmDriverEnum() 指 定 的 回 调 函 数 将 检 查 其 支 持 的 所 有 音 频 格 式, 若 其 中 包 括wFormatTag 值 为WAVE_FORMAT_DSPGROUP_TRUESPEECH 的 音 频 格 式, 则 此 驱 动 程 序 就 是 要 寻 找 的TrueSpeech CODEC, 它 所 支 持 的 第 一 种WAVE_FORMAT_DSPGROUP_TRUESPEECH 音 频 格 式 即 为 目 标 音 频 压 缩 格 式。
2.打 开 驱 动 程 序:
根 据 查 询 的 结 果, 设 hadID 为 TrueSpeech CODEC 的 ID 值,pwfDrv 为 指 向 目 标 WAVEFORMATEX 结 构 的 指 针, 接 下 来 利 用 获 得 的ID 值 打 开 相 应 的 驱 动 程 序
HACMDRIVER had = NULL;
mmr = acmDriverOpen(&had, hadID, 0);
if(mmr) { printf(" 打开驱动程序失败\n"); exit(1); }
3.压 缩: 和 解 压 缩 一 样, 都 是 将 音 频 信 号 从 一 种 音 频 格 式 转 换 成 另 一 种 格 式, 要 完 成 这 一 过 程, 首 先 要 打 开 转 换 流; 在 用acmStreamOpen 打 开 转 换 流 时, 我 们 指 定 了ACM_STREAMOPENF_NONREALTIME 标 志, 它 表 示 转 换 无 需 实 时 进 行, 因 为 很 多 压 缩 算 法 的 计 算 量 是 相 当 大 的, 实 时 完 成 几 乎 是 不 可 能 的, 例 如 在 本 例 中, 如 果 不 指 定 此 标 志,TrueSpeech CODEC 就 会 返 回“ 无 法 完 成” 的 错 误。
HACMSTREAM hstr = NULL;
DWORD dwSrcBytes = dwSrcSamples * wfSrc.wBitsPerSample / 8;
mmr = acmStreamOpen(&hstr,had, //驱动程序句柄 pwfSrc, //指向源音频格式的指针 pwfDrv, //指向目标音频格式的指针 NULL, //无过滤器 NULL, //无回调函数 0,ACM_STREAMOPENF_NONREALTIME);
在 真 正 进 行 转 换 之 前, 还 必 须 准 备 转 换 流 的 信 息 头。 下 面 一 段 代 码 中, 先 利 用 源 数 据 的 大 小 以 及 目 标 格 式 的 平 均 数 据 率 估 算 目 标 数 据 的 缓 存 区 大 小, 然 后 调 用acmStreamPrepareHeader 为 转 换 准 备 信 息 头。
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);
语 音 数 据 真 正 的 压 缩 过 程 是 由 函 数acmStreamConvert() 完 成 的。 在 调 用acmStreamConvert() 时 可 以 指 定 回 调 函 数, 以 便 在 转 换 过 程 中 显 示 进 度 信 息 等。 在 本 例 中, 未 指 定 回 调 函 数, 只 是 简 单 地 等 待 压 缩 的 结 束。
—- mmr = acmStreamConvert(hstr, &shdr, 0);
数 据 压 缩 完 毕 后, 应 用 程 序 就 可 以 把 缓 冲 区 中 的 数 据 写 入 目 标 文 件 中。
最 后, 必 须 关 闭 转 换 流 和 驱 动 程 序。
mmr = acmStreamClose(hstr, 0); mmr = acmDriverClose(had, 0);
版权申明:本站文章均来自网络,如有侵权,请评论 ,收到后立即删除,谢谢!
基于VC的ACM音频编程接口压缩Wave音频(三)的更多相关文章
- 基于VC的ACM音频编程接口压缩Wave音频(一)
(一)概述 音频数据一般都具有较高的采样率,经过压缩的原始数据才具有实用价值,否则不仅要占用大量存储空间而且在播放或进行网络传输时效率也是非常低下的,所以音频数字压缩编码在多媒体应用中有着广泛而又重要 ...
- 基于VC的ACM音频编程接口压缩Wave音频(二)
(二)获取CODECs 的 信 息 ACM 的API 函 数 定 义 在 头 文 件msacm.h 中, 除 此 之 外, 对ACM 编 程 还 必 须 包 含 头 文 件mmsystem.h,mm ...
- Linux音频编程指南
Linux音频编程指南 虽然目前Linux的优势主要体现在网络服务方面,但事实上同样也有着非常丰富的媒体功能,本文就是以多媒体应用中最基本的声音为对象,介绍如何在Linux平台下开发实际的音频应用程序 ...
- 【Linux系统编程应用】Linux音频编程基础(一)【转】
转自:https://blog.csdn.net/dengjin20104042056/article/details/52435290 一.数字音频 音频信号是一种连续变化的模拟信号,但计算机只能处 ...
- Linux音频编程指南(转)
转自: http://www.ibm.com/developerworks/cn/linux/l-audio/ Linux音频编程指南 虽然目前Linux的优势主要体现在网络服务方面,但事实上同样也有 ...
- VC 与Matlab混合编程之引擎操作详解
Visual C++ 是当前主流的应用程序开发环境之一,开发环境强大,开发的程序执行速度快.但在科学计算方面函数库显得不够丰富.读取.显示数据图形不方便. Matlab 是一款将数值分析.矩阵计算.信 ...
- VC++学习之网络编程中的套接字
VC++学习之网络编程中的套接字 套接字,简单的说就是通信双方的一种约定,用套接字中的相关函数来完成通信过程.应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问 ...
- Linux音频编程
1. 背景 在<Jasper语音助理介绍>中, 介绍了Linux音频系统, 本文主要介绍了Linux下音频编程相关内容. 音频编程主要包括播放(Playback)和录制(Record), ...
- 【转】Alsa音频编程【精华】
一.前序 这里了解一下各个参数的含义以及一些基本概念. 声音是连续模拟量,计算机将它离散化之后用数字表示,就有了以下几个名词术语. 样本长度(sample):样本是记录音频数据最基本的单位,计算机对每 ...
随机推荐
- python打印服务器所有进程
#有时候我们需要查看服务器上所有进程,来判断哪些进程是否已经称为僵尸进程#!/usr/local/bin/python3.5 import psutil for i in psutil.pids(): ...
- .NET使用Com组件的一点点教训笔记~
中控IFACE系列的产品,二次开发包 zkemkeeper.dll 在system32 ,SySWoW64都注册了,就是他妈的用不了. 最后,在 system32 ,SySWoW64 注册了,然后把需 ...
- 为何PHP插入mysql的中文是乱码?【坑】
依然没有找到最终的解决方法,PHP插入的中文在phpmyadmin中看是乱码,但是用PHP获取之后显示正常: 可以在phpmyadmin中直接插入中文,在PHPmyadmin中显示正常,用PHP获取中 ...
- 在Linux上配置xampp后远程访问域名报错
在Linux上配置xampp后远程访问域名报错: New XAMPP security concept: Access to the requested object is only availabl ...
- .NET 4.0 中超长路径超长文件名的问题
1. 昨天开发中遇到一个问题,场景如下: 客户端从服务器下载一个文件并解压,客户端在使用后需要做清理操作(删除解压出来的文件),结果删除失败,抛出如下异常: The specified path, f ...
- Verilog经典输入控制/激励信号模板1
:]i; always @ ( posedge CLOCK or negedge RESET ) if( !RESET ) begin i <= 'd0; Start_Si ...
- HTML5中canvas大小调整
今天用到canvas元素,发现它的大小不是像普通dom元素一样,直接设置css样式可以改变的,它会由自己原本的大小伸缩. 例如, <canvas id='canvas'></canv ...
- java 中与 或 非 异或 和位移运算
与(&) 或(|) 异或(^) 和位移(>>,<<) 通常和符号位无关 .. 但是非比较特殊,与符号位有关,所以计算的时候要考虑符号位 先扩展为32字符,前16位为符号 ...
- 接收新信息,在会话中看不到(thread表数据插入/更新失败)
分析原因:收到短信,sms表插入信息,触发器会自动更新thread表,更新失败导致一直有一条未读信息数量显示,但在会话列表中却看不到. (偶现,低概率. 解决方法:接收新信息插入后,立即查询threa ...
- Java多线程基本概念
基本概念 线程与任务的概念不一样. 任务:通常是一些抽象的且离散的工作单元,比如在Web请求中,针对用户的请求需要返回相应的页面是一个任务,在Java中实现Runnable接口的类也是一个任务. 线程 ...