4 lsp系数量化
现在来分析这个
10 lsp系数已经计算出来了,由于lsp的性质,可以将它们分成若干段,分别量化
它们将会被分成 3,3,4这三个分矢量
每个矢量都会有一个256的码本表(大概是这么多的,可以直接计算一下那个数组的大小)
Lsp_Qnt 这个函数,执行lsp量化的过程,会形成一个lsp三个分矢量在码本表里的下标索引
首先我们看到每个lsp系数被进行了加权
权值就是与相邻lsp距离大的那个值的倒数,也就是说,一个lsp系数如果位置有点"偏",那么
它在量化中的比重就小了
代码片段,这里就不列出计算距离的那一部分了
/* Invert the differences */ //lsc权值是距离的倒数
//lsc 为什么选用0x20,这是因为div_s要求被除数一定要小于除数,而0x20是一定满足这个条件的,这导致本应用0x80表示
1,最后的结果是扩大2^13次方
Tmp0 = (Word16) 0x0020 ;
for ( i = 0 ; i < LpcOrder ; i ++ ) {
if ( Wvect[i] > Tmp0 )
Wvect[i] = div_s( Tmp0, Wvect[i] ) ;
else
Wvect[i] = MAX_16 ;
}
注意取倒数的Tmp0 =0x0020,这个值选得是有依据的,保证itu的除法不出错
然后对权值进行归一化
去除直流分量,这是由于itu采用的是定点数,所以目标向量的值不宜过大,去除直流分量后,从
直流分量的定义,可以看出来,大概会在+-20之间
*/ //去除直流分量 lsp参数尽量减小,使码本里的值不会太大,减少计算的bit位(这可以从码本里的值看出来)
for ( i = 0 ; i < LpcOrder ; i ++ ) {
CurrLsp[i] = sub( CurrLsp[i], LspDcTable[i] ) ;
PrevLsp[i] = sub( PrevLsp[i], LspDcTable[i] ) ;
}
这里考虑到lsp的相关性,还应扣减之前lsp的值的12/32,进一步减小目标向量值的大小
*/ // 12/32将以前的lsp进行衰减,量化差值
for ( i = 0 ; i < LpcOrder ; i ++ ) {
Tmp0 = mult_r( PrevLsp[i], (Word16) LspPrd0 ) ;
CurrLsp[i] = sub( CurrLsp[i], Tmp0 ) ;
}
LspPrd0 就是12/32,即它是扩大了32767倍的这是由于mult_r缩小计算后的值,所以预先扩大12/32
在码本表里搜索,采用的方式是欧式距离最短的那个码本向量的下标,做为量化的结果(当然,要乘上权值后搜索),
代码片段
/*
g723里的公式,经过推演实际上为 (E - Eb)^2 * W E即为去除直流分量的,并且做了预测差值的项,即标准中的 en
(3.4) ,于是在 Lsp_Svq里量化时,直接计算 Eb为码本里的值
只需要计算 w(2 Eb * E - Eb^2)的最大值即可,因为 E^2是固定的,从这里看出w的扩大倍数,对计算结果无影响
*/
return Lsp_Svq( CurrLsp, Wvect ) ;
Lsp_Svq 这个就是搜索欧式距离最小的那个码本向量 search vector quat(呵呵,看函数名应该是这个意思)
注意,并没有完整地计算欧式距离,因为E^2是固定的,只需要计算w(2 Eb * E - Eb^2)最大即可,
推导
w(E^2 - 2 Eb * E + Eb^2),本应计算此式的最小值,因为E^2不变,所以只需计算w(2 Eb * E - Eb^2)最大
代码片段较为简单,此处不列举了
至此,完成了声道参数的编码过程.接下来,就是要对激励进行编码了(也就是逆滤波后的残差信号)
待续....
林绍川
2011.5.15 于杭州