G.711编码原理

2023-05-16

目录

  1. 参考
  2. 概述
  3. G.711原理
  4. 总结

1. 参考

  • [1] wikipedia/A-law_algorithm
  • [2] github.com/quatanium/foscam-ios-sdk
  • [3] charybdis/G711算法学习

2. 概述

本文目的:
1、熟悉G711a/u两种格式的基本原理
2、熟悉两种压缩算法的实现步骤及提供源码实现

G.711是国际电信联盟ITU-T定制出来的一套语音压缩标准,它代表了对数PCM(logarithmic pulse-code modulation)抽样标准,是主流的波形声音编解码标准,主要用于电话。

  1. 主要用脉冲编码调制对音频采样,采样率为8k每秒。它利用一个 64Kbps 未压缩通道传输语音讯号。
  2. 压缩率为1:2, 即把16位成8位。

G.711 标准下主要有两种压缩算法。

  1. u-law algorithm (又称u-law, ulaw, mu-law),主要运用于北美和日本。
  2. A-law algorithm,主要运用于欧洲和世界其他地区。特别设计用来方便计算机处理的。

G.711将14bit(uLaw)或者13bit(aLaw)采样的PCM数据编码成8bit的数据流,播放的时候在将此8bit的数据还原成14bit或者13bit进行播放,不同于MPEG这种对于整体或者一段数据进行考虑再进行编解码的做法,G711是波形编解码算法,就是一个sample对应一个编码,所以压缩比固定为:

  • 8/14 = 57% (uLaw)
  • 8/13 = 62% (aLaw)

3. G.711原理

G.711是将语音模拟信号进行一种非线性量化, 详细的资料可以在ITU 上下到相关的spec 。下面主要列出一些性能参数:
G.711(PCM方式)

  • 采样率:8kHz
  • 信息量:64kbps/channel
  • 理论延迟:0.125msec
  • 品质:MOS值4.10

算法原理:
A-law的公式如下,一般采用A=87.6

画出图来则是如下图,用x表示输入的采样值,F(x)表示通过A-law变换后的采样值,y是对F(x)进行量化后的采样值。

由此可见

  • 在输入的x为高值的时候,F(x)的变化是缓慢的,有较大范围的x对应的F(x)最终被量化为同一个y,精度较低。
  • 相反在低声强区域,也就是x为低值的时候,F(x)的变化很剧烈,有较少的不同x对应的F(x)被量化为同一个y。意思就是说在声音比较小的区域,精度较高。

对应反量化公式(即上面函数的反函数):

3.1 G.711A(A-LAW)压缩十三折线法

G.711A输入的是13位(S16的高13位),这种格式是经过特别设计的,便于数字设备进行快速运算。

  1. 取符号位并取反得到s。
  2. 获取强度位eee,获取方法如下图所示
  3. 获取高位样本位wxyz
  4. 组合为seeewxyz,将seeewxyz逢偶数为取补数。

A-law如下表计算。

  • 第一列是采样点,共13bit,最高位为符号位。
  • 对于前两行,折线斜率均为1/2,跟负半段的相应区域位于同一段折线上。
  • 对于3到8行,斜率分别是1/4到1/128,共6段折线。
  • 总共13段折线,这就是所谓的A-law十三段折线法。

示例:

输入pcm数据为1234,二进制对应为(0000 0100 1101 0010)
二进制变换下排列组合方式(0 00001 0011 010010)
1、获取符号位最高位为0,取反,s=1
2、获取强度位00001,查表,编码制应该是eee=011
3、获取高位样本wxyz=0011
4、组合为10110011,逢偶数为取反为11100110,得到E6

#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. */
static int seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
                0x1FF, 0x3FF, 0x7FF, 0xFFF};
static int seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
                0x3FF, 0x7FF, 0xFFF, 0x1FFF};
 
static int search(
    int val,    /* changed from "short" *drago* */
    int *   table,
    int size)   /* changed from "short" *drago* */
{
    int i;      /* changed from "short" *drago* */
 
    for (i = 0; i < size; i++) {
        if (val <= *table++)
            return (i);
    }
    return (size);
}
 
int linear2alaw(int pcm_val)        /* 2's complement (16-bit range) */
                                        /* changed from "short" *drago* */
{
    int     mask;   /* changed from "short" *drago* */
    int     seg;    /* changed from "short" *drago* */
    int     aval;
 
    pcm_val = pcm_val >> 3;//这里右移3位,因为采样值是16bit,而A-law是13bit,存储在高13位上,低3位被舍弃
 
 
    if (pcm_val >= 0) {
        mask = 0xD5;        /* sign (7th) bit = 1 二进制的11010101*/
    } else {
        mask = 0x55;        /* sign bit = 0  二进制的01010101*/
        pcm_val = -pcm_val - 1; //负数转换为正数计算
    }
 
    /* Convert the scaled magnitude to segment number. */
    seg = search(pcm_val, seg_aend, 8); //查找采样值对应哪一段折线
 
    /* Combine the sign, segment, and quantization bits. */
 
    if (seg >= 8)       /* out of range, return maximum value. */
        return (0x7F ^ mask);
    else {
//以下按照表格第一二列进行处理,低4位是数据,5~7位是指数,最高位是符号
        aval = seg << SEG_SHIFT;
        if (seg < 2)
            aval |= (pcm_val >> 1) & QUANT_MASK;
        else
            aval |= (pcm_val >> seg) & QUANT_MASK;
        return (aval ^ mask);
    }
}

int alaw2linear(int a_val)      
{
    int     t;      /* changed from "short" *drago* */
    int     seg;    /* changed from "short" *drago* */
 
    a_val ^= 0x55; //异或操作把mask还原
 
    t = (a_val & QUANT_MASK) << 4;//取低4位,即表中的abcd值,然后左移4位变成abcd0000
    seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; //取中间3位,指数部分
    switch (seg) {
    case 0: //表中第一行,abcd0000 -> abcd1000
        t += 8;
        break;
    case 1: //表中第二行,abcd0000 -> 1abcd1000
        t += 0x108;
        break;
    default://表中其他行,abcd0000 -> 1abcd1000 的基础上继续左移(按照表格第二三列进行处理)
        t += 0x108;
        t <<= seg - 1;
    }
    return ((a_val & SIGN_BIT) ? t : -t);
}

3.2 G.711u(u-law)

使用在北美和日本,输入的是14位,编码算法就是查表,计算出:基础值+平均偏移值

μ-law的公式如下,μ取值一般为255

 

 

相应的μ-law的计算方法如下表

示例:
输入pcm数据为1234
1、取得范围值,查表得 +2014 to +991 in 16 intervals of 64
2、得到基础值为0xA0
3、得到间隔数为64
4、得到区间基本值2014
5、当前值1234和区间基本值差异2014-1234=780
6、偏移值=780/间隔数=780/64,取整得到12
7、输出为0xA0+12=0xAC

#define BIAS        (0x84)      /* Bias for linear code. 线性码偏移值*/
#define CLIP            8159    //最大量化级数量
 
int linear2ulaw( int    pcm_val)    /* 2's complement (16-bit range) */
{
    int     mask;
    int     seg;
    int     uval;
 
    /* Get the sign and the magnitude of the value. */
    pcm_val = pcm_val >> 2;
    if (pcm_val < 0) {
        pcm_val = -pcm_val;
        mask = 0x7F;
    } else {
        mask = 0xFF;
    }
        if ( pcm_val > CLIP ) pcm_val = CLIP;       /* clip the magnitude 削波*/
    pcm_val += (BIAS >> 2);
 
    /* Convert the scaled magnitude to segment number. */
    seg = search(pcm_val, seg_uend, 8);
 
    /*
     * Combine the sign, segment, quantization bits;
     * and complement the code word.
     */
    if (seg >= 8)       /* out of range, return maximum value. */
        return (0x7F ^ mask);
    else {
        uval = (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
        return (uval ^ mask);
    }
 
}
 
int ulaw2linear( int    u_val)
{
    int t;
 
    /* Complement to obtain normal u-law value. */
    u_val = ~u_val;
 
    /*
     * Extract and bias the quantization bits. Then
     * shift up by the segment number and subtract out the bias.
     */
    t = ((u_val & QUANT_MASK) << 3) + BIAS;
    t <<= (u_val & SEG_MASK) >> SEG_SHIFT;
 
    return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}

3.2 A-law和u-law对比

A-law和u-law画在同一个坐标轴中就能发现A-law在低强度信号下,精度要稍微高一些。

实际应用中,我们确实可以用浮点数计算的方式把F(x)结果计算出来,然后进行量化,但是这样一来计算量会比较大,实际上对于A-law(A=87.6时),是采用13折线近似的方式来计算的,而μ-law(μ=255时)则是15段折线近似的方式。

4. 总结

G711尽管是一种非常古老的话音编码算法,原理和计算也比较简单,但是其中用到的一些基本原理同样在其他编码算法中得到了应用,对其进行深入的了解有助于更好的理解其他的算法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

G.711编码原理 的相关文章

  • Android Studio aar包引用方式

    主工程 第一种方式 1 将aar包复制到app libs目录下 2 在app的build gradle文件中配置如下 xff1a android repositories flatDir dirs 39 libs 39 implementa
  • MacOs “无法打开***,因为无法验证开发者...”

    在终端执行如下指令 sudo spctl master disable 执行完上面指令后 xff0c 在 安全性与隐私 设置的 允许从以下位置下载的App 中会新增一个任何来源 xff0c 如下面的对比图 xff0c 然后应用在运行中就不会
  • mac编译android源码-创建磁盘映像

    因为mac默认的磁盘环境是不区分大小的 xff0c 而git并不支持此类文件系统 xff0c 所以我们需要创建我们所需要的磁盘映像用来存放下载的源码 首先你需要找在mac上的磁盘工具 xff0c 一般是在应用程序列表 其他文件夹里面 2 如
  • android源码编译-如何在Mac中卸载openjdk15

    说明 之前在mac上使用intellij idea时 xff0c 由于没有在Mac上安装过jdk xff0c 所以就在intellij idea中下载了openjdk15版本 后来觉得想要换一个旧点的版本 xff0c 就想卸载了openjd
  • Mac OS查看和设置JAVA_HOME

    下载java https www java com zh CN download 1 查看JAVA版本 打开Mac电脑 xff0c 查看JAVA版本 xff0c 打开终端Terminal xff0c 通过命令行查看笔者的java版本 xff
  • Android源码编译–jdk版本查询

    2 1 Android源码所需JDK版本 根参考资料 1 的说明 xff0c 在android src build core main mk中对jdk的版本进行查询 xff0c 以确定当前系统是否安装了特定版本的jdk xff0c 因此可以
  • android源码编译 ninja: build stopped: subcommand failed.

    接着编译 make j8 线程加多少个具体看机器配置 xff0c 问题也最可能是这一步骤引起的 xff0c 如果是虚拟机的话 xff0c 建议不要加线程 xff0c 直接使用make执行
  • Ubuntu环境下完美安装python模块numpy,scipy,matplotlib

    不同的ubuntu版本安装过这三个模块几次了 xff0c 然而总是出现各种问题 xff0c 最近一次是在ubuntu 16 04 LTS server版本安装的 xff0c 总的来说安装的比较顺利 先把pip安装好 sudo apt get
  • prebuilts/misc/darwin-x86/bison/bison: Bad CPU type in executable

    方案一 cd external bison touch patch high sierra patch vim patch high sierra patch With format string strictness High Sierr
  • android源码编译 坑

    bash lunch command not found 先调用 build envsetup sh 再执行 lunch Can not find SDK Can not find SDK 10 6 at Developer SDKs Ma
  • 获取当前MacOSX SDK

    xcrun show sdk path 打印出 Library Developer CommandLineTools SDKs MacOSX sdk xcrun show sdk version 打印出 10 15 4 xcode sele
  • Mac OS10.12 编译Android源码8.1

    内容 介绍mac os10 12拉取android源码 xff0c 并且编译后 xff0c 刷入手机的过程 下载的rom是android 8 1 xff0c 手机是pixel 准备工作 硬盘大小 本人Mac磁盘空间只有256GB xff0c
  • android源码 xcode版本,【Android】AOSP源码下载及编译 for mac

    本文记录了AOSP在Mac系统上下载和编译的过程 采用的系统是 macOS 10 13 1 所使用的AOSP分支是 android 8 1 0 r7 系统预留空间 大于200G 一 环境配置 环境配置 xff0c 官网给出了非常全的教程 x
  • (Android 9.0)Activity启动流程源码分析

    前言 熟悉Activity的启动流程和运行原理是一个合格的应用开发人员所应该具备的基本素质 xff0c 其重要程度就不多做描述了 同时 xff0c 知识栈应该不断的更新 xff0c 最新发布的Android 9 0版本相较于之前的几个版本也
  • Lifecycle 源码详解

    Lifecycle 是 Jetpack 整个家族体系内最为基础的内容之一 xff0c 正是因为有了 Lifecycle 的存在 xff0c 使得如今开发者搭建依赖于生命周期变化的业务逻辑变得简单高效了许多 xff0c 使得我们可以用一种统一
  • git常用命令

    1 拉取远程所有分支 git clone xxx git branch r grep v 39 gt 39 while read remote do git branch track 34 remote origin 34 34 remot
  • Android应用启动流程分析

    1 前言 网上看过很多Activity启动过程的源码解析 xff0c 很多文章会贴上一大段代码 xff0c 然后从startActivity 函数开始深究整个源码的调用栈 个人感觉这类文章代码细节太多 xff0c 反而容易迷失在源码调用之中
  • 从一个分支cherry-pick多个commit到其他分支

    在branch1开发 xff0c 进行多个提交 xff0c 这是切换到branch2 xff0c 想把之前branch1分支提交的commit都 复制 过来 xff0c 怎么办 xff1f 单个commit只需要git cherry pic
  • IntWritable详解

    1 Hadoop数据类型如下图 xff1a 由上图的Writable层次结构图可以看到绝大多数的数据类型都实现了Writable WritableComparable接口 xff0c 在此先分析一下这两个接口情况 自顶下下逐步分析 Writ
  • 线程池源码剖析

    线程池 xff08 英语 xff1a thread pool xff09 xff1a 一种线程使用模式 线程过多会带来调度开销 xff0c 进而影响缓存局部性和整体性能 而线程池维护着多个线程 xff0c 等待着监督管理者分配可并发执行的任

随机推荐

  • Java 设计模式之装饰者模式

    一 了解装饰者模式 1 1 什么是装饰者模式 装饰者模式指的是在不必改变原类文件和使用继承的情况下 xff0c 动态地扩展一个对象的功能 它是通过创建一个包装对象 xff0c 也就是装饰者来包裹真实的对象 所以装饰者可以动态地将责任附加到对
  • Java 设计模式之策略模式

    一 了解策略模式 1 1 什么是策略模式 策略模式 Strategy Pattern 是指对一系列的算法定义 xff0c 并将每一个算法封装起来 xff0c 而且使它们还可以相互替换 此模式让算法的变化独立于使用算法的客户 1 2 策略模式
  • Java 设计模式之适配器模式

    一 了解适配器模式 1 1 什么是适配器模式 适配器模式将一个类的接口 xff0c 转换成客户期望的另一个接口 适配器让原来接口不兼容的类可以合作无间 适配器模式有两种 xff1a 对象 适配器和 类 适配器 这个模式可以通过创建适配器进行
  • 责任链模式

    责任链模式的定义与特点 责任链模式的定义 xff1a 使多个对象都有机会处理请求 xff0c 从而避免请求的发送者和接受者之间的耦合关系 xff0c 将这个对象连成一条链 xff0c 并沿着这条链传递该请求 xff0c 直到有一个对象处理他
  • java设计模式-桥接模式

    桥接模式定义 桥接模式 xff08 Bridge Pattern xff09 xff0c 将抽象部分与它的实现部分分离 xff0c 使它们都可以独立地变化 更容易理解的表述是 xff1a 实现系统可从多种维度分类 xff0c 桥接模式将各维
  • java设计模式-状态模式

    1 状态模式的定义和特点 状态 xff08 State xff09 模式的定义 xff1a 对有状态的对象 xff0c 把复杂的 判断逻辑 提取到不同的状态对象中 xff0c 允许状态对象在其内部状态发生改变时改变其行为 状态模式是一种对象
  • java设计模式-命令模式

    18 xff0c 命令模式 18 1 命令模式的定义和特点 命令 xff08 Command xff09 模式的定义如下 xff1a 将一个请求封装为一个对象 xff0c 使发出请求的责任和执行请求的责任分割开 这样两者之间通过命令对象进行
  • java设计模式-代理模式

    17 xff0c 代理模式 17 1 代理模式的定义和特点 代理模式的定义 xff1a 由于某些原因需要给某对象提供一个代理以控制对该对象的访问 这时 xff0c 访问对象不适合或者不能直接引用目标对象 xff0c 代理对象作为访问对象和目
  • 工厂方法模式

    概念定义 工厂方法 Factory Method 模式 xff0c 又称多态工厂 Polymorphic Factory 模式或虚拟构造器 Virtual Constructor 模式 工厂方法模式通过定义工厂抽象父类 或接口 负责定义创建
  • TextFuseNet: Scene Text Detection with Richer Fused Features论文阅读

    TextFuseNet Scene Text Detection with Richer Fused Features 利用更丰富的特征融合进行场景文本检测 代码 xff1a https github com ying09 TextFuse
  • JUC原子类: CAS, Unsafe和原子类详解

    CAS 线程安全的实现方法包含 互斥同步 synchronized 和 ReentrantLock非阻塞同步 CAS AtomicXXXX无同步方案 栈封闭 xff0c Thread Local xff0c 可重入代码 什么是CAS CAS
  • OKHttp中的责任链模式

    一 什么是责任链模式 责任链 xff0c 顾名思义是将多个节点通过链条的方式连接起来 xff0c 每一个节点相当于一个对象 xff0c 而每一个对象层层相关 xff0c 直接或者间接引用下一个对象 xff08 节点 xff09 xff1b
  • android bugly关于混淆后如何知道正确代码

    bugly xff1a 腾讯自制 xff0c 是个4 xff0c 5句代码就能简单加入在线更新 捕获异常的好功能 xff0c 后台也是使用腾讯的 Android混淆 xff1a 启用一个配置 xff0c 把所有变量 类名改成 34 a 34
  • 大康Dacom Athlete+蓝牙耳机与手机配对上的原因及解决办法:

    1 原因 xff1a 蓝牙耳机没有进入配对模式 解决办法 xff1a 蓝牙耳机都有一个功能键 xff0c 长按听到开机提示音后不要松手 xff0c 继续长按 xff0c 直至听到进入配对模式提示音或者 滴 的提示音 xff0c 此时蓝红等交
  • android查看编译后的class文件

    其查看目录如下 然后在硬盘文件中打开 xff0c 可以看到详细的class文件列表
  • socket的shutdownInput和shutdownOutput

    虽然在大多数的时候可以直接使用Socket类或输入输出流的close方法关闭网络连接 xff0c 但有时我们只希望关闭OutputStream或InputStream xff0c 而在关闭输入输出流的同时 xff0c 并不关闭网络连接 这就
  • 使用广播接收器时,onReceive 会多次执行

    原因一 xff1a 没有在onDestory中调用解注册 unregisterReceiver 原因二 xff1a BroadcastReceiver变量所在的Activity或者Fragment被创建的多次 xff0c 形成多个对象
  • Android Studio自动生成单例代码

    AS中有可以自己设置代码模板 xff0c 使用起来简单方便 同样的 xff0c 单例类的代码样式统一 xff0c 除了类名外全部一致 所以使用模板更加方便 在设置中的Editor Live Template中新建模板 xff0c 然后把单例
  • android:excludeFromRecents 属性需要注意的小地方

    在 Android 系统中 xff0c 如果我们不想某个 Activity 出现在 Recent screens 中 xff0c 可以设置 lt activity gt 属性 android excludeFromRecents 为 tru
  • G.711编码原理

    目录 参考概述G 711原理总结 1 参考 1 wikipedia A law algorithm 2 github com quatanium foscam ios sdk 3 charybdis G711算法学习 2 概述 本文目的 x