当前位置: 首页 > news >正文

A律十三折线法G711编解码介绍

A律十三折线法G711编解码介绍


简介

在这里插入图片描述

G711国际电信联盟ITU-T定制出来的一套语音压缩标准,主要用于对PCM音频数据编码,将PCM16bit数据压缩为为8Bit,它是主流的波形音频编码器,相当于只在帧内压缩,不会从帧间之间来考虑压缩,输出码率通常大于32kbps,所以推荐输入信号码率为64kbps,8Khz和S16的采样格式,压缩比为1:2;

G711有两套编码标准A-law用于13bit压缩为8bit,u-law则是用于15bit压缩为8bit;前者主要用于北美和中国地区,后者则用于欧美和日本地区;


数学原理

简单来说,G711可以将16Bit数据压缩为8Bit数据。编码有两种A-law和u-law,A-law编码针对计算机做了设计处理,将13Bit压缩为8Bit,而u-law则是15Bit数据压缩;国内通用前者,所以我们以A-law为例讲解,它的函数公式:

A=87.6时,函数图像接近原点,函数图像如下:
在这里插入图片描述
该函数图中,X表示输入信号,Y表示输出信号,且均归一化到(-1, +1)区间;将x轴(0,1)非均匀量化为为8段1/2、1/4、… 1/64、1/128最终到原点0,共8段;同理每段对应到Y轴上也有8段,并且x负轴也分为这相同的8段,在原点(0,0)处,-1/64到+1/64是实质是相同的斜率,可归纳一个段,加上剩余的12段,也就是十三段,经过十三折线后的函数图像不再像上图的曲线,而是一段段的直线连接,折线图逼近A-law曲线图,故称十三折线法;并且十三段折线对应不同的斜率,在值较小时,曲线斜率近似于折线,精度较高,而值较大时,则曲线斜率与折线相差较大,精度较低

在以上基础上,我们将每一个(如1-1/2、1/2-1/4)大段称为“段落”,在每个段落内部实现均分16分,这样在X轴上(-1,+1)就有16个段落 * 16个均分 = 256个量级;对应到Y轴上也是256个量级,这样我们就将输入信号编码离散化到256个量级范围,刚好是8Bit,也就是编码后的值范围在256量级,也就是8Bit;而输入端X,我们段落之间非均匀化划分,段内16分均匀划分,这种均匀-非均匀量化范围可以0~2048(12bit)的范围,加上还有负数的情况(1bit极性),所以我们输入信号可以对13bit的数据进行编码,按照这种原理进行量化的表格如下:

量化范围归一化段落码(3bit)权重值
0~160~1/1280 0 08 4 2 1
16~321/128~1/640 0 18 4 2 1
32-641/64~1/320 1 016 8 4 2
64~1281/32~1/160 1 132 16 8 4
128~2561/16~1/81 0 064 32 16 8
256~5121/8~1/41 0 1128 64 32 16
512~10241/4~1/21 1 0256 128 64 32
1024~20481/2~11 1 1512 256 128 64

总段落实质是16个段落,8个正8个负,负数情况下转为正进行查表,同时记录正负极性

而段内码是均匀划分,表格如何:

量化范围段内码(4bit)
00x0
10x1
20x2
150xf

拥有上面两张表后,我们就可以实现对输入信号进行编码压缩了,上面段落码+段内码一共才7bit,还差一位bit,这个就是信号的极性,正负了;

例如,输入信号2000,请问输出编码是多少?

  • 确定段落码
    2000在1024~2048段,所以段落码是1 1 1
  • 确定段内码
    2000 - 1024 = 976,1024~2048段内权重值为512 256 128 64,也就是512x + 256y+128z + 64w趋近于976,最终x=1,y=1,z=1,w=1;
  • 极性取反2000的符号位是0,所以极性为1
    最终2000的编码值为1 1 1 1 1 1 1 1 = 0xff

计算机实现

以上是十三折线法原理,但是转化到计算机上来还是有区别的,例如我们一般存储数据类型都是8的倍数类型存储,如short类型就是16bit,但是十三折线是针对13bit的数据压缩,这个时候就需要自行处理,移除低位3bit或者高位3bit,根据自己的需求处理;并且计算机处理做了特殊的改动,以下表为准:

在这里插入图片描述

  • Linear Input code 代表输入的十三bit信号值,s是符号位0…1代表序号位,abcd代表强度位,x是会移除的bit
  • Compressed code是经过压缩编码后的数据,s取反,0…1表示输入的序号位,高位第一个1的位置,abcd则是输入保留下来的
  • Linear output code是逆过程,解码后的数据,s恢复,abcd恢复,输入x则只会添1做补偿,其他为0,这块也就是误差值存在

所以,按照上述表格,进行编码的步骤:

  1. 获取符号位
  2. 确定序号位的第一个高位1的位置,并确定序号编码
  3. 获取强度为abcd,也就是序号位后紧跟的4bit
  4. 最后还需要进行异或处理

最后,贴源码,网上有很多,我也是参考别人的,因为已经写得很好了,没必要自己在去重新实现:

#define         SIGN_BIT        (0x80)      /* Sign bit for a A-law byte. */
#define         QUANT_MASK      (0xf)       /* Quantization field mask. */
#define         NSEGS           (8)         /* Number of A-law segments. */
#define         SEG_SHIFT       (4)         /* Left shift for segment number. */
#define         SEG_MASK        (0x70)      /* Segment field mask. */
#define         BIAS            (0x84)      /* Bias for linear code. */
#define         CLIP            8159#define         G711_A_LAW      (0)
#define         G711_MU_LAW     (1)
#define         DATA_LEN        (16)
确定序号位的顺序index 
static short seg_aend[8] = { 0x1F, 0x3F, 0x7F, 0xFF,0x1FF, 0x3FF, 0x7FF, 0xFFF
};
编码函数
unsigned char linear2alaw(int pcm_val)
{int mask;int seg; unsigned char aval;移除低位3bitpcm_val = pcm_val >> 3;根据值正负确定mask掩码if (pcm_val >= 0) {mask = 0xD5;/* sign (7th) bit = 1 */} else {mask = 0x55;/* sign bit = 0 */因为十三折线输入信号正负范围都是一样的,但是有符号的类型如char-128~+127负数是多一位,这里减一刚好和正数对应,并且pcm_val变为正值了,对应去编码pcm_val = -pcm_val - 1;}查找序号位indexseg = search(pcm_val, seg_aend, 8);编码超过最大值,去范围内最大值0x7fif (seg >= 8)/* out of range, return maximum value. */return (unsigned char) (0x7F ^ mask);else {  aval = (unsigned char) seg << SEG_SHIFT;为什么要分两种情况?seg为2说明序号位位于第一位,再他后面只有5个bit了,只能移动一位if (seg < 2) aval |= (pcm_val >> 1) & QUANT_MASK;seg大于2情况右移seg个bit,只保留其后4位强度位即可else    aval |= (pcm_val >> seg) & QUANT_MASK;异或处理返回     return (aval ^ mask);}
}
解码过程
int alaw2linear(unsigned char a_val)
{int t;int seg;得到偶数位异或后的值a_val ^= 0x55;获取强度位4bit,并且左移动4位,强度位也已经在编码前的位置了t = (a_val & QUANT_MASK) << 4;获取序号位,也就是符号位后面第几位是1seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;switch (seg) {符号位全为0的情况,说明编码之前的值很小,而t是强度位保留下来了,就补偿加88刚好是一个字节低4位的最大值,当做补偿case 0:t += 8;break;符号位为1,说明7位序号位刚好最后一位是1 也就是0x0100 中间强度位刚好4个字节为t 低4位补偿8      case 1:printf("i'm here");t += 0x108;break;default:其他符号位则以序号位为1的情况进行左移动,将序号位移动到正确的位置上去t += 0x108;t <<= seg - 1;}根据符号位确定返回正负值return ((a_val & SIGN_BIT) ? t : -t);
}

以上就是A-law的算法原理以及实现过程,u-law是15折线法,和A-law原理差不多,感兴趣的可以自行去研究,这里就不再阐述了!


参考文献

关于二进制的基础知识
PCM的A律13折线编码介绍
通信原理之13折线


http://www.taodudu.cc/news/show-4320640.html

相关文章:

  • acw165. 小猫爬山-DFS剪枝与优化
  • kotlin基础知识
  • Shell变成规范与变量
  • 在虚机VirtualBox7.0.8安装Androidx86_64系统详细步骤要点
  • 【文末福利送资料】深度探索GPT模型,竟然10个字都不会说?
  • Android之实现《用户隐私政策》《服务条款》等文字点击可查看协议内容的超链接功能
  • 餐饮SaaS行进时:美团To B,二维火To C
  • 数据挖掘基础
  • 类美团外卖、骑手、类快递取餐柜、整合菜品供应商、前厅、后厨、配送、智能厨电设备的智慧餐饮业务
  • (精品)基于Web的酒店客房管理系统的设计与实现毕业论文+开题报告+项目源码(SSM)及数据库+查重报告
  • 速卖帮AI点餐流程 AI菜品识别结账
  • golang并发http请求几种方式
  • python行业中性_用Python分析指数: 11月16日热门指数Z值表
  • 各类ETF跟踪指数的数据统计分析
  • 右侧追击(二)——券商行业
  • windows 防火墙解除或禁止ping方法
  • windows防火墙 程序_如何允许应用程序通过Windows防火墙进行通信
  • windows防火墙开启后,设置准入端口
  • windows 防火墙日志_如何使用Windows防火墙日志跟踪防火墙活动
  • 告别神秘客,人力成本节约90%,DuDuTalk工牌用AI帮你智慧巡店
  • 美团拍店,一个“顺道”赚钱的小项目,去饭店的路上,饭钱有了
  • 扔硬币中的思考——隐含变量建模
  • 猪猪的机器学习笔记(一)微积分和概率论
  • 密码学之PRP/PRF转换引理
  • spark while_while循环怎么理解
  • JAVA后端面经总结——应用类
  • 《Effective C++》第三版 第六章 继承与面向对象设计 32~35条例
  • 30岁以后搞Android已经没有前途?复习指南
  • 小程序FMP优化实录,附小技巧
  • 用计算机核裂变模拟实验,SAS和蒙特卡罗模拟(1):开篇
  • 一些场景题
  • Mathorcup数学建模竞赛第六届-【妈妈杯】B题:小区车位分布的评价和优化模型(附特等奖获奖论文和Java代码)
  • 国科大2019年大数据分析课件作业 考试-程学旗 靳小龙 刘盛华
  • 新加坡国立大学计算机系访学,高盛华课题组徐衍钰(博)2019年8月-2020年1月于新加坡国立大学交流访学...
  • 日媒:争夺中国人才,跨国公司败北
  • 为什么那么多公司都选择灵活用工?