g723源码详细分析-20-共振峰后置滤波器

现在来分析最后一块g723中最后一个未分析模块

共振峰后置滤波器
涉及函数 Spf Scale

观察itu 3.8 式49.3:
           10
       1 -  Σ  ai * λ1^i * z^(-i)
           i=1
F(z)= ---------------------------  (1 - 0.25 * k * z^(-i))
           10
       1 -  Σ  ai * λ2^i * z^(-i)
           i=1


这个滤波器是由两部分组成
(1 - 0.25 * k * z^(-i)) 这一部分为倾斜补偿滤波器,
由k的取值可以起到那频谱倾斜度调节的作用,这一点会在本文下面进一步说明

别来看短时滤波部分,即
           10
       1 -  Σ  ai * λ1^i * z^(-i)
           i=1
      ---------------------------
           10
       1 -  Σ  ai * λ2^i * z^(-i)
           i=1

其中λ1=0.65 λ2=0.75
回顾共振峰感知加权滤波器,这两个值的大小正好是相反的(共振峰加权γ1=0.9 γ2=0.5)

共振峰感加权,目的是加强频谱中共振峰处的能量,但同时也会对波谷处的噪声,
共振峰后置滤波器就是要降低波谷处噪声

由于需要构造的稳定系统,可以想见,z^-1的系数应该要小于1,即ai*(λ2^i)必须不能大于1,
保险的办法,就是λ2不能大于1,又由于需要降低频谱波谷处的能量,
引入的调节因子λ1,自然就必须比λ2小

现在来看倾斜补偿滤波器:
(1 - 0.25 * k * z^(-i))

k的取值 见itu文档式49.1 49.2
根据柯西定理,我们很容易得出 -1 < k < 1
z用单位圆代入,可得到频谱幅度的表达式:
1+(0.25)^2 - 0.5*cos(x) k=1 时
1+(0.25)^2 + 0.5*cos(x) k=-1 时

很容易看出,当k=1时(意味着信号自关联性强,即信号低频能量很高),
倾斜补偿滤波器是将高频抬高,而将低频适当抑制

当k=-1时则正好相反

分析完公式的含义,代码基本是照本宣科了,Spf代码片段:
Word32  Spf( Word16 *Tv, Word16 *Lpc )
{
    int   i,j   ;

    Word32   Acc0,Acc1   ;
    Word32   Sen ;
    Word16   Tmp ;
    Word16   Exp ;

    Word16   FirCoef[LpcOrder] ;
    Word16   IirCoef[LpcOrder] ;

    Word16   TmpVect[SubFrLen] ;
//lsc 在频域内共振峰加强?? --- 感知加权是加强了共振峰附近的能量(可以从两个系数的比值看出),而此处应正好相反
 /*
  * Compute ARMA coefficients.  Compute the jth FIR coefficient by
  * multiplying the jth quantized LPC coefficient by (0.65)^j.
  * Compute the jth IIR coefficient by multiplying the jth quantized
  * LPC coefficient by (0.75)^j.  This emphasizes the formants in
  * the frequency response.
  */
    for ( i = 0 ; i < LpcOrder ; i ++ ) {
        FirCoef[i] = mult_r( Lpc[i], PostFiltZeroTable[i] ) ;
        IirCoef[i] = mult_r( Lpc[i], PostFiltPoleTable[i] ) ;
    }

 /*
  * Normalize the speech vector.
  */
    for ( i = 0 ; i < SubFrLen ; i ++ )
        TmpVect[i] = Tv[i] ;
    Exp = Vec_Norm( TmpVect, (Word16) SubFrLen ) ;

 /*
  * Compute the first two autocorrelation coefficients R[0] and R[1]
  */
    Acc0 = (Word32) 0 ;
    Acc1 = L_mult( TmpVect[0], TmpVect[0] ) ;
    for ( i = 1 ; i < SubFrLen ; i ++ ) {
        Acc0 = L_mac( Acc0, TmpVect[i], TmpVect[i-1] ) ;
        Acc1 = L_mac( Acc1, TmpVect[i], TmpVect[i] ) ;
    }

 /*
  * Scale the energy for the later use.
  */
    Sen = L_shr( Acc1, (Word16)(2*Exp + 4) ) ;//lsc 4 = 3 + 1 这里还原了解码信号的能量

 /*
  * Compute the first-order partial correlation coefficient of the
  * input speech vector.
  */
    Tmp = extract_h( Acc1 ) ;//lsc tmp能量的高16位
    if ( Tmp != (Word16) 0 ) {

        /* Compute first parkor */
        Acc0 = L_shr( Acc0, (Word16) 1 ) ;
        Acc1 = Acc0 ;
        Acc0 = L_abs( Acc0 ) ;

        Tmp = div_l( Acc0, Tmp ) ;

        if ( Acc1 < (Word32) 0 )
            Tmp = negate( Tmp ) ;
    }
    else
        Tmp = (Word16) 0 ;

 /*
  * Compute the compensation filter parameter and update the memory
  */
    //lsc 倾斜补偿滤波器,是一个"高通"滤波器,根据itu的算法 低频大约是0.5625 高频大约是 1.5625,大意是引入后置滤波后
    //lsc 会造成频谱倾斜,即高频的能量被抑制了,需要加强,
    //lsc 倾斜滤波器的"斜率"应该是根据共振峰所处的位置来调节的,
    //lsc 可以看出k的取值就是 应该是 -1 1之间
    //lsc 如果k是1 那么说明信号相邻之间的相关性极强,也就是说能量可能集中在低频,要平衡能量,此时会变成高通滤波
    //lsc 如果k是-1, 说明信号相关性不强,也就是说能量可能集中在高频,为平衡能量,此时会变成低通滤波
    Acc0 = L_deposit_h( DecStat.Park ) ;
    Acc0 = L_msu( Acc0, DecStat.Park, (Word16) 0x2000 ) ;
    Acc0 = L_mac( Acc0, Tmp, (Word16) 0x2000 ) ;
    DecStat.Park = round( Acc0 ) ;

    Tmp  = mult( DecStat.Park, PreCoef ) ;
    Tmp &= (Word16) 0xfffc ;


 /*
  *  Do for all elements in the subframe
  */
    for ( i = 0 ; i < SubFrLen ; i ++ ) {

 /*
  * Input the speech vector
  */
        Acc0 = L_deposit_h( Tv[i] ) ;
        Acc0 = L_shr( Acc0, (Word16) 2 ) ;

 /*
  * Formant postfilter
  */

        /* FIR part */
        for ( j = 0 ; j < LpcOrder ; j ++ )
            Acc0 = L_msu( Acc0, FirCoef[j], DecStat.PostFirDl[j] ) ;

        /* Update FIR memory */
        for ( j = LpcOrder-1 ; j > 0 ; j -- )
            DecStat.PostFirDl[j] = DecStat.PostFirDl[j-1] ;
        DecStat.PostFirDl[0] = Tv[i] ;

        /* IIR part */
        for ( j = 0 ; j < LpcOrder ; j ++ )
            Acc0 = L_mac( Acc0, IirCoef[j], DecStat.PostIirDl[j] ) ;

        /* Update IIR memory */
        for ( j = LpcOrder-1 ; j > 0 ; j -- )
            DecStat.PostIirDl[j] = DecStat.PostIirDl[j-1] ;

        Acc0 = L_shl( Acc0, (Word16) 2 ) ;
        Acc1 = Acc0 ;

        DecStat.PostIirDl[0] = round( Acc0 ) ;

 /*
  * Compensation filter
  */
        Acc1 = L_mac( Acc1, DecStat.PostIirDl[1], Tmp ) ;

        Tv[i] = round( Acc1 ) ;
    }
    return Sen ;
}

关于增益缩放问题,代码片段如下:
            /* Do the gain scaling unit.  (Text: Section 3.9) */
            Scale( Dpnt, Senr ) ;//lsc 做共振峰感知加权后, 语音的能量会出现放大或者缩小,这里处理,补回去
公式见itu 3.9节的式50.

g723 done!
                                            林绍川
                                            2012.01.19于杭州
posted @ 2012-01-19 15:52  飞天大蟾蜍  阅读(36)  评论(0编辑  收藏  举报