本文对 G.722.1 的解码器作以介绍,如有表述不当之处欢迎批评指正。欢迎任何形式的转载,但请务必注明出处。
目录
引言简介解码器1. 解码幅度包络2. 确定编码类型3. 解码 MLT 系数4. 噪声填充5. 欠缺的比特6. 丢帧补偿7. 逆 MLT 变换8. 总结引言
上篇文章 《音频编解码之 G7221 编码器》介绍了 G.722.1 的编码器部分,这篇文章介绍其解码器部分。
简介
G.722.1 是一种基于变换域编码的算法采样率: 16000hz比特率: 24kbit/s 32kbit/s变换域: MLT(Modulated Lapped Transform)帧长: 20ms变换窗长: 40ms有效编码带宽: 50~7000hz解码器
解码器先对每个区域的幅度包络进行解码,然后使用与编码器同样的方式产生 16 种不同的编码方法,再通过分类控制比特确定编码器所选用的编码方法,最后对 MLT 系数解码重建。
1. 解码幅度包络
接收到码流中的前 5 个比特表示第 0 个区域幅度包络的量化索引 rms_index(0)rms\_index(0)rms_index(0),通过查表的方式解码出
diff_rms_index(r),1≤r<14diff\_rms\_index(r), 1\leq{r}<14diff_rms_index(r),1≤r<14
并通过以下方式得到其他区域幅度包络的量化索引
rms_index(r)=rms_index(r−1)+diff_rms_index(r),1≤r<14,1≤r<14rms\_index(r) = rms\_index(r-1) + diff\_rms\_index(r), 1\leq{r}<14, 1\leq{r}<14rms_index(r)=rms_index(r−1)+diff_rms_index(r),1≤r<14,1≤r<14
然后通过 rms_index(r)rms\_index(r)rms_index(r) 得到区域的幅度包络 rms(r)rms(r)rms(r)。
2. 确定编码类型
使用与编码器中相同的方法,生成 16 种不同的编码方法,并通过分类控制比特确定编码器所使用的编码方法。
3. 解码 MLT 系数
通过查表解码得到 vector_index(v)vector\_index(v)vector_index(v),并通过下式得到 MLT 系数的量化索引
k(j)=⌊vector_index(v)(kmax+1)l⌋MOD(kmax+1)k(j)=\lfloor\frac{vector\_index(v)}{(kmax+1)^{l}}\rfloor MOD(kmax+1)k(j)=⌊(kmax+1)lvector_index(v)⌋MOD(kmax+1)
其中 MODMODMOD 为取余操作
j=(v+1)vd−l−1j=(v+1)\bm{vd}-l-1j=(v+1)vd−l−1 0≤l≤vd−10\leq{l}\leq{\bm{vd}-1}0≤l≤vd−1 0≤v≤vpr−10\leq{v}\leq{\bm{vpr}-1}0≤v≤vpr−1
上面式子中所用到的变量可在编码器一文中找到对应的定义。为什么对 vector_indexvector\_indexvector_index 经过上面式子的运算就能得到 kkk 那,先回顾一下编码器一文中的式子
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−1k(v∗vd+l)(kmax+1)vd−(l+1)
这个式子是由 kkk 得到 vector_indexvector\_indexvector_index,正好与前一个式子相反。下面举个例子详细说明一下这两个互为“逆”的式子。
假设给区域 0 分配的类别值是 0,那么由编码器一文可知,该区域在编码阶段将包含 10 个矢量,每个矢量包含 2 个标量,以第 2 个矢量 [k(2),k(3)][k(2), k(3)][k(2),k(3)] 为例, 可知 v=1v=1v=1,vd=2\bm{vd}=2vd=2,kmax=13kmax=13kmax=13,带入上式可得
vector_index(1)=k(1∗2+0)∗(13+1)2−(0+1)+k(1∗2+1)∗(13+1)2−(1+1)vector\_index(1)=k(1*2+0)*(13+1)^{2-(0+1)}+k(1*2+1)*(13+1)^{2-(1+1)}vector_index(1)=k(1∗2+0)∗(13+1)2−(0+1)+k(1∗2+1)∗(13+1)2−(1+1)
化简之后可得
vector_index(1)=k(2)∗14+k(3)vector\_index(1)=k(2)*14+k(3)vector_index(1)=k(2)∗14+k(3)
现在知道了如何由 k(2)k(2)k(2) 和 k(3)k(3)k(3) 得到 vector_index(1)vector\_index(1)vector_index(1),那么再通过之前的那个式子看如何由 vector_index(1)vector\_index(1)vector_index(1) 得到 k(2)k(2)k(2) 和 k(3)k(3)k(3),
l=0⇒⌊vector_index(1)(13+1)0⌋MOD(13+1)=k(3)l=0 \rArr \lfloor\frac{vector\_index(1)}{(13+1)^{0}}\rfloor MOD(13+1)=k(3)l=0⇒⌊(13+1)0vector_index(1)⌋MOD(13+1)=k(3)
l=1⇒⌊vector_index(1)(13+1)1⌋MOD(13+1)=k(2)l=1 \rArr \lfloor\frac{vector\_index(1)}{(13+1)^{1}}\rfloor MOD(13+1)=k(2)l=1⇒⌊(13+1)1vector_index(1)⌋MOD(13+1)=k(2)
通过这个式子相信大家明白了 kkk 和 vector_indexvector\_indexvector_index 之间是如何互相计算得到的。计算出 MLT 系数的量化索引 k(j)k(j)k(j) 之后,将 k(j)k(j)k(j) 映射到表1 所对应的值,然后将该值与解码得到的幅度包络 rms(r)rms(r)rms(r) 相乘得到 MLT 系数幅度,并按照符号比特设置非零系数的符号。
表1 G.722.1 用来重建MLT系数的参数
4. 噪声填充
没有对类别为 7 的区域的 MLT 系数幅度进行编码,解码时将其用噪声代替。在编码类别为 5 和 6 的区域时,由于量化步长较大,因此也有许多系数被量化为了 0,解码时同样将其用噪声代替。这些噪声由于符号随机、幅度与 rms(r)rms(r)rms(r) 成比例的系数值代替。表2 规定了比例常数。
表2 G.722.1 噪声填充比例性常数
5. 欠缺的比特
编码时,可能编码器在完成最后一个非类别 7 区域的编码之前比特已经不够用了。这种情况下,解码器将该区域以及剩余的所有区域当成类别 7 作处理。
6. 丢帧补偿
解码器若获知当前帧丢失,则使用前一帧已解码的 MLT 系数。若前一帧也丢失,解码器将当前帧的 MLT 系数全部置为 0。
7. 逆 MLT 变换
将 MLT 系数转换到时域,这儿不具体介绍公式。
8. 总结
磕磕绊绊花了一天多的时间终于写完了,这其实是笔者 1 年前的工作了,有好多细节得重新回忆,可能还有好多地方理解地不对。笔者在刚开始学习 G.722.1 编解码器的时候有好多细节不懂,至今也是。比如生成 16 种编码方法的具体做法,以及为什么要那样做,其次就是 G.722.1 中有大量的表格,那些值是怎么得到的,其中某些值的含义又是什么。如果读者了解其中详情或是发现文章中有理解错误的地方,还请多多赐教!