`

g723源码详细分析-12-更新内存与打包等

 
阅读更多
完成声道参数与激励编码后,需要将这些信息打包成帧,
并且要更新相应的内存,如保存当前激励成为之后编码的自适应激励码本等

在Find_Fcbk之后,即完成了所有编码,接下来更新内存状态
Decod_Acbk里解码自适应激励,这个函数在编码自适应激励时描述过了,即根据基音周期
从历史激励里,相邻的五个激励加权形成自适应激励

自适应激励与修正激励(低速率下为固定码本激励,高速率下为多脉冲激励)相加,形成历史激励
代码片段如下:

//固定与自适应相加,形成历史码本激励
for ( j = 0 ; j < SubFrLen ; j ++ ) {
Dpnt[j] = shl( Dpnt[j], (Word16) 1 ) ;//lsc 固定码本/多脉冲激励是在原始信号缩小两倍的基础上计算出来的,这时要还原回去,
Dpnt[j] = add( Dpnt[j], ImpResp[j] ) ;//lsc 从这里看出,自适应激励是原值
CodStat.PrevExc[PitchMax-SubFrLen+j] = Dpnt[j] ;
}

Update_Err:
这个函数是用于调节自适应激励的增益使用的,这里回顾一样在搜索自适应激励时被调用的
Test_Err,它用于决定搜索增益码本的范围.
总的来说,当增益处于低水平时(即搜索范围较小时),它的作用是将搜索范围调大.
在增益处于高水平时(即搜索范围较小时),它的作用是将搜索范围调小

Update_Err首先是根据自适应码本增益,计算出误差,
误差总共有5个,每30个采样值块,对应至一个误差(由于基音周期最长为147,所有有5个误差)
误差被记录在全局变量:CodStat.Err,它是根据时间降序排列的,即CodStat.Err[0]记录的误差
离当前最近, CodStat.Err[4]则最远

举个例子:如果基音周期为60,会根据CodStat.Err[2] CodStat.Err[1]的值来生成新的误差估值
生成的依据是历史误差值,乘以误差增益码本里的值(取值范围大约从0.125到2.2不等),再加4
可以看出,增益小,误差也会越来越小,
而增益大,误差也越来越大

代码片段如下
void Update_Err(
Word16 Olp, Word16 AcLg, Word16 AcGn
)
{//lsc 对这段的理解,这段是为了让自适应码本的搜索次数限制在一定的次数之内
//通过对固定码本的增益,形成一个历史误差数组(5段),根据基音周期,分别落在这五段之内,
//5段的数据是按时间排序的,0表示最近的时间,4表示最远的时间,计算的依据则是根据当前的基音周期,从相应的段中(除30),取数据进行估值
//在进行自适应码本搜索的时候,则根据基音周期,从相应的段中取出最大的误差增益,来决定自适应码本增益搜索的次数
//(次数越多,根据表,我们知道增益会越大,这样就起到降低固定码本的目标向量的作用)
Word16 *ptr_tab;
Word16 i, iz, temp1, temp2;
Word16 Lag;
Word32 Worst1, Worst0, L_temp;
Word16 beta;

Lag = Olp - (Word16)Pstep + AcLg;

/* Select Quantization tables */
i = 0 ;
ptr_tab = tabgain85;
if ( WrkRate == Rate63 ) {
if ( Olp >= (Word16) (SubFrLen-2) ) ptr_tab = tabgain170;
}
else {
ptr_tab = tabgain170;
}
beta = ptr_tab[(int)AcGn]; /* beta = gain * 8192 */


if(Lag <= (SubFrLen/2)) {
Worst0 = L_mls(CodStat.Err[0], beta);
Worst0 = L_shl(Worst0, 2);
Worst0 = L_add(Err0, Worst0);
Worst1 = Worst0;
}

else {
iz = mult(Lag, 1092); /* Lag / 30 */ //lsc 32767/30 约等于1092 --- mult乘法的结果是缩小2*15次方的,所以iz还是一个很小的值
temp1 = add(iz, 1);
temp2 = sub(shl(temp1, 5), shl(temp1, 1)); /* 30 (iz+1) */ //lsc这里相当于判断 120/30这种情况
if(temp2 != Lag) {

if(iz == 1) {//lsc这里零的情况
Worst0 = L_mls(CodStat.Err[0], beta);
Worst0 = L_shl(Worst0, 2);
Worst0 = L_add(Err0, Worst0);//lsc Err0 shr2之后直接是0
Worst1 = L_mls(CodStat.Err[1], beta);
Worst1 = L_shl(Worst1, 2);
Worst1 = L_add(Err0, Worst1);
if(Worst0 > Worst1) Worst1 = Worst0;
else Worst0 = Worst1;
}

else {//lsc这是非零的情况
Worst0 = L_mls(CodStat.Err[iz-2], beta);
Worst0 = L_shl(Worst0, 2);
Worst0 = L_add(Err0, Worst0);
L_temp = L_mls(CodStat.Err[iz-1], beta);
L_temp = L_shl(L_temp, 2);
L_temp = L_add(Err0, L_temp);
if(L_temp > Worst0) Worst0 = L_temp;
Worst1 = L_mls(CodStat.Err[iz], beta);
Worst1 = L_shl(Worst1, 2);
Worst1 = L_add(Err0, Worst1);
if(L_temp > Worst1) Worst1 = L_temp;
}
}
else { /* Lag % SubFrLen = 0 */ //lsc这大概就120/30这种情况
Worst0 = L_mls(CodStat.Err[iz-1], beta);
Worst0 = L_shl(Worst0, 2);
Worst0 = L_add(Err0, Worst0);
Worst1 = L_mls(CodStat.Err[iz], beta);
Worst1 = L_shl(Worst1, 2);
Worst1 = L_add(Err0, Worst1);
}
}

for(i=4; i>=2; i--) {
CodStat.Err[i] = CodStat.Err[i-2];
}
CodStat.Err[0] = Worst0;
CodStat.Err[1] = Worst1;

return;
}

Word16 Test_Err(
Word16 Lag1, Word16 Lag2
)
{

int i, i1, i2;
Word16 zone1, zone2;
Word32 Acc, Err_max;
Word16 iTest;

i2 = Lag2 + ClPitchOrd/2;
zone2 = mult( (Word16) i2, (Word16) 1092);//lsc 这里的意思就是除30 i2倒退一个基音周期,与i1为限,正好包含了"前一个波形"帧

i1 = - SubFrLen + 1 + Lag1 - ClPitchOrd/2;
if(i1 <= 0) i1 = 1;
zone1 = mult( (Word16) i1, (Word16) 1092);

//lsc 起始点,在历史的误差数组中取出误差最大的那个
Err_max = -1L;
for(i=zone2; i>=zone1; i--) {
Acc = L_sub(CodStat.Err[i], Err_max);
if(Acc > 0L) {
Err_max = CodStat.Err[i];
}
}
Acc = L_sub(Err_max, ThreshErr);
if((Acc > 0L) || (CodStat.SinDet < 0 ) ) {//lsc 高于某个阀值,调整为0,说明增益一直大于1,误差一直维持在较大的水平
iTest = 0;
}
else {//lsc 误差越大(增益大于1),搜索的范围越小,误差越小(增益小于1),搜索的范围越大,这样会起到调节增益的作用
Acc = L_negate(Acc);
Acc = L_shr(Acc, DEC);
iTest = extract_l(Acc);
}

return(iTest);
}

最后是更新振铃减法里相应的值,用于下一个子帧做扣减零输入响应时使用,
代码基本是把公式翻译成c代码,不详细分析了

最后打包操作,将量化的lsp系数(笔者记忆中这应该是一个索引),自适应码本以及增益

两种速率下面的修正码本以及增益打成一个包,相应帧格式itu文档里的描述,这里不重复了

有个细节稍微说一下,即多脉冲位置的打包问题,
笔者简要地说明如下:
注意表格CombinatorialTable的特点
即 98280 + 20475 恰好等于118755
意味着118755等于第二排从20475 ... 1所有的值的
98280等于第二排 17550 ... 1所有值的和,
可以自行验证,编码时做加法,解码时做减法,可以根据所得结果是否大于0来判断对应的位置有无脉冲
118755 , 23751 3654 406 29 1
98280 , 20475 3276 378 28 1
80730 , 17550 2925 351 27 1
65780 , 14950 2600 325 26 1
53130 , 12650 2300 300 25 1
42504 , 10626 2024 276 24 1
33649 , 8855 1771 253 23 1
26334 , 7315 1540 231 22 1
20349 , 5985 1330 210 21 1
15504 , 4845 1140 190 20 1
11628 , 3876 969 171 19 1
8568 , 3060 816 153 18 1
6188 , 2380 680 136 17 1
4368 , 1820 560 120 16 1
3003 , 1365 455 105 15 1
2002 , 1001 364 91 14 1
1287 , 715 286 78 13 1
792 , 495 220 66 12 1
462 , 330 165 55 11 1
252 , 210 120 45 10 1
126 , 126 84 36 9 1
56 , 70 56 28 8 1
21 , 35 35 21 7 1
6 , 15 20 15 6 1
1 , 5 10 10 5 1
1 4 6 4 1
1 3 3 1
1 2 1
1 1
1



关于解码,静音压缩以及舒适背景音生成问题,笔者将在之后的章节继续分析.


林绍川
2011.10.09 于杭州


分享到:
评论

相关推荐

    【变色龙】app封装系统源码+互站在售封装系统.zip

    CPU:1核,内存:2G,硬盘:10G,1M带宽 不能用空间,有要修改php环境的要求。 版本区别: 1、免费版本 封装App 微信小程序 2、授权版本 封装App 微信小程序 分发App 在线签名 超级签名 企业签名 苹果...

    运营版打包同城交友网站源码带17万会员数据 婚恋征婚交友网站 含支付宝免签接口

    运营版打包同城交友网站源码带17万会员数据 婚恋征婚交友网站 含支付宝免签接口 同城交友网站源码带17万会员数据 婚恋征婚交友网站 运行环境:ASP+MSSQL 2005 。 需要用VPS服务器安装 请用1G以上内存的VPS服务器安装...

    2022最新版【变色龙】app封装系统源码+封装系统

    这款变色龙app封装系统源码更适合小企业主和个人用户,打包过程简单方便快捷。附件为变色龙app封装系统源码官方正版下载,无毒无后门,原汁原味。 源码功能介绍 1、App封装 实现App封装,混合开发App,100多JS接口...

    变色龙app封装系统源码下载

    这款变色龙app封装系统源码更适合小企业主和个人用户,打包过程简单方便快捷。附件为变色龙app封装系统源码官方正版下载,无毒无后门,原汁原味。 源码功能介绍 1、App封装 实现App封装,混合开发App,100多JS接口...

    linux.chm文档

    chage -E 2005-12-31 user1 设置用户口令的失效期限 pwck 检查 '/etc/passwd' 的文件格式和语法修正以及存在的用户 grpck 检查 '/etc/passwd' 的文件格式和语法修正以及存在的群组 newgrp group_name 登陆进一个...

    易语言模块 XMLDOM 解析 构造 获取 更改 添加 删除 遍历元素 格式化XML

    示例源码: https://chensg-my.sharepoint.com/:f:/g/personal/jybbs1_chensg_onmicrosoft_com/Etm2ZdQQ8JFDjFNZWHtF8gUBvX_asvFeMcwnp97JzDwYEw?e=rKhrSF 什么是 XML DOM? XML DOM 是: 用于 XML 的标准对象模型 ...

    HGE_系列教材(1-9)

    在HGE 的文档中有详细谈到如何安装的问题,这里讲一下VC6 平台的安装问题: 1. 下载完HGE 之后,需要使用到lib\vc 文件夹下的库文件以及include 目录下的头文 件 2. 打开 Tools-&gt;Options-&gt;Directories 如上两图,...

    Linux命令笔记

    1:free 查看内存与swap分区使用状况 2:创建swap分区或开机自动挂载 第三部分:用户权限 用户权限/用户管理命令 1:useradd 添加新用户 语法:useradd [选项] 用户名 2:passwd 设置用户密码 语法:passwd [选项] ...

    网管教程 从入门到精通软件篇.txt

    ★详细的xp修复控制台命令和用法!!! 放入xp(2000)的光盘,安装时候选R,修复! Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的诊断和测试以及恢复系统功能的工具。小...

Global site tag (gtag.js) - Google Analytics