?? exc_lbc.c
字號:
Word16 Lag1, Lag2;
Word16 off_filt;
/* Init constants */
Olp = (*Line).Olp[shr(Sfc, (Word16) 1)] ;
Lid = (Word16) Pstep ;
Gid = (Word16) 0 ;
Hb = (Word16) 3 + (Sfc & (Word16) 1 ) ;
/* For even frames only */
if ( (Sfc & (Word16)1) == (Word16) 0 ) {
if ( Olp == (Word16) PitchMin )
Olp = add( Olp, (Word16) 1 ) ;
if ( Olp > (Word16) (PitchMax-5) )
Olp = (Word16)(PitchMax-5) ;
}
lPnt = CorBuf ;
for ( k = 0 ; k < (int) Hb ; k ++ ) {
/* Get residual from the excitation buffer */
Get_Rez( RezBuf, PrevExc, (Word16)(Olp-(Word16)Pstep+k) ) ;
/* Filter the last one using the impulse response */
for ( i = 0 ; i < SubFrLen ; i ++ ) {
Acc0 = (Word32) 0 ;
for ( j = 0 ; j <= i ; j ++ )
Acc0 = L_mac( Acc0, RezBuf[ClPitchOrd-1+j], ImpResp[i-j] ) ;
FltBuf[ClPitchOrd-1][i] = round( Acc0 ) ;
}
/* Update all the others */
for ( i = ClPitchOrd-2 ; i >= 0 ; i -- ) {
FltBuf[i][0] = mult_r( RezBuf[i], (Word16) 0x2000 ) ;
for ( j = 1 ; j < SubFrLen ; j ++ ) {
Acc0 = L_deposit_h( FltBuf[i+1][j-1] ) ;
Acc0 = L_mac( Acc0, RezBuf[i], ImpResp[j] ) ;
FltBuf[i][j] = round( Acc0 ) ;
}
}
/* Compute the cross with the signal */
for ( i = 0 ; i < ClPitchOrd ; i ++ ) {
Acc1 = (Word32) 0 ;
for ( j = 0 ; j < SubFrLen ; j ++ ) {
Acc0 = L_mult( Tv[j], FltBuf[i][j] ) ;
Acc1 = L_add( Acc1, L_shr( Acc0, (Word16) 1 ) ) ;
}
*lPnt ++ = L_shl( Acc1, (Word16) 1 ) ;
}
/* Compute the energies */
for ( i = 0 ; i < ClPitchOrd ; i ++ ) {
Acc1 = (Word32) 0 ;
for ( j = 0 ; j < SubFrLen ; j ++ )
Acc1 = L_mac( Acc1, FltBuf[i][j], FltBuf[i][j] ) ;
*lPnt ++ = Acc1 ;
}
/* Compute the between crosses */
for ( i = 1 ; i < ClPitchOrd ; i ++ ) {
for ( j = 0 ; j < i ; j ++ ) {
Acc1 = (Word32) 0 ;
for ( l = 0 ; l < SubFrLen ; l ++ ) {
Acc0 = L_mult( FltBuf[i][l], FltBuf[j][l] ) ;
Acc1 = L_add( Acc1, L_shr( Acc0, (Word16) 1 ) ) ;
}
*lPnt ++ = L_shl( Acc1, (Word16) 2 ) ;
}
}
}
/* Find Max and normalize */
Acc1 = (Word32) 0 ;
for ( i = 0 ; i < Hb*20 ; i ++ ) {
Acc0 = L_abs(CorBuf[i]) ;
if ( Acc0 > Acc1 )
Acc1 = Acc0 ;
}
Exp = norm_l( Acc1 ) ;
/* Convert to shorts */
for ( i = 0 ; i < Hb*20 ; i ++ ) {
Acc0 = L_shl( CorBuf[i], Exp ) ;
CorVct[i] = round( Acc0 ) ;
}
/* Test potential error */
Lag1 = Olp-(Word16)Pstep;
Lag2 = Olp-(Word16)Pstep+ Hb -(Word16)1;
off_filt = Test_Err(Lag1, Lag2);
Bound[0] = NbFilt085_min + shl(off_filt,2);
if(Bound[0] > NbFilt085) Bound[0] = NbFilt085;
Bound[1] = NbFilt170_min + shl(off_filt,3);
if(Bound[1] > NbFilt170) Bound[1] = NbFilt170;
/* Init the search loop */
Acc1 = (Word32) 0 ;
for ( k = 0 ; k < (int) Hb ; k ++ ) {
/* Select Quantization tables */
l = 0 ;
if ( WrkRate == Rate63 ){
if ( (Sfc & (Word16) 1) == (Word16) 0 ) {
if ( (int)Olp-Pstep+k >= SubFrLen-2 )l ++ ;
}
else {
if ( (int)Olp >= SubFrLen-2 ) l ++ ;
}
}
else {
l = 1;
}
sPnt = AcbkGainTablePtr[l] ;
for ( i = 0 ; i < (int) Bound[l] ; i ++ ) {
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < 20 ; j ++ )
Acc0 = L_add( Acc0, L_shr( L_mult(CorVct[k*20+j], *sPnt ++),
(Word16) 1 ) ) ;
if ( Acc0 > Acc1 ) {
Acc1 = Acc0 ;
Gid = (Word16) i ;
Lid = (Word16) k ;
}
}
}
/* Modify Olp for even sub frames */
if ( (Sfc & (Word16) 1 ) == (Word16) 0 ) {
Olp = Olp - (Word16) Pstep + Lid ;
Lid = (Word16) Pstep ;
}
/* Save Gains and Olp */
(*Line).Sfs[Sfc].AcLg = Lid ;
(*Line).Sfs[Sfc].AcGn = Gid ;
(*Line).Olp[shr(Sfc, (Word16) 1)] = Olp ;
/* Decode the Acbk contribution and subtract it */
Decod_Acbk( RezBuf, PrevExc, Olp, Lid, Gid ) ;
for ( i = 0 ; i < SubFrLen ; i ++ ) {
Acc0 = L_deposit_h( Tv[i] ) ;
Acc0 = L_shr( Acc0, (Word16) 1 ) ;
for ( j = 0 ; j <= i ; j ++ )
Acc0 = L_msu( Acc0, RezBuf[j], ImpResp[i-j] ) ;
Acc0 = L_shl( Acc0, (Word16) 1 ) ;
Tv[i] = round( Acc0 ) ;
}
return;
}
/*
**
** Function: Get_Rez()
**
** Description: Gets delayed contribution from the previous excitation
** vector.
**
** Links to text: Sections 2.14, 2.18 & 3.4
**
** Arguments:
**
** Word16 *Tv delayed excitation
** Word16 *PrevExc Previous excitation vector
** Word16 Lag Closed loop pitch lag
**
** Outputs:
**
** Word16 *Tv delayed excitation
**
** Return value: None
**
*/
void Get_Rez( Word16 *Tv, Word16 *PrevExc, Word16 Lag )
{
int i ;
for ( i = 0 ; i < ClPitchOrd/2 ; i ++ )
Tv[i] = PrevExc[PitchMax - (int) Lag - ClPitchOrd/2 + i] ;
for ( i = 0 ; i < SubFrLen+ClPitchOrd/2 ; i ++ )
Tv[ClPitchOrd/2+i] = PrevExc[PitchMax - (int)Lag + i%(int)Lag] ;
return;
}
/*
**
** Function: Decod_Acbk()
**
** Description: Computes the adaptive codebook contribution from the previous
** excitation vector.
** With the gain index, the closed loop pitch lag, the jitter
** which when added to this pitch lag gives the actual closed
** loop value, and after having selected the proper codebook,
** the pitch contribution is reconstructed using the previous
** excitation buffer.
**
** Links to text: Sections 2.14, 2.18 & 3.4
**
** Arguments:
**
** Word16 *Tv Reconstructed excitation vector
** Word16 *PrevExc Previous excitation vector
** Word16 Olp closed-loop pitch period
** Word16 Lid Jitter around pitch period
** Word16 Gid Gain vector index in 5- dimensional
** adaptive gain vector codebook
**
** Outputs:
**
** Word16 *Tv Reconstructed excitation vector
**
** Return value: None
**
*/
void Decod_Acbk( Word16 *Tv, Word16 *PrevExc, Word16 Olp, Word16 Lid,
Word16 Gid )
{
int i,j ;
Word32 Acc0 ;
Word16 RezBuf[SubFrLen+ClPitchOrd-1] ;
Word16 *sPnt ;
Get_Rez( RezBuf, PrevExc, (Word16)(Olp - (Word16)Pstep + Lid) ) ;
/* Select Quantization tables */
i = 0 ;
if ( WrkRate == Rate63 ) {
if ( Olp >= (Word16) (SubFrLen-2) ) i ++ ;
}
else {
i = 1;
}
sPnt = AcbkGainTablePtr[i] ;
sPnt += (int)Gid*20 ;
for ( i = 0 ; i < SubFrLen ; i ++ ) {
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < ClPitchOrd ; j ++ )
Acc0 = L_mac( Acc0, RezBuf[i+j], sPnt[j] ) ;
Acc0 = L_shl( Acc0, (Word16) 1 ) ;
Tv[i] = round( Acc0 ) ;
}
return;
}
/*
**
** Function: Comp_Info()
**
** Description: Voiced/unvoiced classifier.
** It is based on a cross correlation maximization over the
** last 120 samples of the frame and with an index varying
** around the decoded pitch lag (from L-3 to L+3). Then the
** prediction gain is tested to declare the frame voiced or
** unvoiced.
**
** Links to text: Section 3.10.2
**
** Arguments:
**
** Word16 *Buff decoded excitation
** Word16 Olp Decoded pitch lag
**
** Outputs: None
**
** Return value:
**
** Word16 Estimated pitch value
*/
Word16 Comp_Info( Word16 *Buff, Word16 Olp, Word16 *Gain, Word16 *ShGain)
{
int i,j ;
Word32 Acc0,Acc1 ;
Word16 Tenr ;
Word16 Ccr,Enr ;
Word16 Indx ;
/* Normalize the excitation */
*ShGain = Vec_Norm( Buff, (Word16) (PitchMax+Frame) ) ;
if ( Olp > (Word16) (PitchMax-3) )
Olp = (Word16) (PitchMax-3) ;
Indx = Olp ;
Acc1 = (Word32) 0 ;
for ( i = (int)Olp-3 ; i <= (int)Olp+3 ; i ++ ) {
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < 2*SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Buff[PitchMax+Frame-2*SubFrLen+j],
Buff[PitchMax+Frame-2*SubFrLen-i+j] ) ;
if ( Acc0 > Acc1 ) {
Acc1 = Acc0 ;
Indx = (Word16) i ;
}
}
/* Compute target energy */
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < 2*SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Buff[PitchMax+Frame-2*SubFrLen+j],
Buff[PitchMax+Frame-2*SubFrLen+j] ) ;
Tenr = round( Acc0 ) ;
*Gain = Tenr;
/* Compute best energy */
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < 2*SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Buff[PitchMax+Frame-2*SubFrLen-(int)Indx+j],
Buff[PitchMax+Frame-2*SubFrLen-(int)Indx+j] ) ;
Ccr = round( Acc1 ) ;
if ( Ccr <= (Word16) 0 )
return (Word16) 0 ;
Enr = round( Acc0 ) ;
Acc0 = L_mult( Enr, Tenr ) ;
Acc0 = L_shr( Acc0, (Word16) 3 ) ;
Acc0 = L_msu( Acc0, Ccr, Ccr ) ;
if ( Acc0 < (Word32) 0 )
return Indx ;
else
return (Word16) 0 ;
}
/*
**
** Function: Regen()
**
** Description: Performs residual interpolation depending of the frame
** classification.
** If the frame is previously declared unvoiced, the excitation
** is regenerated using a random number generator. Otherwise
** a periodic excitation is generated with the period
** previously found.
**
** Links to text: Section 3.10.2
**
** Arguments:
**
** Word16 *DataBuff current subframe decoded excitation
** Word16 *Buff past decoded excitation
** Word16 Lag Decoded pitch lag from previous frame
** Word16 Gain Interpolated gain from previous frames
** Word16 Ecount Number of erased frames
** Word16 *Sd Random number used in unvoiced cases
**
** Outputs:
**
** Word16 *DataBuff current subframe decoded excitation
** Word16 *Buff updated past excitation
**
** Return value: None
**
*/
void Regen( Word16 *DataBuff, Word16 *Buff, Word16 Lag, Word16 Gain,
Word16 Ecount, Word16 *Sd )
{
int i ;
/* Test for clearing */
if ( Ecount >= (Word16) ErrMaxNum ) {
for ( i = 0 ; i < Frame ; i ++ )
DataBuff[i] = (Word16) 0 ;
for ( i = 0 ; i < Frame+PitchMax ; i ++ )
Buff[i] = (Word16) 0 ;
}
else {
/* Interpolate accordingly to the voicing estimation */
if ( Lag != (Word16) 0 ) {
/* Voiced case */
for ( i = 0 ; i < Frame ; i ++ )
Buff[PitchMax+i] = Buff[PitchMax-(int)Lag+i] ;
for ( i = 0 ; i < Frame ; i ++ )
DataBuff[i] = Buff[PitchMax+i] = mult( Buff[PitchMax+i],
(Word16) 0x6000 ) ;
}
else {
/* Unvoiced case */
for ( i = 0 ; i < Frame ; i ++ )
DataBuff[i] = mult( Gain, Rand_lbc( Sd ) ) ;
/* Clear buffer to reset memory */
for ( i = 0 ; i < Frame+PitchMax ; i ++ )
Buff[i] = (Word16) 0 ;
}
}
return;
}
/*
**
** Function: Comp_Lpf()
**
** Description: Computes pitch postfilter parameters.
** The pitch postfilter lag is first derived (Find_B
** and Find_F). Then, the one that gives the largest
** contribution is used to calculate the gains (Get_Ind).
**
**
** Links to text: Section 3.6
**
** Arguments:
**
** Word16 *Buff decoded excitation
** Word16 Olp Decoded pitch lag
** Word16 Sfc Subframe index
**
** Outputs:
**
**
** Return value:
**
** PFDEF Pitch postfilter parameters: PF.Gain Pitch Postfilter gain
** PF.ScGn Pitch Postfilter scaling gain
** PF.Indx Pitch postfilter lag
*/
PFDEF Comp_Lpf( Word16 *Buff, Word16 Olp, Word16 Sfc )
{
int i,j ;
PFDEF Pf ;
Word32 Lcr[5] ;
Word16 Scr[5] ;
Word16 Bindx, Findx ;
Word16 Exp ;
Word32 Acc0,Acc1 ;
/* Initialize */
Pf.Indx = (Word16) 0 ;
Pf.Gain = (Word16) 0 ;
Pf.ScGn = (Word16) 0x7fff ;
/* Find both indices */
Bindx = Find_B( Buff, Olp, Sfc ) ;
Findx = Find_F( Buff, Olp, Sfc ) ;
/* Combine the results */
if ( (Bindx == (Word16) 0) && (Findx == (Word16) 0) )
return Pf ;
/* Compute target energy */
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j],
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -