本文对 G.722.1 的编码器作以介绍,如有表述不当之处欢迎批评指正。欢迎任何形式的转载,但请务必注明出处。

目录

  • 引言
  • 简介
  • 编码器
    • 1. 计算、量化和编码 MLT 的幅度包络
      • 1-1. MLT 重叠调制变换
      • 1-2. 计算、量化 MLT 的幅度包络
      • 1-3. 编码 MLT 的幅度包络
    • 2. 确定编码方法、量化和编码 MLT 的系数
      • 2-1. 产生 16 组不同的编码(分类)方法
      • 2-2. 归一化、量化和编码 MLT 系数
    • 3. 细节
      • 3-1. 符号比特
      • 3-2. 确定最终编码方法
      • 3-3. 比特流模块
    • 4. 总结

引言

由于工作需要接触了一段时间的音频编解码算法 G.722.1,在此作以记录。

简介

  • G.722.1 是一种基于变换域编码的算法
  • 采样率: 16000hz
  • 比特率: 24kbit/s,32kbit/s
  • 变换域: MLT(Modulated Lapped Transform)
  • 帧长: 20ms
  • 变换窗长: 40ms
  • 有效编码带宽: 50~7000hz

编码器

图1 G.722.1 编码器方框图

上图展示了 G.722.1 的编码过程, 主要包含三个模块:

  • 对 MLT 的幅度包络进行计算、量化和编码
  • 确定编码方法,并对 MLT 的系数进行归一化、量化和编码

下面详细分析这几个模块所做的事情。

1. 计算、量化和编码 MLT 的幅度包络

1-1. MLT 重叠调制变换

MLT 是一个严格抽样,完美重建的线形变换过程(引用自 G.722.1 官方文档中文版)此处不介绍具体公式。前一帧 320 个采样点与当前帧 320 个采样点拼接为 640 个采样点作为 MLT 变化的输入,MLT 变换输出 320 个系数。
mlt(m),0≤m<320mlt(m), 0\leq{m}<320mlt(m),0≤m<320

1-2. 计算、量化 MLT 的幅度包络

将 MLT 输出的 320 个系数平均分为 16 个区域,每个区域包含 20 个系数,对应 500hz 带宽,但编码器只对前 14 个区域也就是 0~7000hz 进行编码。

首先根据以下公式计算每个区域的幅度包络:
rms(r)=120∑j=019mlt(20r+j)mlt(20r+j),0≤r<14rms(r) = \sqrt{\frac{1}{20}\sum_{j=0}^{19}mlt(20r+j)mlt(20r+j)}, 0\leq{r}<14rms(r)=201​j=0∑19​mlt(20r+j)mlt(20r+j)​,0≤r<14

利用以下量化集合对上述 14 个区域的幅度包络进行量化,生成量化索引 rms_index(r),0≤r<14rms\_index(r),0\leq{r}<14rms_index(r),0≤r<14
2(i+22),−8≤i≤31,i∈Z2^{(\frac{i+2}{2})}, -8\leq{i}\leq{31}, i\in\mathbb Z2(2i+2​),−8≤i≤31,i∈Z

进一步对第一个区域的量化索引 rms_index(0)rms\_index(0)rms_index(0) 进行限制使得
1≤rms_index(0)≤311\leq{rms\_index(0)}\leq311≤rms_index(0)≤31

具体在量化过程中,iii 的取值应该使得幅度包络 rms(r)rms(r)rms(r) 处于 2(i−0.5+22)2^{(\frac{i-0.5+2}{2})}2(2i−0.5+2​) 和 2(i+0.5+22)2^{(\frac{i+0.5+2}{2})}2(2i+0.5+2​) 之间。用下面的例子说明该操作:如果 rms(r)=310rms(r)=310rms(r)=310,则应该将其量化为 2(15+22)2^{(\frac{15+2}{2})}2(215+2​),也即 rms_index(r)=15rms\_index(r)=15rms_index(r)=15,因为 2(15−0.5+22)≤rms(r)=310≤2(15+0.5+22)2^{(\frac{15-0.5+2}{2})}\leq{rms(r)=310}\leq{2^{(\frac{15+0.5+2}{2})}}2(215−0.5+2​)≤rms(r)=310≤2(215+0.5+2​)。

1-3. 编码 MLT 的幅度包络

使用 5 个 bit 来编码幅度包络的量化索引 rms_index(r)rms\_index(r)rms_index(r)。直接将第零个区域的量化索引 rms_index(0)rms\_index(0)rms_index(0) 进行传输,而其余区域传输的则是与前一个区域量化索引的差值的霍夫曼编码。
diff_rms_index(r)=rms_index(r)−rms_index(r−1),1≤r<14diff\_rms\_index(r)=rms\_index(r)-rms\_index(r-1), 1\leq{r}<{14}diff_rms_index(r)=rms_index(r)−rms_index(r−1),1≤r<14

且限定其取值范围
−12≤diff_rms_index(r)≤11-12\leq{diff\_rms\_index(r)}\leq11−12≤diff_rms_index(r)≤11

也就是说,除了第零个区域外,其余区域传输的都是 diff_rms_index(r)diff\_rms\_index(r)diff_rms_index(r) 的霍夫曼编码(通过查找两个霍夫曼表实现,一个霍夫曼表表示编码该差值需要多少 bit,另一个霍夫曼表表示把该差值具体编码成什么)。

2. 确定编码方法、量化和编码 MLT 的系数

第一部分主要是量化和编码每个区域的幅度包络,该部分主要用于确定一些量化和编码 MLT 系数相关的参数,并用这些参数对 MLT 系数进行量化。这部分相比第一部分增加了难度,笔者刚开始接触的时候看了好几遍才算看懂。笔者在这尽量用简洁的语言描述清楚该部分所做的事情。

2-1. 产生 16 组不同的编码(分类)方法

该部分根据编码完 MLT 的幅度包络所剩下的比特数以及 rms_index(r)rms\_index(r)rms_index(r) 产生 16 种不同的编码方法(或者说产生 16 种不同的参数,这些参数用于对 MLT 系数进行量化和编码)并从中选取最合适的一种编码方法(或者说选取最合适的一种参数)。下面简单介绍一下这 16 种不同的编码方法。

编码器会给 14 个区域中的每个区域都分配一个类别,共有 0~7 共 8 种可选类别。每种类别决定了该区域的量化和编码参数,并决定了量化该区域的 MLT 系数预计所需的比特数,如图2 所示。

表1 G.722.1 每一类别预计所需的比特数


由于每个区域有 8 种类别可选,因此从算术上来说应该有 8148^{14}814 种不同的编码方法,但这其中有许多编码方法是不合理的,G.722.1 编码器最终只生成 16 种不同的编码方法,并且这 16 种编码方法之间是有联系的,那就是每种编码方法和与其相邻的编码方法之间只有一个区域分配的类别不同,并且该区域的类别值只相差 1。这块可能有点绕,既有 16 种编码方法,又有 14 个区域,还有 8 种区域类别,这几个数字之间到底是什么关系哪,下面举个例子来说明一下,见表2:

表2 G.722.1 编码方法示例

编码方法1 编码方法2 编码方法3 *** 编码方法16
区域0 2 2 2 * *
区域1 1 1 1 * *
区域2 2 2 2 * *
区域3 1 0 0 * *
区域4 2 2 2 * *
区域5 4 4 4 * *
区域6 3 3 2 * *
区域7 4 4 4 * *
区域8 3 3 3 * *
区域9 6 6 6 * *
区域10 5 5 5 * *
区域11 7 7 7 * *
区域12 6 6 6 * *
区域13 7 7 7 * *

表2 展示了编码器产生的 16 种编码方法之间的关系,可以看到第 2 种编码方法与第 1 种编码方法只在区域 3 的类别分配上不同,第 1 种编码方法给区域 3 分配的是类别 1,第 2 种编码方法给区域 3 分配的是类别 0,两者区域 3 的类别值只差 1。第 3 种编码方法与第 2 种编码方法也是类似的关系,依次类推,其余第 n 种编码方法与第 n-1 种编码方法也是类似的关系。通过表2,相信读者现在已经能捋清楚 16 种编码方法、14 个区域和 8 种区域类别之间的关系了。还有需要注意的一点是,最终产生的 16 种编码方法是按照所用比特数从大到小依次排列的,也就是第 0 种编码方法所用比特数最多,第 15 种编码方法所用比特数最少。

写到这,其实并没有具体提到这 16 种编码方法到底是如何根据前面所说的剩余比特数和 rms_index(r)rms\_index(r)rms_index(r) 产生的。笔者也不打算在这详说,因为这部分比较繁琐,笔者不一定能说清楚,最重要的是笔者也没太理解其中公式的具体含义……感兴趣的可以根据 G.722.1 官方文档以及源码作进一步了解。

2-2. 归一化、量化和编码 MLT 系数

该部分对类别分配为 0~6 的区域的 MLT 系数进行所谓的标量量化矢量霍夫曼编码(SQVH),而对类别分配为 7 的区域的 MLT 系数不进行编码,认为该区域没有有效的音频信息。

首先,编码器对每个区域的 MLT 系数的绝对值进行归一化和量化,产生量化索引 k(j)k(j)k(j):
k(j)=min{⌊∣x∗mlt(20r+j)∣+deadzone_rounding⌋,kmax}k(j)=min\{\lfloor|x*mlt(20r+j)|+deadzone\_rounding\rfloor,kmax\}k(j)=min{⌊∣x∗mlt(20r+j)∣+deadzone_rounding⌋,kmax}

其中
0≤j<200\leq{j}<200≤j<20x=1/(stepsize∗(rms(r)的量化值))x=1/(stepsize*(rms(r)的量化值))x=1/(stepsize∗(rms(r)的量化值))

上式中所用的参数见表3:

表3 G.722.1 SQVH 程序所用参数表1


上面展示了如何对 MLT 系数的绝对值进行归一化和量化,但为何通过这种方式来做、表3 中参数的具体值是如何得到的以及 deadzone_round 的作用是什么,笔者现在还没搞太懂。介绍完 MLT 系数的归一化,下面就介绍如何对这些归一化之后的系数进行量化和编码。

先看表3,定义了几个参数 vd\bm {vd}vd、vpr\bm {vpr}vpr 和 u\bm {u}u

表4 G.722.1 SQVH 程序所用参数表2


要理解表4 中的几个参数的具体含义就要和表3 一起对照着看。可以观察到表4 中每一行均满足以下关系:
vd∗vpr=20\bm{vd}*\bm{vpr}=20vd∗vpr=20u=(kmax+1)vd\bm{u}=(kmax+1)^{\bm{vd}}u=(kmax+1)vd

先看第一个公式中的 20 是什么意思哪,回想一下,这个 20 正是每个区域中所包含的 MLT 系数的个数。因此,vd\bm{vd}vd 和 vpr\bm{vpr}vpr 所代表的含义也就比较明显了:将每个区域的 20 个 MLT 系数,每 vd\bm{vd}vd 个组成一个矢量,总共有 vpr\bm{vpr}vpr 个矢量。类别为 0 的区域矢量数最多,总共有 10 个矢量。类别为 5、6 的区域矢量数最少,总共有 4 个矢量。

再看第二个公式,kmaxkmaxkmax 是在表3 中定义的,是指不同类别的区域的 MLT 系数归一化之后能取到的最大值。比如,类别为 0 的区域,其 MLT 系数归一化之后能取到的最大值是 13,最小值是 0,总共有 14 种可能的取值;类别为 6 的区域,其 MLT 系数归一化之后能取到的最大值是 1,最小值是 0,总共有 2 种可能的取值;kmax+1kmax+1kmax+1 就是指该类别的区域的 MLT 系数归一化之后所有可能的取值数目。因此第二个公式代表的意思就是该类别的区域的每个矢量(每个矢量共包含 vd\bm{vd}vd 个标量)所有可能取值数目。

上面讲了如何对不同类别的区域的 MLT 系数的绝对值进行归一化,并如何组合成矢量,下面就开始介绍如何对这些组合成的矢量进行编码。

将每个区域的各个矢量按照下面的公式量化为标量:
vector_index(v)=∑l=0vd−1k(v∗vd+l)(kmax+1)vd−(l+1)vector\_index(v)=\sum_{l=0}^{\bm{vd}-1}{k(v*\bm{vd}+l)(kmax+1)^{\bm{vd}-(l+1)}}vector_index(v)=l=0∑vd−1​k(v∗vd+l)(kmax+1)vd−(l+1)

其中 0≤v≤vpr−10\leq{v}\leq{\bm{vpr}-1}0≤v≤vpr−1 表示区域 rrr 中的第 vvv 个矢量

再将 vector_index(v)vector\_index(v)vector_index(v) 通过查表的方式进行霍夫曼编码(此处同样有两张表,一张表表示编码该值需要多少比特,另一张表表示将该值具体编码成什么)。上述所描述的从 MLT 系数的归一化到最终的霍夫曼编码的整个过程称为标量量化矢量霍夫曼编码(SQVH) 。

至此,G.722.1 编码器的主要部分已讲的差不多了。还有一些细节需要了解。

3. 细节

3-1. 符号比特

刚才讲的是对 MLT 系数的绝对值进行归一化、量化和编码,并没提到符号位,实际上在具体传输比特的过程中,符号比特直接位于表示 vector_index(v)vector\_index(v)vector_index(v) 的比特的后面。vector_index(v)vector\_index(v)vector_index(v) 里面对应包含了多少非零值。后面就有多少个符号比特,其中正数的符号比特为 1。

3-2. 确定最终编码方法

之前提到总共有 16 种编码方法,且第 0 种编码方法使用的比特数最多,第 15 种编码方法使用的比特数最少,最终传输的过程中只选用其中最合适的一种。比如第 0 种编码方法使用了 500 个比特,第 1 种编码方法使用了 470 个比特,但每一帧最多只能用 480 个比特,所以最终选择第 1 种编码方法,多出来的 10 个比特全部置为 1;还有比如第 0~15 种编码方法所用比特数都大于 480,那么最终选取第 15 种编码方法,传输过程中只传输前 480 个比特,剩余的比特不传输。

3-3. 比特流模块

最终编码后的比特流包含三个部分:

图2 G.722.1 编码器主要比特流字段及其传输顺序
第一部分和第三部分比较清楚,第二部分就是指具体使用的哪种编码方法,因为总共有 16 种编码方法,所以用 4 个比特表示。

4. 总结

G.722.1 的编码器部分终于讲的差不多了,其中有很多细节笔者也没太搞懂,若是读者了解其中缘由,希望能指教一二。还有就是 G.722.1 在实际代码实现过程中可能不完全和文档中的一样,感兴趣的可以阅读源码了解细节。

音频编解码之 G7221 编码器相关推荐

  1. [总结]FFMPEG视音频编解码零基础学习方法--转

    ffmpeg编解码学习 目录(?)[-] ffmpeg程序的使用ffmpegexeffplayexeffprobeexe 1 ffmpegexe 2 ffplayexe 3 ffprobeexe ff ...

  2. FFMPEG视音频编解码零基础学习方法

    总结]FFMPEG视音频编解码零基础学习方法 在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的"大神",有的是刚 ...

  3. 音视频开发(5)---FFMPEG视音频编解码零基础学习方法

    FFMPEG视音频编解码零基础学习方法 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/leixiaohua1020/article/details/ ...

  4. G711(PCM/PCMA/PCMU),G721,G723,G729等 音频编解码

    G711,G721,G723音频编解码,G729音频库,Android G711(PCMA/PCMU).G726.PCM音频转码到AAC,ffmpeg接收g723音频流,Android G726语音编 ...

  5. [总结]视音频编解码技术零基础学习方法

    原文地址:http://blog.csdn.net/leixiaohua1020/article/details/18893769 一直想把视音频编解码技术做一个简单的总结,可是苦于时间不充裕,一直没 ...

  6. 视音频编解码技术零基础学习方法(向雷神致敬)

    一直想把视音频编解码技术做一个简单的总结,可是苦于时间不充裕,一直没能完成.今天有着很大的空闲,终于可以总结一个有关视音频技术的入门教程,可以方便更多的人学习从零开始学习视音频技术.需要注意的是,本文 ...

  7. 视音频编解码技术零基础学习方法

    一直想把视音频编解码技术做一个简单的总结,可是苦于时间不充裕,一直没能完成.今天有着很大的空闲,终于可以总结一个有关视音频技术的入门教程,可以方便更多的人学习从零开始学习视音频技术.需要注意的是,本文 ...

  8. [总结]FFMPEG视音频编解码零基础学习方法

    在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFMPEG进行视音频编解码的人,有的已经是有多年经验的"大神",有的是刚开始学习的初学者.在和大家探讨的过程中,我忽然 ...

  9. 详解音频编解码的原理、演进和应用选型等

    本文来自网易云音乐音视频实验室负责人刘华平在LiveVideoStackCon 2017大会上的分享,并由LiveVideoStack根据演讲内容整理而成(本次演讲PPT文稿,请从文末附件下载). 1 ...

  10. [总结]FFMPEG视音频编解码零基础学习方法【转】

    本文转载自:http://blog.csdn.net/leixiaohua1020/article/details/15811977 在CSDN上的这一段日子,接触到了很多同行业的人,尤其是使用FFM ...

最新文章

  1. 硕博就业:引进博士40万;硕士20万;本科15万
  2. samli文件_5.3 smali文件格式
  3. 深度学习之卷积神经网络(11)卷积层变种
  4. C# 7 中的模范和实践
  5. 小程序多个echars_小程序界面与逻辑
  6. lintcode: Check Sum of Square Numbers
  7. 【渝粤教育】国家开放大学2019年春季 1344金融风险管理 参考试题
  8. MVC的Ajax传值问题
  9. Python__关于列表的引用 以append操作为例
  10. Python教学视频(一)Python基础环境的安装
  11. 微信小程序图片显示不出来的解决方案
  12. 微信公众号消息推送服务器,微信服务号模块消息推送
  13. 盛诺基和信达生物达成临床研究合作
  14. 关于重装系统前的准备、备份和重装完后系统优化、使用习惯等说明
  15. Windows远程桌面怎么使用,看完马上学会!
  16. Camera2 开发问题记录
  17. 在Linux上安装VLC播放器
  18. 《看不见的森林:林中自然笔记》书摘一
  19. 设计技巧之:LOGO色彩搭配
  20. uni-app中Card slots的使用(添加点击事件)(uni-card)

热门文章

  1. 2小时完成的第一个副业单子:Python修正excel表格数据
  2. 研究生复试------12 学做菜
  3. 你的忧伤,是我青春路过的彷徨
  4. 当代计算机科学的先驱John Todd逝世
  5. 创建不带参数的存储过程
  6. Button控件更改背景和去掉边框
  7. 悉尼大学COMP5216Assignment2课业解析
  8. css改变透明背景png图片的图标颜色
  9. Codeforces - Garland
  10. mas6a801 sw tree disp