g723源码详细分析(三) lsp量化

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 于杭州

你可能感兴趣的:(源码)