0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

简单的声音数据ADPCM压缩方法

聚丰开发 2019-01-11 18:12 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

| 聚丰开发方案开发设计及PCBA批量交付|

▼▼▼


前两天有朋友发邮件给我,他有2~3k大小的图像,想用AVR的单片机进行压缩处理,看我有什么建议。


《删繁就简-单片机入门到精通》(我写的~(#^.^#))一书中有一章节的内容和数据压缩有关,我在网上也发布了相关的测试源代码,这些代码可以用做参考。


我们常使用的JPG图片是一种效率较高的压缩方法,在图像细节没有明显失真的情况下可以达到10倍的压缩率,不过这个10倍是针对尺寸比较大的图像,对于小尺寸图像并不适用。原因是通用的压缩方法,都需要包含一个头信息,头信息会占用一定空间,这样对于小尺寸图像虽然图像数据能有比较好的压缩率,但加上头信息最后得到的全部数据缩小的比率就有限。


越是压缩率高的方法,其算法自然也越复杂,像这位朋友用的是AVR单片机,处理复杂算法的能力有限,几年前我们用51的单片机测试过160*120大小的图像,压缩成JPG需要3~4秒的时间,完全不能满足应用需求。(压缩会比解压缩更费时间)


除了图像,声音数据也常常需要进行压缩处理
,不过声音的压缩处理方法和图像会有所不同,大多是提取声音数据的规律,用数学模型来模拟人喉咙发声,这种方法压缩率高,但需要非常复杂的运算,也不适合低速的单片机用程序实现。


但有一种简单的声音压缩方法例外,这种方法完全是基于被压缩的数据分布特性,认为声音数据是在0幅度上下正态分布,幅度越大的值出现的几率越小,而且采样所得的数据通常是平滑相连,出现上一点幅度为正最大而下一点幅度为负最小的可能性几乎为零,两点间的变化差异大都局限于一定范围之内,于是将声音数据处理相邻两点的变化值,从而起到压缩效果,这样处理的算法也比较简单。

这里给大家介绍
一种简单的ADPCM处理方法,是我以前在网上收集的。用这种方法实际上也可以用来处理前面图像数据压缩的问题,只是需要先将图像数据预处理为RGB或YUV分量,然后进行压缩处理


IMA-ADPCM 算法

-------------------------------------------------------


IMA-ADPCM (ADPCM Adaptive Differential Pulse Code Modulation), 是一种针对 16bit (或者更高?) 声音波形数据的一种有损压缩算法, 它将声音流中每次采样的 16bit 数据以 4bit 存储, 所以压缩比 1:4. 而压缩/解压缩算法非常的简单, 所以是一种低空间消耗,高质量声音获得的好途径. 著名的 WestWood 在它的许多游戏里都使用了这个技术, DUNE II, C&C, RA 等等, 保存声音的数据文件后缀名为 .AUD 的大多用 IMA-ADPCM 压缩. (不过 WestWood 的游戏数据文件大多经过打包, 这些小文件统统放进了一个 .MIX 文件包中, 关于解开 .MIX 文件包, 见http://www.geocities.com/SiliconValley/8682)


ADPCM 主要是针对连续的波形数据的, 保存的是波形的变化情况, 以达到描述整个波形的目的. 本文并不想详细介绍 ADPCM 算法原理, 那些是数学知识,有高等数学基础的朋友可以自己研究, 云风数学马马虎虎, 这里也讲不清楚, 但是它的编码和解码的过程却很简洁, 列在后面, 相信大家能够看明白.


先给不熟悉声音信号的储存的朋友补一课, 不想看就跳过吧 ^_^: 一般游戏中用到的声音有两种不同性质的, 一是波形数据, 是经过事先声音采样录制下来的, 采样时一般按每秒 8千到 4 万次的频率(8Khz ~44.4Khz)记录每次采样时的声音强度, 在播放时, 再以同一频率, 按样本声音的强弱变化触发扬声器, 声音就被重现了, 如果你将采样数据流标在坐标纸上,就会发现是一条波形曲线, 如果采样时将声音信号强弱分为 256 级, 就是我们说的 8bit 采样, 如果分为 65536 级, 就是 16bit 采样了; 另一是 MIDI 类的, 它是将各种乐器的声学性质都事先记录下来, 而数据流中仍旧是按一定频率记录, 但不是每秒数千上万次了, 大约只有几 Hz 到几十 Hz, 将几种乐器按某一音频和强度触发描述下来, 经过声卡合成为波形信号就可以播放了.


8bit 采样的声音人耳是可以接受的, 比如 Win95 启动的音乐, 而 16bit 采样的声音可以算是高音质了, 现代游戏中也多采用它. (将声音强度分的更细没有太多的意义, 通常都是提高采样频率来近一步提高音质) ADPCM 算法却可以将每次采样得到的 16bit 数据压缩到 4bit ;-) 需要注意的是, 如果要压缩/接压缩立体声信号, 请注意采样时, 声音信号是放在一起的, 需要将两个声道分别处理. OK, 下面列出了其中的奥妙, 请细细品味:


----------------------------------------------------------------


IMA-ADPCM 压缩过程


首先我们认为声音信号都是从零开始的,那么需要初始化两个变量


int index="0",prev_sample:=0;


下面的循环将依次处理声音数据流, 注意其中的 getnextsample() 应该得到一个 16bit 的采样数据, 而 outputdata() 可以将计算出来的数据保存起来,程序中用到的 step_table[], index_adjust[] 附在后面:
int index="0",prev_sample:=0;


while (还有数据要处理) {
cur_sample=getnextsample(); // 得到当前的采样数据
delta="cur"_sample-prev_sample; // 计算出和上一个的增量
if (delta<0) delta="-delta",sb=8;   
else sb="0"; // sb 保存的是符号位


code = 4*delta / step_table[index]; // 根据 steptable[] 得到一个 0~7 的值
if (code>7) code="7"; // 它描述了声音强度的变化量


index+=index_adjust[code]; // 根据声音强度调整下次取 steptable 的序号
if (index<0) index="0";            // 便于下次得到更精确的变化量的描述
else if (index>88) index="88";


prev_sample=cur_sample;


outputode(code|sb); // 加上符号位保存起来
}


---------------------------------------------------------


IMA-ADPCM 解压缩过程


接压缩实际是压缩的一个逆过程, 同样其中的 getnextcode() 应该得到一个编码, 而 outputsample() 可以将解码出来的声音信号保存起来. 这段代码同样使用了同一个的 setp_table[] 和 index_adjust() 附在后面:


int index="0",cur_sample:=0;


while (还有数据要处理) {
code="getnextcode"(); // 得到下一个数据


if ((code & 8) != 0) sb="1" else sb="0";
code&=7; // 将 code 分离为数据和符号


delta=(step_table[index]*code) /4 + step_table[index] / 8;
// 后面加的一项是为了减少误差


if (sb==1) delta="-delta";


cur_Sample+=delta; // 计算出当前的波形数据
if (cur_sample>32767) cur_sample=32767;
else if (cur_sample<-32768) cur_sample:=-32768;


output_sample(cur_sample);


index+=index_adjust[code];
if (index<0) index="0";
if (index>88) index="88";
}




---------------------------------------------------------


附表


int index_adjust[8] = {-1,-1,-1,-1,2,4,6,8};


int step_table[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 };



---------------------------------------------------------
关于 WestWood 的 .AUD 文件,结构比较简单, 这里顺带提一下, 有兴趣可以自己写处理 AUD 文件的程序 ;-) 其 8bit 的声音压缩算法尚不知晓, 但用的最广泛的 16bit 声音正是用 IMA-ADPCM 压缩, 每个 AUD 文件都有一个文件头, 结构如下:


struct {
unsigned short int samplespersec; // 频率
long int size; // 除掉文件头的大小
long int outsize; // 输出数据大小 (通常是 4 倍)
unsigned char flags; // 位 0 描述是否立体声, 位 1 描述是否 16 bit
unsigned char type; // 1=WW 压缩, 99=IMA ADPCM
}


AUD 文件的声音信号是按块存放的, 每块大约 512 字节, 没一块都有一个块头结构:


struct {
unsigned short int size; // 压缩过的数据大小
unsigned short int outsize; // 输出数据大小 (通常是 4 倍)
long int id; // 永远是 0x0000DEAF
}


---------------------------------------------------------
本文参考了 Vladan Bato 写的 AUD 文件格式描述. 可以去他的网页
http://www.geocities.com/SiliconValley/8682找到原文和他写的 AUD,WAV 转换程序.另外, Allegro 的爱好者可能想自己加入 AUD 的支持(Allegro 3.1 新增 Plug-In 支持, 增加新文件类型很方便), 不妨看看http://www.alphalink.com.au/~tjaden, 这里有完成了的 AUD 支持库.
---------------------------------------------------------


聚丰开发网址:http://www.elecfans.com/kf/

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 方案开发
    +关注

    关注

    0

    文章

    29

    浏览量

    2921
  • 电子开发者
    +关注

    关注

    0

    文章

    3

    浏览量

    3712
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    如何基于FFmpeg解码ADPCM音频

    在数字音频的浩瀚星图中,ADPCM是⼀颗低调却恒久的星,它诞生于1970年代贝尔实验室的走廊,见证了从电话交换机到 PlayStation 游戏机的沧桑变迁,如今依然在工业控制器的蜂鸣声、监控录像
    的头像 发表于 01-27 16:39 966次阅读
    如何基于FFmpeg解码<b class='flag-5'>ADPCM</b>音频

    【瑞萨RA6E2地奇星开发板试用】4、PWM模块的音频播放功能

    PWM模块播放音频,适合语音提示、简单音效等对音质要求不高的应用,是成本敏感的嵌入式系统提供音频解决方案 瑞萨RA6E2提供了PWM模块的音频播放功能。通过使用ADPCM模块来解码PCM数据。将该
    发表于 12-26 09:14

    linux的压缩和解压操作

    进行压缩,然后传输压缩的文件,这样可以减少文件传输所需要的带宽和时间,在网络接收到文件之后再解压,就可以得到文件了。 文件的压缩有两种方式:有损压缩和无损
    发表于 12-23 06:56

    电能质量在线监测装置数据压缩对装置性能有哪些影响?

    电能质量在线监测装置的数据压缩功能对性能的影响 总体可控且轻微 ,核心集中在「CPU 占用、内存消耗、存储读写速度、数据传输延迟」四大维度,且通过厂商优化(硬件加速、算法选型、资源调度)可将负面影响
    的头像 发表于 12-17 10:28 489次阅读
    电能质量在线监测装置<b class='flag-5'>数据压缩</b>对装置性能有哪些影响?

    如何配置电能质量在线监测装置的数据压缩存储功能?

    现代电能质量在线监测装置普遍支持数据压缩存储,可显著节省存储空间 (2-20 倍) 和传输流量。配置步骤如下: 一、配置前准备 1. 确认装置支持情况 高端装置 (电网侧):标配硬件压缩模块
    的头像 发表于 12-17 10:26 622次阅读
    如何配置电能质量在线监测装置的<b class='flag-5'>数据压缩</b>存储功能?

    电能质量在线监测装置支持哪些数据压缩算法?

    电能质量在线监测装置支持 无损压缩 和 有损压缩 两大类算法,适配不同数据类型(实时数据、历史数据、波形
    的头像 发表于 12-12 14:08 677次阅读
    电能质量在线监测装置支持哪些<b class='flag-5'>数据压缩</b>算法?

    电能质量在线监测装置的数据压缩存储功能对数据传输速度的影响有多大?

    电能质量在线监测装置的数据压缩存储功能对数据传输速度的影响,可通过 量化对比 + 场景拆解 明确: 绝大多数场景下传输速度提升 50%~80%(低带宽场景甚至超 90%),仅软件压缩的小文件传输或
    的头像 发表于 12-11 16:45 1445次阅读
    电能质量在线监测装置的<b class='flag-5'>数据压缩</b>存储功能对<b class='flag-5'>数据</b>传输速度的影响有多大?

    电能质量在线监测装置的数据压缩存储功能对数据传输速度有影响吗?

    电能质量在线监测装置的数据压缩存储功能对数据传输速度的影响是 “双刃剑” : 核心正面影响: 压缩数据量减小,大幅降低传输带宽需求,缩短传输时间 (尤其适用于大文件如暂态录波、历史
    的头像 发表于 12-11 16:43 1347次阅读
    电能质量在线监测装置的<b class='flag-5'>数据压缩</b>存储功能对<b class='flag-5'>数据</b>传输速度有影响吗?

    电能质量在线监测装置的数据压缩存储功能支持的数据格式可以修改吗?

    电能质量在线监测装置的数据压缩存储功能支持的数据格式 部分可修改 ,具体取决于格式类型(数据文件格式 / 压缩算法格式)与厂家设计,核心结论如下: 一、
    的头像 发表于 12-11 16:39 1219次阅读
    电能质量在线监测装置的<b class='flag-5'>数据压缩</b>存储功能支持的<b class='flag-5'>数据</b>格式可以修改吗?

    应用于暂态波形存储的数据压缩算法需要考虑哪些因素?

    应用于暂态波形存储的数据压缩算法,需围绕 暂态波形特性 (突变性、关键特征依赖性)、 工业场景需求 (实时性、硬件限制)及 数据应用价值 (故障溯源、合规性)综合考量,核心需关注以下六大维度: 一
    的头像 发表于 11-05 15:02 440次阅读

    如何进行声音定位?

    文章主要介绍了如何利用一种简单的TDOA算法进行声音点位,并使用数据采集卡进行声音定位的实验。
    的头像 发表于 09-23 15:47 2134次阅读
    如何进行<b class='flag-5'>声音</b>定位?

    氢气压缩机PLC数据采集系统解决方案

    ,包括启停、转速、压力、温度、流量等,确保设备安全稳定运行。 然而,随着生产规模的扩大和智能化管理需求的提升,企业面临着数据孤岛、远程监控不足、故障预警滞后等挑战。为解决这些问题,物通博联提供基于PLC智能网关的压缩
    的头像 发表于 08-15 17:15 1048次阅读
    氢气<b class='flag-5'>压缩</b>机PLC<b class='flag-5'>数据</b>采集系统解决方案

    声源定位模块-AR1105# 声源定位# 声音定位

    声音降噪
    深圳市声讯电子有限公司
    发布于 :2025年08月01日 16:01:09

    低内存场景下的高效压缩利器:FastLZ压缩库应用实践指南

    联网设备等场景的严苛需求。 FastLZ ——是一款高效且小巧的开源压缩库,主要用于实现基于LZ77算法的字节对齐数据压缩。LZ77(Lempel-Ziv 1977)是数据压缩领域的一种经典
    的头像 发表于 07-22 15:13 503次阅读
    低内存场景下的高效<b class='flag-5'>压缩</b>利器:FastLZ<b class='flag-5'>压缩</b>库应用实践指南

    谐波怎么处理最简单方法

    谐波问题是电力系统中常见的电能质量问题,它不仅影响设备正常运行,还可能造成能源浪费和设备损坏。针对谐波处理的最简单方法,我们可以从以下几个方面入手: 一、理解谐波产生的原因 谐波主要由非线性负载产生
    的头像 发表于 07-13 16:35 4249次阅读
    谐波怎么处理最<b class='flag-5'>简单</b>的<b class='flag-5'>方法</b>