www.pudn.com > G711-729.rar > EXC_LBC.C
/*
**
** File: exc_lbc.c
**
** Description: Functions that implement adaptive and fixed codebook
** operations.
**
** Functions:
**
** Computing Open loop Pitch lag:
**
** Estim_Pitch()
**
** Harmonic noise weighting:
**
** Comp_Pw()
** Filt_Pw()
**
** Fixed Cobebook computation:
**
** Find_Fcbk()
** Gen_Trn()
** Find_Best()
** Find_Pack()
** Find_Unpk()
** ACELP_LBC_code()
** Cor_h()
** Cor_h_X()
** reset_max_time()
** D4i64_LBC()
** G_code()
** search_T0()
**
** Adaptive Cobebook computation:
**
** Find_Acbk()
** Get_Rez()
** Decod_Acbk()
**
** Pitch postfilter:
** Comp_Lpf()
** Find_B()
** Find_F()
** Filt_Lpf()
**
** Residual interpolation:
**
** Comp_Info()
** Regen()
**
*/
/*
ITU-T G.723 Speech Coder ANSI-C Source Code Version 5.00
copyright (c) 1995, AudioCodes, DSP Group, France Telecom,
Universite de Sherbrooke. All rights reserved.
*/
#include
#include
#include "typedef.h"
#include "basop.h"
#include "cst_lbc.h"
#include "tab_lbc.h"
#include "lbccodec.h"
#include "util_lbc.h"
#include "exc_lbc.h"
#include "tame.h"
#include "util_cng.h"
/*
**
** Function: Estim_Pitch()
**
** Description: Open loop pitch estimation made twice per frame (one for
** the first two subframes and one for the last two).
** The method is based on the maximization of the
** crosscorrelation of the speech.
**
** Links to text: Section 2.9
**
** Arguments:
**
** Word16 *Dpnt Perceptually weighted speech
** Word16 Start Starting index defining the subframes under study
**
** Outputs:
**
** Return value:
**
** Word16 Open loop pitch period
**
*/
Word16 Estim_Pitch( Word16 *Dpnt, Word16 Start )
{
int i,j ;
Word32 Acc0,Acc1 ;
Word16 Exp,Tmp ;
Word16 Ccr,Enr ;
Word16 Indx = (Word16) PitchMin ;
Word16 Mxp = (Word16) 30 ;
Word16 Mcr = (Word16) 0x4000 ;
Word16 Mnr = (Word16) 0x7fff ;
Word16 Pr ;
/* Init the energy estimate */
Pr = Start - (Word16)PitchMin + (Word16)1 ;
Acc1 = (Word32) 0 ;
for ( j = 0 ; j < 2*SubFrLen ; j ++ )
Acc1 = L_mac( Acc1, Dpnt[Pr+j], Dpnt[Pr+j] ) ;
/* Main Olp search loop */
for ( i = PitchMin ; i <= PitchMax-3 ; i ++ ) {
Pr = sub( Pr, (Word16) 1 ) ;
/* Energy update */
Acc1 = L_msu( Acc1, Dpnt[Pr+2*SubFrLen], Dpnt[Pr+2*SubFrLen] ) ;
Acc1 = L_mac( Acc1, Dpnt[Pr], Dpnt[Pr] ) ;
/* Compute the cross */
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < 2*SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Dpnt[Start+j], Dpnt[Pr+j] ) ;
if ( Acc0 > (Word32) 0 ) {
/* Compute Exp and mant of the cross */
Exp = norm_l( Acc0 ) ;
Acc0 = L_shl( Acc0, Exp ) ;
Exp = shl( Exp, (Word16) 1 ) ;
Ccr = round( Acc0 ) ;
Acc0 = L_mult( Ccr, Ccr ) ;
Ccr = norm_l( Acc0 ) ;
Acc0 = L_shl( Acc0, Ccr ) ;
Exp = add( Exp, Ccr ) ;
Ccr = extract_h( Acc0 ) ;
/* Do the same with energy */
Acc0 = Acc1 ;
Enr = norm_l( Acc0 ) ;
Acc0 = L_shl( Acc0, Enr ) ;
Exp = sub( Exp, Enr ) ;
Enr = round( Acc0 ) ;
if ( Ccr >= Enr ) {
Exp = sub( Exp, (Word16) 1 ) ;
Ccr = shr( Ccr, (Word16) 1 ) ;
}
if ( Exp <= Mxp ) {
if ( (Exp+1) < Mxp ) {
Indx = (Word16) i ;
Mxp = Exp ;
Mcr = Ccr ;
Mnr = Enr ;
continue ;
}
if ( (Exp+1) == Mxp )
Tmp = shr( Mcr, (Word16) 1 ) ;
else
Tmp = Mcr ;
/* Compare with equal exponents */
Acc0 = L_mult( Ccr, Mnr ) ;
Acc0 = L_msu( Acc0, Enr, Tmp ) ;
if ( Acc0 > (Word32) 0 ) {
if ( ((Word16)i - Indx) < (Word16) PitchMin ) {
Indx = (Word16) i ;
Mxp = Exp ;
Mcr = Ccr ;
Mnr = Enr ;
}
else {
Acc0 = L_mult( Ccr, Mnr ) ;
Acc0 = L_negate(L_shr( Acc0, (Word16) 2 ) ) ;
Acc0 = L_mac( Acc0, Ccr, Mnr ) ;
Acc0 = L_msu( Acc0, Enr, Tmp ) ;
if ( Acc0 > (Word32) 0 ) {
Indx = (Word16) i ;
Mxp = Exp ;
Mcr = Ccr ;
Mnr = Enr ;
}
}
}
}
}
}
return Indx ;
}
/*
**
** Function: Comp_Pw()
**
** Description: Computes harmonic noise filter coefficients.
** For each subframe, the optimal lag is searched around the
** open loop pitch lag based on only positive correlation
** maximization.
**
** Links to text: Section 2.11
**
** Arguments:
**
** Word16 *Dpnt Formant perceptually weighted speech
** Word16 Start
** Word16 Olp Open loop pitch lag
**
** Outputs: None
**
** Return value:
**
** PWDEF Word16 Indx lag of the harmonic noise shaping filter
** Word16 Gain gain of the harmonic noise shaping filter
**
*/
PWDEF Comp_Pw( Word16 *Dpnt, Word16 Start, Word16 Olp )
{
int i,j ;
Word32 Lcr[15] ;
Word16 Scr[15] ;
PWDEF Pw ;
Word32 Acc0,Acc1 ;
Word16 Exp ;
Word16 Ccr,Enr ;
Word16 Mcr,Mnr ;
/* Compute and save target energy */
Lcr[0] = (Word32) 0 ;
for ( i = 0 ; i < SubFrLen ; i ++ )
Lcr[0] = L_mac( Lcr[0], Dpnt[Start+i], Dpnt[Start+i] ) ;
/* Compute all Crosses and energys */
for ( i = 0 ; i <= 2*PwRange ; i ++ ) {
Acc1 = Acc0 = (Word32) 0 ;
for ( j = 0 ; j < SubFrLen ; j ++ ) {
Acc0 = L_mac( Acc0, Dpnt[Start+j],
Dpnt[Start-(Olp-PwRange+i)+j]) ;
Acc1 = L_mac( Acc1, Dpnt[Start-(Olp-PwRange+i)+j],
Dpnt[Start-(Olp-PwRange+i)+j] ) ;
}
/* Save both */
Lcr[2*i+1] = Acc1 ;
Lcr[2*i+2] = Acc0 ;
}
/* Normalize to maximum */
Acc1 = (Word32) 0 ;
for ( i = 0 ; i < 15 ; i ++ ) {
Acc0 = Lcr[i] ;
Acc0 = L_abs( Acc0 ) ;
if ( Acc0 > Acc1 )
Acc1 = Acc0 ;
}
Exp = norm_l( Acc1 ) ;
for ( i = 0 ; i < 15 ; i ++ ) {
Acc0 = L_shl( Lcr[i], Exp ) ;
Scr[i] = round( Acc0 ) ;
}
/* Find the best pair */
Pw.Indx = (Word16) -1 ;
Pw.Gain = (Word16) 0 ;
Mcr = (Word16) 1 ;
Mnr = (Word16) 0x7fff ;
for ( i = 0 ; i <= 2*PwRange ; i ++ ) {
Enr = Scr[2*i+1] ;
Ccr = Scr[2*i+2] ;
if ( Ccr <= (Word16) 0 )
continue ;
Exp = mult_r( Ccr, Ccr ) ;
/* Compute the cross */
Acc0 = L_mult( Exp, Mnr ) ;
Acc0 = L_msu ( Acc0, Enr, Mcr ) ;
if ( Acc0 > (Word32) 0 ) {
Mcr = Exp ;
Mnr = Enr ;
Pw.Indx = (Word16)i ;
}
}
if ( Pw.Indx == -1 ) {
Pw.Indx = Olp ;
return Pw ;
}
/* Check the db limit */
Acc0 = L_mult( Scr[0], Mnr ) ;
Acc1 = Acc0 ;
Acc0 = L_shr( Acc0, (Word16) 2 ) ;
Acc1 = L_shr( Acc1, (Word16) 3 ) ;
Acc0 = L_add( Acc0, Acc1 ) ;
Acc1 = L_mult( Scr[2*Pw.Indx+2], Scr[2*Pw.Indx+2] ) ;
Acc0 = L_sub( Acc0, Acc1 ) ;
if ( Acc0 < (Word32) 0 ) {
Exp = Scr[2*Pw.Indx + 2] ;
if ( Exp >= Mnr )
Pw.Gain = PwConst ;
else {
Pw.Gain = div_s( Exp, Mnr ) ;
Pw.Gain = mult_r( Pw.Gain, PwConst ) ;
}
}
Pw.Indx = Olp - PwRange + Pw.Indx ;
return Pw ;
}
/*
**
** Function: Filt_Pw()
**
** Description: Applies harmonic noise shaping filter.
** Lth order FIR filter on each subframe (L: lag of the filter).
**
** Links to text: Section 2.11
**
** Arguments:
**
** Word16 *DataBuff Target vector
** Word16 *Dpnt Formant perceptually weighted speech
** Word16 Start
** PWDEF Pw Parameters of the harmonic noise shaping filter
**
** Outputs:
**
** Word16 *DataBuff Target vector
**
** Return value: None
**
*/
void Filt_Pw( Word16 *DataBuff, Word16 *Dpnt, Word16 Start, PWDEF Pw )
{
int i ;
Word32 Acc0 ;
/* Perform the harmonic weighting */
for ( i = 0 ; i < SubFrLen ; i ++ ) {
Acc0 = L_deposit_h( Dpnt[PitchMax+Start+i] ) ;
Acc0 = L_msu( Acc0, Pw.Gain, Dpnt[PitchMax+Start-Pw.Indx+i] ) ;
DataBuff[Start+(Word16)i] = round( Acc0 ) ;
}
return;
}
/*
**
** Function: Find_Fcbk()
**
** Description: Fixed codebook excitation computation.
**
**
** Links to text: Sections 2.15 & 2.16
**
** Arguments:
**
** Word16 *Dpnt Target vector
** Word16 *ImpResp Impulse response of the synthesis filter
** LineDef *Line Excitation parameters for one subframe
** Word16 Sfc Subframe index
**
** Outputs:
**
** Word16 *Dpnt Excitation vector
** LINEDEF *Line Fixed codebook parameters for one subframe
**
** Return value: None
**
*/
void Find_Fcbk( Word16 *Dpnt, Word16 *ImpResp, LINEDEF *Line, Word16 Sfc )
{
int i ;
Word16 T0_acelp, gain_T0;
Word16 Srate ;
BESTDEF Best ;
switch(WrkRate) {
case Rate63: {
Srate = Nb_puls[(int)Sfc] ;
Best.MaxErr = (Word32) 0xc0000000L ;
Find_Best( &Best, Dpnt, ImpResp, Srate, (Word16) SubFrLen ) ;
if ( (*Line).Olp[Sfc>>1] < (Word16) (SubFrLen-2) ) {
Find_Best( &Best, Dpnt, ImpResp, Srate, (*Line).Olp[Sfc>>1]);
}
/* Reconstruct the excitation */
for ( i = 0 ; i < SubFrLen ; i ++ )
Dpnt[i] = (Word16) 0 ;
for ( i = 0 ; i < Srate ; i ++ )
Dpnt[Best.Ploc[i]] = Best.Pamp[i] ;
/* Code the excitation */
Fcbk_Pack( Dpnt, &((*Line).Sfs[Sfc]), &Best, Srate ) ;
if ( Best.UseTrn == (Word16) 1 )
Gen_Trn( Dpnt, Dpnt, (*Line).Olp[Sfc>>1] ) ;
break;
}
case Rate53: {
T0_acelp = search_T0(
(Word16) ((*Line).Olp[Sfc>>1]-1+(*Line).Sfs[Sfc].AcLg),
(*Line).Sfs[Sfc].AcGn, &gain_T0 );
(*Line).Sfs[Sfc].Ppos = ACELP_LBC_code(
Dpnt, ImpResp, T0_acelp, Dpnt, &(*Line).Sfs[Sfc].Mamp,
&(*Line).Sfs[Sfc].Grid, &(*Line).Sfs[Sfc].Pamp, gain_T0 );
(*Line).Sfs[Sfc].Tran = 0;
break;
}
}
return;
}
/*
**
** Function: Gen_Trn()
**
** Description: Generation of a train of Dirac functions with the period
** Olp.
**
** Links to text: Section 2.15
**
** Arguments:
**
** Word16 *Dst Fixed codebook excitation vector with train of Dirac
** Word16 *Src Fixed codebook excitation vector without train of Dirac
** Word16 Olp Closed-loop pitch lag of subframe 0 (for subframes 0 & 1)
** Closed-loop pitch lag of subframe 2 (for subframes 2 & 3)
**
** Outputs:
**
** Word16 *Dst excitation vector
**
** Return value: None
**
*/
void Gen_Trn( Word16 *Dst, Word16 *Src, Word16 Olp )
{
int i ;
Word16 Tmp0,Tmp1 ;
Word16 Tmp[SubFrLen] ;
Tmp0 = Olp ;
for ( i = 0 ; i < SubFrLen ; i ++ ) {
Tmp[i] = Src[i] ;
Dst[i] = Src[i] ;
}
while ( Tmp0 < SubFrLen ) {
for ( i = (int) Tmp0 ; i < SubFrLen ; i ++ ) {
Tmp1 = add( Dst[i], Tmp[i-(int)Tmp0] ) ;
Dst[i] = Tmp1 ;
}
Tmp0 = add( Tmp0, Olp ) ;
}
return;
}
/*
**
** Function: Find_Best()
**
** Description: Fixed codebook search for the high rate encoder.
** It performs the quantization of the residual signal.
** The excitation made of Np positive or negative pulses
** multiplied by a gain and whose positions on the grid are
** either all odd or all even, should approximate as best as
** possible the residual signal (perceptual criterion).
**
** Links to text: Section 2.15
**
** Arguments:
**
** BESTDEF *Best Parameters of the best excitation model
** Word16 *Tv Target vector
** Word16 *ImpResp Impulse response of the combined filter
** Word16 Np Number of pulses (6 for even subframes; 5 for odd subframes)
** Word16 Olp Closed-loop pitch lag of subframe 0 (for subframes 0 & 1)
** Closed-loop pitch lag of subframe 2 (for subframes 2 & 3)
**
** Outputs:
**
** BESTDEF *Best
**
** Return value: None
**
*/
void Find_Best( BESTDEF *Best, Word16 *Tv, Word16 *ImpResp, Word16 Np,
Word16 Olp )
{
int i,j,k,l ;
BESTDEF Temp ;
Word16 Exp ;
Word16 MaxAmpId ;
Word16 MaxAmp ;
Word32 Acc0,Acc1,Acc2 ;
Word16 Imr[SubFrLen] ;
Word16 OccPos[SubFrLen] ;
Word16 ImrCorr[SubFrLen] ;
Word32 ErrBlk[SubFrLen] ;
Word32 WrkBlk[SubFrLen] ;
/* Update Impulse response */
if ( Olp < (Word16) (SubFrLen-2) ) {
Temp.UseTrn = (Word16) 1 ;
Gen_Trn( Imr, ImpResp, Olp ) ;
}
else {
Temp.UseTrn = (Word16) 0 ;
for ( i = 0 ; i < SubFrLen ; i ++ )
Imr[i] = ImpResp[i] ;
}
/* Scale Imr to avoid overflow */
for ( i = 0 ; i < SubFrLen ; i ++ )
OccPos[i] = shr( Imr[i], (Word16) 1 ) ;
/* Compute Imr AutoCorr function */
Acc0 = (Word32) 0 ;
for ( i = 0 ; i < SubFrLen ; i ++ )
Acc0 = L_mac( Acc0, OccPos[i], OccPos[i] ) ;
Exp = norm_l( Acc0 ) ;
Acc0 = L_shl( Acc0, Exp ) ;
ImrCorr[0] = round( Acc0 ) ;
/* Compute all the other */
for ( i = 1 ; i < SubFrLen ; i ++ ) {
Acc0 = (Word32) 0 ;
for ( j = i ; j < SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, OccPos[j], OccPos[j-i] ) ;
Acc0 = L_shl( Acc0, Exp ) ;
ImrCorr[i] = round( Acc0 ) ;
}
/* Cross correlation with the signal */
Exp = sub( Exp, 4 ) ;
for ( i = 0 ; i < SubFrLen ; i ++ ) {
Acc0 = (Word32) 0 ;
for ( j = i ; j < SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Tv[j], Imr[j-i] ) ;
ErrBlk[i] = L_shl( Acc0, Exp ) ;
}
/* Search for the best sequence */
for ( k = 0 ; k < Sgrid ; k ++ ) {
Temp.GridId = (Word16) k ;
/* Find maximum amplitude */
Acc1 = (Word32) 0 ;
for ( i = k ; i < SubFrLen ; i += Sgrid ) {
Acc0 = L_abs( ErrBlk[i] ) ;
if ( Acc0 >= Acc1 ) {
Acc1 = Acc0 ;
Temp.Ploc[0] = (Word16) i ;
}
}
/* Quantize the maximum amplitude */
Acc2 = Acc1 ;
Acc1 = (Word32) 0x40000000L ;
MaxAmpId = (Word16) (NumOfGainLev - MlqSteps) ;
for ( i = MaxAmpId ; i >= MlqSteps ; i -- ) {
Acc0 = L_mult( FcbkGainTable[i], ImrCorr[0] ) ;
Acc0 = L_sub( Acc0, Acc2 ) ;
Acc0 = L_abs( Acc0 ) ;
if ( Acc0 < Acc1 ) {
Acc1 = Acc0 ;
MaxAmpId = (Word16) i ;
}
}
MaxAmpId -- ;
for ( i = 1 ; i <=2*MlqSteps ; i ++ ) {
for ( j = k ; j < SubFrLen ; j += Sgrid ) {
WrkBlk[j] = ErrBlk[j] ;
OccPos[j] = (Word16) 0 ;
}
Temp.MampId = MaxAmpId - (Word16) MlqSteps + (Word16) i ;
MaxAmp = FcbkGainTable[Temp.MampId] ;
if ( WrkBlk[Temp.Ploc[0]] >= (Word32) 0 )
Temp.Pamp[0] = MaxAmp ;
else
Temp.Pamp[0] = negate(MaxAmp) ;
OccPos[Temp.Ploc[0]] = (Word16) 1 ;
for ( j = 1 ; j < Np ; j ++ ) {
Acc1 = (Word32) 0xc0000000L ;
for ( l = k ; l < SubFrLen ; l += Sgrid ) {
if ( OccPos[l] != (Word16) 0 )
continue ;
Acc0 = WrkBlk[l] ;
Acc0 = L_msu( Acc0, Temp.Pamp[j-1],
ImrCorr[abs_s((Word16)(l-Temp.Ploc[j-1]))] ) ;
WrkBlk[l] = Acc0 ;
Acc0 = L_abs( Acc0 ) ;
if ( Acc0 > Acc1 ) {
Acc1 = Acc0 ;
Temp.Ploc[j] = (Word16) l ;
}
}
if ( WrkBlk[Temp.Ploc[j]] >= (Word32) 0 )
Temp.Pamp[j] = MaxAmp ;
else
Temp.Pamp[j] = negate(MaxAmp) ;
OccPos[Temp.Ploc[j]] = (Word16) 1 ;
}
/* Compute error vector */
for ( j = 0 ; j < SubFrLen ; j ++ )
OccPos[j] = (Word16) 0 ;
for ( j = 0 ; j < Np ; j ++ )
OccPos[Temp.Ploc[j]] = Temp.Pamp[j] ;
for ( l = SubFrLen-1 ; l >= 0 ; l -- ) {
Acc0 = (Word32) 0 ;
for ( j = 0 ; j <= l ; j ++ )
Acc0 = L_mac( Acc0, OccPos[j], Imr[l-j] ) ;
Acc0 = L_shl( Acc0, (Word16) 2 ) ;
OccPos[l] = extract_h( Acc0 ) ;
}
/* Evaluate error */
Acc1 = (Word32) 0 ;
for ( j = 0 ; j < SubFrLen ; j ++ ) {
Acc1 = L_mac( Acc1, Tv[j], OccPos[j] ) ;
Acc0 = L_mult( OccPos[j], OccPos[j] ) ;
Acc1 = L_sub( Acc1, L_shr( Acc0, (Word16) 1 ) ) ;
}
if ( Acc1 > (*Best).MaxErr ) {
(*Best).MaxErr = Acc1 ;
(*Best).GridId = Temp.GridId ;
(*Best).MampId = Temp.MampId ;
(*Best).UseTrn = Temp.UseTrn ;
for ( j = 0 ; j < Np ; j ++ ) {
(*Best).Pamp[j] = Temp.Pamp[j] ;
(*Best).Ploc[j] = Temp.Ploc[j] ;
}
}
}
}
return;
}
/*
**
** Function: Fcbk_Pack()
**
** Description: Encoding of the pulse positions and gains for the high
** rate case.
** Combinatorial encoding is used to transmit the optimal
** combination of pulse locations.
**
** Links to text: Section 2.15
**
** Arguments:
**
** Word16 *Dpnt Excitation vector
** SFSDEF *Sfs Encoded parameters of the excitation model
** BESTDEF *Best Parameters of the best excitation model
** Word16 Np Number of pulses (6 for even subframes; 5 for odd subframes)
**
** Outputs:
**
** SFSDEF *Sfs Encoded parameters of the excitation model
**
** Return value: None
**
*/
void Fcbk_Pack( Word16 *Dpnt, SFSDEF *Sfs, BESTDEF *Best, Word16 Np )
{
int i,j ;
/* Code the amplitudes and positions */
j = MaxPulseNum - (int) Np ;
(*Sfs).Pamp = (Word16) 0 ;
(*Sfs).Ppos = (Word32) 0 ;
for ( i = 0 ; i < SubFrLen/Sgrid ; i ++ ) {
if ( Dpnt[(int)(*Best).GridId + Sgrid*i] == (Word16) 0 )
(*Sfs).Ppos = L_add( (*Sfs).Ppos, CombinatorialTable[j][i] ) ;
else {
(*Sfs).Pamp = shl( (*Sfs).Pamp, (Word16) 1 ) ;
if ( Dpnt[(int)(*Best).GridId + Sgrid*i] < (Word16) 0 )
(*Sfs).Pamp = add( (*Sfs).Pamp, (Word16) 1 ) ;
j ++ ;
/* Check for end */
if ( j == MaxPulseNum )
break ;
}
}
(*Sfs).Mamp = (*Best).MampId ;
(*Sfs).Grid = (*Best).GridId ;
(*Sfs).Tran = (*Best).UseTrn ;
return;
}
/*
**
** Function: Fcbk_Unpk()
**
** Description: Decoding of the fixed codebook excitation for both rates.
** Gains, pulse positions, grid position (odd or even), signs
** are decoded and used to reconstruct the excitation.
**
** Links to text: Section 2.17 & 3.5
**
** Arguments:
**
** Word16 *Tv Decoded excitation vector
** SFSDEF Sfs Encoded parameters of the excitation (for one subframe)
** Word16 Olp Closed loop adaptive pitch lag
** Word16 Sfc Subframe index
**
** Outputs:
**
** Word16 *Tv Decoded excitation vector
**
** Return value: None
**
*/
void Fcbk_Unpk( Word16 *Tv, SFSDEF Sfs, Word16 Olp, Word16 Sfc )
{
int i,j ;
Word32 Acc0 ;
Word16 Np ;
Word16 Tv_tmp[SubFrLen+4];
Word16 acelp_gain, acelp_sign, acelp_shift, acelp_pos;
Word16 offset, ipos, T0_acelp, gain_T0;
switch(WrkRate) {
case Rate63: {
Np = Nb_puls[(int)Sfc] ;
for ( i = 0 ; i < SubFrLen ; i ++ )
Tv[i] = (Word16) 0 ;
if ( Sfs.Ppos >= MaxPosTable[Sfc] )
return ;
/* Decode the amplitudes and positions */
j = MaxPulseNum - (int) Np ;
Acc0 = Sfs.Ppos ;
for ( i = 0 ; i < SubFrLen/Sgrid ; i ++ ) {
Acc0 = L_sub( Acc0, CombinatorialTable[j][i] ) ;
if ( Acc0 < (Word32) 0 ) {
Acc0 = L_add( Acc0, CombinatorialTable[j][i] ) ;
j ++ ;
if ( (Sfs.Pamp & (1 << (MaxPulseNum-j) )) != (Word16) 0 )
Tv[(int)Sfs.Grid + Sgrid*i] = -FcbkGainTable[Sfs.Mamp] ;
else
Tv[(int)Sfs.Grid + Sgrid*i] = FcbkGainTable[Sfs.Mamp] ;
if ( j == MaxPulseNum )
break ;
}
}
if ( Sfs.Tran == (Word16) 1 )
Gen_Trn( Tv, Tv, Olp ) ;
break;
}
case Rate53: {
for ( i = 0 ; i < SubFrLen+4 ; i ++ )
Tv_tmp[i] = (Word16) 0 ;
/* decoding gain */
acelp_gain = FcbkGainTable[Sfs.Mamp];
/* decoding grid */
acelp_shift = Sfs.Grid;
/* decoding Sign */
acelp_sign = Sfs.Pamp;
/* decoding Pos */
acelp_pos = (short) Sfs.Ppos;
offset = 0;
for(i=0; i<4; i++) {
ipos = (acelp_pos & (Word16)0x0007) ;
ipos = shl(ipos,3) + acelp_shift + offset;
if( (acelp_sign & 1 )== 1) {
Tv_tmp[ipos] = acelp_gain;
}
else {
Tv_tmp[ipos] = -acelp_gain;
}
offset = add(offset,2);
acelp_pos = shr(acelp_pos, 3);
acelp_sign = shr(acelp_sign,1);
}
for (i = 0; i < SubFrLen; i++) Tv[i] = Tv_tmp[i];
T0_acelp = search_T0( (Word16) (Olp-1+Sfs.AcLg), Sfs.AcGn,
&gain_T0);
if(T0_acelp (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],
Buff[PitchMax+(int)Sfc*SubFrLen+j] ) ;
Lcr[0] = Acc0 ;
if ( Bindx != (Word16) 0 ) {
Acc0 = (Word32) 0 ;
Acc1 = (Word32) 0 ;
for ( j = 0 ; j < SubFrLen ; j ++ ) {
Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j],
Buff[PitchMax+(int)Sfc*SubFrLen+(int)Bindx+j] ) ;
Acc1 = L_mac( Acc1, Buff[PitchMax+(int)Sfc*SubFrLen+(int)Bindx+j],
Buff[PitchMax+(int)Sfc*SubFrLen+(int)Bindx+j] ) ;
}
Lcr[1] = Acc0 ;
Lcr[2] = Acc1 ;
}
else {
Lcr[1] = (Word32) 0 ;
Lcr[2] = (Word32) 0 ;
}
if ( Findx != (Word16) 0 ) {
Acc0 = (Word32) 0 ;
Acc1 = (Word32) 0 ;
for ( j = 0 ; j < SubFrLen ; j ++ ) {
Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j],
Buff[PitchMax+(int)Sfc*SubFrLen+(int)Findx+j] ) ;
Acc1 = L_mac( Acc1, Buff[PitchMax+(int)Sfc*SubFrLen+(int)Findx+j],
Buff[PitchMax+(int)Sfc*SubFrLen+(int)Findx+j] ) ;
}
Lcr[3] = Acc0 ;
Lcr[4] = Acc1 ;
}
else {
Lcr[3] = (Word32) 0 ;
Lcr[4] = (Word32) 0 ;
}
/* Normalize and convert to shorts */
Acc1 = 0L ;
for ( i = 0 ; i < 5 ; i ++ ) {
Acc0 = Lcr[i] ;
if ( Acc0 > Acc1 )
Acc1 = Acc0 ;
}
Exp = norm_l( Acc1 ) ;
for ( i = 0 ; i < 5 ; i ++ ) {
Acc0 = L_shl( Lcr[i], Exp ) ;
Scr[i] = extract_h( Acc0 ) ;
}
/* Select the best pair */
if ( (Bindx != (Word16) 0) && ( Findx == (Word16) 0) )
Pf = Get_Ind( Bindx, Scr[0], Scr[1], Scr[2] ) ;
if ( (Bindx == (Word16) 0) && ( Findx != (Word16) 0) )
Pf = Get_Ind( Findx, Scr[0], Scr[3], Scr[4] ) ;
if ( (Bindx != (Word16) 0) && ( Findx != (Word16) 0) ) {
Exp = mult_r( Scr[1], Scr[1] ) ;
Acc0 = L_mult( Exp, Scr[4] ) ;
Exp = mult_r( Scr[3], Scr[3] ) ;
Acc1 = L_mult( Exp, Scr[2] ) ;
if ( Acc0 > Acc1 )
Pf = Get_Ind( Bindx, Scr[0], Scr[1], Scr[2] ) ;
else
Pf = Get_Ind( Findx, Scr[0], Scr[3], Scr[4] ) ;
}
return Pf ;
}
/*
**
** Function: Find_B()
**
** Description: Computes best pitch postfilter backward lag by
** backward cross correlation maximization around the
** decoded pitch lag
** of the subframe 0 (for subframes 0 & 1)
** of the subframe 2 (for subframes 2 & 3)
**
** Links to text: Section 3.6
**
** Arguments:
**
** Word16 *Buff decoded excitation
** Word16 Olp Decoded pitch lag
** Word16 Sfc Subframe index
**
** Outputs: None
**
** Return value:
**
** Word16 Pitch postfilter backward lag
*/
Word16 Find_B( Word16 *Buff, Word16 Olp, Word16 Sfc )
{
int i,j ;
Word16 Indx = 0 ;
Word32 Acc0,Acc1 ;
if ( Olp > (Word16) (PitchMax-3) )
Olp = (Word16) (PitchMax-3) ;
Acc1 = (Word32) 0 ;
for ( i = (int)Olp-3 ; i <= (int)Olp+3 ; i ++ ) {
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j],
Buff[PitchMax+(int)Sfc*SubFrLen-i+j] ) ;
if ( Acc0 > Acc1 ) {
Acc1 = Acc0 ;
Indx = -(Word16) i ;
}
}
return Indx ;
}
/*
**
** Function: Find_F()
**
** Description: Computes best pitch postfilter forward lag by
** forward cross correlation maximization around the
** decoded pitch lag
** of the subframe 0 (for subframes 0 & 1)
** of the subframe 2 (for subframes 2 & 3)
**
** Links to text: Section 3.6
**
** Arguments:
**
** Word16 *Buff decoded excitation
** Word16 Olp Decoded pitch lag
** Word16 Sfc Subframe index
**
** Outputs: None
**
** Return value:
**
** Word16 Pitch postfilter forward lag
*/
Word16 Find_F( Word16 *Buff, Word16 Olp, Word16 Sfc )
{
int i,j ;
Word16 Indx = 0 ;
Word32 Acc0,Acc1 ;
if ( Olp > (Word16) (PitchMax-3) )
Olp = (Word16) (PitchMax-3) ;
Acc1 = (Word32) 0 ;
for ( i = Olp-3 ; i <= Olp+3 ; i ++ ) {
Acc0 = (Word32) 0 ;
if ( ((int)Sfc*SubFrLen+SubFrLen+i) <= Frame ) {
for ( j = 0 ; j < SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+j],
Buff[PitchMax+(int)Sfc*SubFrLen+i+j] ) ;
}
if ( Acc0 > Acc1 ) {
Acc1 = Acc0 ;
Indx = (Word16) i ;
}
}
return Indx ;
}
/*
**
** Function: Get_Ind()
**
** Description: Computes gains of the pitch postfilter.
** The gains are calculated using the cross correlation
** (forward or backward, the one with the greatest contribution)
** and the energy of the signal. Also, a test is performed on
** the prediction gain to see whether the pitch postfilter
** should be used or not.
**
**
**
** Links to text: Section 3.6
**
** Arguments:
**
** Word16 Ind Pitch postfilter lag
** Word16 Ten energy of the current subframe excitation vector
** Word16 Ccr Crosscorrelation of the excitation
** Word16 Enr Energy of the (backward or forward) "delayed" excitation
**
** Outputs: None
**
** Return value:
**
** PFDEF
** Word16 Indx Pitch postfilter lag
** Word16 Gain Pitch postfilter gain
** Word16 ScGn Pitch postfilter scaling gain
**
*/
PFDEF Get_Ind( Word16 Ind, Word16 Ten, Word16 Ccr, Word16 Enr )
{
Word32 Acc0,Acc1 ;
Word16 Exp ;
PFDEF Pf ;
Pf.Indx = Ind ;
/* Check valid gain */
Acc0 = L_mult( Ten, Enr ) ;
Acc0 = L_shr( Acc0, (Word16) 2 ) ;
Acc1 = L_mult( Ccr, Ccr ) ;
if ( Acc1 > Acc0 ) {
if ( Ccr >= Enr )
Pf.Gain = LpfConstTable[(int)WrkRate] ;
else {
Pf.Gain = div_s( Ccr, Enr ) ;
Pf.Gain = mult( Pf.Gain, LpfConstTable[(int)WrkRate] ) ;
}
/* Compute scaling gain */
Acc0 = L_deposit_h( Ten ) ;
Acc0 = L_shr( Acc0, (Word16) 1 ) ;
Acc0 = L_mac( Acc0, Ccr, Pf.Gain ) ;
Exp = mult( Pf.Gain, Pf.Gain ) ;
Acc1 = L_mult( Enr, Exp ) ;
Acc1 = L_shr( Acc1, (Word16) 1 ) ;
Acc0 = L_add( Acc0, Acc1 ) ;
Exp = round( Acc0 ) ;
Acc1 = L_deposit_h( Ten ) ;
Acc0 = L_deposit_h( Exp ) ;
Acc1 = L_shr( Acc1, (Word16) 1 ) ;
if ( Acc1 >= Acc0 )
Exp = (Word16) 0x7fff ;
else
Exp = div_l( Acc1, Exp ) ;
Acc0 = L_deposit_h( Exp ) ;
Pf.ScGn = Sqrt_lbc( Acc0 ) ;
}
else {
Pf.Gain = (Word16) 0 ;
Pf.ScGn = (Word16) 0x7fff ;
}
Pf.Gain = mult( Pf.Gain, Pf.ScGn ) ;
return Pf ;
}
/*
**
** Function: Filt_Lpf()
**
** Description: Applies the pitch postfilter for each subframe.
**
** Links to text: Section 3.6
**
** Arguments:
**
** Word16 *Tv Pitch postfiltered excitation
** Word16 *Buff decoded excitation
** PFDEF Pf Pitch postfilter parameters
** Word16 Sfc Subframe index
**
** Outputs:
**
** Word16 *Tv Pitch postfiltered excitation
**
** Return value: None
**
*/
void Filt_Lpf( Word16 *Tv, Word16 *Buff, PFDEF Pf, Word16 Sfc )
{
int i ;
Word32 Acc0 ;
for ( i = 0 ; i < SubFrLen ; i ++ ) {
Acc0 = L_mult( Buff[PitchMax+(int)Sfc*SubFrLen+i], Pf.ScGn ) ;
Acc0 = L_mac( Acc0, Buff[PitchMax+(int)Sfc*SubFrLen+(int)Pf.Indx+i],
Pf.Gain ) ;
Tv[(int)Sfc*SubFrLen+i] = round( Acc0 ) ;
}
return;
}
/*
**
** Function: ACELP_LBC_code()
**
** Description: Find Algebraic codebook for low bit rate LBC encoder
**
** Links to text: Section 2.16
**
** Arguments:
**
** Word16 X[] Target vector. (in Q0)
** Word16 h[] Impulse response. (in Q12)
** Word16 T0 Pitch period.
** Word16 code[] Innovative vector. (in Q12)
** Word16 gain Innovative vector gain. (in Q0)
** Word16 sign Signs of the 4 pulses.
** Word16 shift Shift of the innovative vector
** Word16 gain_T0 Gain for pitch synchronous fiter
**
** Inputs :
**
** Word16 X[] Target vector. (in Q0)
** Word16 h[] Impulse response. (in Q12)
** Word16 T0 Pitch period.
** Word16 gain_T0 Gain for pitch synchronous fiter
**
** Outputs:
**
** Word16 code[] Innovative vector. (in Q12)
** Word16 gain Innovative vector gain. (in Q0)
** Word16 sign Signs of the 4 pulses.
** Word16 shift Shift of the innovative vector.
**
** Return value:
**
** Word16 index Innovative codebook index
**
*/
Word16 ACELP_LBC_code(Word16 X[], Word16 h[], Word16 T0, Word16 code[],
Word16 *ind_gain, Word16 *shift, Word16 *sign, Word16 gain_T0)
{
Word16 i, index, gain_q;
Word16 Dn[SubFrLen2], tmp_code[SubFrLen2];
Word16 rr[DIM_RR];
/*
* Include fixed-gain pitch contribution into impulse resp. h[]
* Find correlations of h[] needed for the codebook search.
*/
for (i = 0; i < SubFrLen; i++) /* Q13 --> Q12*/
h[i] = shr(h[i], 1);
if (T0 < SubFrLen-2) {
for (i = T0; i < SubFrLen; i++) /* h[i] += gain_T0*h[i-T0] */
h[i] = add(h[i], mult(h[i-T0], gain_T0));
}
Cor_h(h, rr);
/*
* Compute correlation of target vector with impulse response.
*/
Cor_h_X(h, X, Dn);
/*
* Find innovative codebook.
* rr input matrix autocorrelation
* output filtered codeword
*/
index = D4i64_LBC(Dn, rr, h, tmp_code, rr, shift, sign);
/*
* Compute innovation vector gain.
* Include fixed-gain pitch contribution into code[].
*/
*ind_gain = G_code(X, rr, &gain_q);
for (i = 0; i < SubFrLen; i++) {
code[i] = i_mult(tmp_code[i], gain_q);
}
if(T0 < SubFrLen-2)
for (i = T0; i < SubFrLen; i++) /* code[i] += gain_T0*code[i-T0] */
code[i] = add(code[i], mult(code[i-T0], gain_T0));
return index;
}
/*
**
** Function: Cor_h()
**
** Description: Compute correlations of h[] needed for the codebook search.
**
** Links to text: Section 2.16
**
** Arguments:
**
** Word16 h[] Impulse response.
** Word16 rr[] Correlations.
**
** Outputs:
**
** Word16 rr[] Correlations.
**
** Return value : None
*/
void Cor_h(Word16 *H, Word16 *rr)
{
Word16 *rri0i0, *rri1i1, *rri2i2, *rri3i3;
Word16 *rri0i1, *rri0i2, *rri0i3;
Word16 *rri1i2, *rri1i3, *rri2i3;
Word16 *p0, *p1, *p2, *p3;
Word16 *ptr_hd, *ptr_hf, *ptr_h1, *ptr_h2;
Word32 cor;
Word16 i, k, ldec, l_fin_sup, l_fin_inf;
Word16 h[SubFrLen2];
/* Scaling for maximum precision */
cor = 0;
for(i=0; i 32000 ) {
for(i=0; i max) max = s;
}
/*
* Find the number of right shifts to do on y32[]
* so that maximum is on 13 bits
*/
j = norm_l(max);
if( sub(j,16) > 0) j = 16;
j = sub(18, j);
for(i=0; i 17 bits; 4 pulses in a frame of 60 samples
**
** The code length is 60, containing 4 nonzero pulses
** i0, i1, i2, i3. Each pulse can have 8 possible
** positions (positive or negative):
**
** i0 (+-1) : 0, 8, 16, 24, 32, 40, 48, 56
** i1 (+-1) : 2, 10, 18, 26, 34, 42, 50, 58
** i2 (+-1) : 4, 12, 20, 28, 36, 44, 52, (60)
** i3 (+-1) : 6, 14, 22, 30, 38, 46, 54, (62)
**
** All the pulse can be shifted by one.
** The last position of the last 2 pulses falls outside the
** frame and signifies that the pulse is not present.
** The threshold controls if a section of the innovative
** codebook should be searched or not.
**
** Links to the text: Section 2.16
**
** Input arguments:
**
** Word16 Dn[] Correlation between target vector and impulse response h[]
** Word16 rr[] Correlations of impulse response h[]
** Word16 h[] Impulse response of filters
**
** Output arguments:
**
** Word16 cod[] Selected algebraic codeword
** Word16 y[] Filtered codeword
** Word16 code_shift Shift of the codeword
** Word16 sign Signs of the 4 pulses.
**
** Return value:
**
** Word16 Index of selected codevector
**
*/
Word16 D4i64_LBC(Word16 Dn[], Word16 rr[], Word16 h[], Word16 cod[],
Word16 y[], Word16 *code_shift, Word16 *sign)
{
Word16 i0, i1, i2, i3, ip0, ip1, ip2, ip3;
Word16 i, j, time;
Word16 shif, shift;
Word16 ps0, ps1, ps2, ps3, alp, alp0;
Word32 alp1, alp2, alp3, L32;
Word16 ps0a, ps1a, ps2a;
Word16 ps3c, psc, alpha;
Word16 means, max0, max1, max2, thres;
Word16 *rri0i0, *rri1i1, *rri2i2, *rri3i3;
Word16 *rri0i1, *rri0i2, *rri0i3;
Word16 *rri1i2, *rri1i3, *rri2i3;
Word16 *ptr_ri0i0, *ptr_ri1i1, *ptr_ri2i2, *ptr_ri3i3;
Word16 *ptr_ri0i1, *ptr_ri0i2, *ptr_ri0i3;
Word16 *ptr_ri1i2, *ptr_ri1i3, *ptr_ri2i3;
Word16 *ptr1_ri0i1, *ptr1_ri0i2, *ptr1_ri0i3;
Word16 *ptr1_ri1i2, *ptr1_ri1i3, *ptr1_ri2i3;
Word16 p_sign[SubFrLen2/2];
/* Init pointers */
rri0i0 = rr;
rri1i1 = rri0i0 + NB_POS;
rri2i2 = rri1i1 + NB_POS;
rri3i3 = rri2i2 + NB_POS;
rri0i1 = rri3i3 + NB_POS;
rri0i2 = rri0i1 + MSIZE;
rri0i3 = rri0i2 + MSIZE;
rri1i2 = rri0i3 + MSIZE;
rri1i3 = rri1i2 + MSIZE;
rri2i3 = rri1i3 + MSIZE;
/*
* Extend the backward filtered target vector by zeros
*/
for (i = SubFrLen; i < SubFrLen2; i++) Dn[i] = 0;
/*
* Chose the sign of the impulse.
*/
for (i=0; i= 0) {
p_sign[i/2] = 1;
}
else {
p_sign[i/2] = -1;
Dn[i] = -Dn[i];
Dn[i+1] = -Dn[i+1];
}
}
p_sign[30] = p_sign[31] = 1;
/*
* Compute the search threshold after three pulses
*/
/* odd positions */
/* Find maximum of Dn[i0]+Dn[i1]+Dn[i2] */
max0 = Dn[0];
max1 = Dn[2];
max2 = Dn[4];
for (i = 8; i < SubFrLen; i+=STEP) {
if (Dn[i] > max0) max0 = Dn[i];
if (Dn[i+2] > max1) max1 = Dn[i+2];
if (Dn[i+4] > max2) max2 = Dn[i+4];
}
max0 = add(max0, max1);
max0 = add(max0, max2);
/* Find means of Dn[i0]+Dn[i1]+Dn[i2] */
L32 = 0;
for (i = 0; i < SubFrLen; i+=STEP) {
L32 = L_mac(L32, Dn[i], 1);
L32 = L_mac(L32, Dn[i+2], 1);
L32 = L_mac(L32, Dn[i+4], 1);
}
means =extract_l( L_shr(L32, 4));
/* thres = means + (max0-means)*threshold; */
thres = sub(max0, means);
thres = mult(thres, threshold);
thres = add(thres, means);
/* even positions */
/* Find maximum of Dn[i0]+Dn[i1]+Dn[i2] */
max0 = Dn[1];
max1 = Dn[3];
max2 = Dn[5];
for (i = 9; i < SubFrLen; i+=STEP) {
if (Dn[i] > max0) max0 = Dn[i];
if (Dn[i+2] > max1) max1 = Dn[i+2];
if (Dn[i+4] > max2) max2 = Dn[i+4];
}
max0 = add(max0, max1);
max0 = add(max0, max2);
/* Find means of Dn[i0]+Dn[i1]+Dn[i2] */
L32 = 0;
for (i = 1; i < SubFrLen; i+=STEP) {
L32 = L_mac(L32, Dn[i], 1);
L32 = L_mac(L32, Dn[i+2], 1);
L32 = L_mac(L32, Dn[i+4], 1);
}
means =extract_l( L_shr(L32, 4));
/* max1 = means + (max0-means)*threshold */
max1 = sub(max0, means);
max1 = mult(max1, threshold);
max1 = add(max1, means);
/* Keep maximum threshold between odd and even position */
if(max1 > thres) thres = max1;
/*
* Modification of rrixiy[] to take signs into account.
*/
ptr_ri0i1 = rri0i1;
ptr_ri0i2 = rri0i2;
ptr_ri0i3 = rri0i3;
ptr1_ri0i1 = rri0i1;
ptr1_ri0i2 = rri0i2;
ptr1_ri0i3 = rri0i3;
for(i0=0; i0 ps2) {
shift = 1;
ps2 = ps2a;
}
/* Test threshold */
if ( ps2 > thres) {
/* Init. pointers that depend on 4th loop */
ptr_ri3i3 = rri3i3;
/* 4th pulse loop */
for (i3 = 6; i3 < SubFrLen2; i3 += STEP) {
ps3 = add(ps2, Dn[i3+shift]);
/* alp3 = alp2 + (*ptr_ri3i3++) +
2 x ( (*ptr_ri0i3++) +
(*ptr_ri1i3++) +
(*ptr_ri2i3++) ) */
alp3 = L_mac(alp2, *ptr_ri3i3++, 1);
alp3 = L_mac(alp3, *ptr_ri0i3++, 2);
alp3 = L_mac(alp3, *ptr_ri1i3++, 2);
alp3 = L_mac(alp3, *ptr_ri2i3++, 2);
alp = extract_l(L_shr(alp3, 5));
ps3c = mult(ps3, ps3);
if( L_mult(ps3c, alpha) > L_mult(psc, alp) ) {
psc = ps3c;
alpha = alp;
ip0 = i0;
ip1 = i1;
ip2 = i2;
ip3 = i3;
shif = shift;
}
} /* end of for i3 = */
time --;
if(time <= 0 ) goto end_search; /* Max time finish */
ptr_ri0i3 -= NB_POS;
ptr_ri1i3 -= NB_POS;
} /* end of if >thres */
else {
ptr_ri2i3 += NB_POS;
}
} /* end of for i2 = */
ptr_ri0i2 -= NB_POS;
ptr_ri1i3 += NB_POS;
} /* end of for i1 = */
ptr_ri0i2 += NB_POS;
ptr_ri0i3 += NB_POS;
} /* end of for i0 = */
end_search:
extra = time;
/* Set the sign of impulses */
i0 = p_sign[shr(ip0, 1)];
i1 = p_sign[shr(ip1, 1)];
i2 = p_sign[shr(ip2, 1)];
i3 = p_sign[shr(ip3, 1)];
/* Find the codeword corresponding to the selected positions */
for(i=0; i 0) {
ip0 = add(ip0 ,1);
ip1 = add(ip1 ,1);
ip2 = add(ip2 ,1);
ip3 = add(ip3 ,1);
}
cod[ip0] = i0;
cod[ip1] = i1;
if(ip2 0)
for(i=ip0, j=0; i 0)
for(i=ip1, j=0; i 0)
for(i=ip2, j=0; i 0)
for(i=ip3, j=0; i 0) *sign = add(*sign, 1);
if(i1 > 0) *sign = add(*sign, 2);
if(i2 > 0) *sign = add(*sign, 4);
if(i3 > 0) *sign = add(*sign, 8);
i = shr(ip0, 3);
i = add(i, shl(shr(ip1, 3), 3));
i = add(i, shl(shr(ip2, 3), 6));
i = add(i, shl(shr(ip3, 3), 9));
return i;
}
/*
**
** Function: G_code()
**
** Description: Compute the gain of innovative code.
**
**
** Links to the text: Section 2.16
**
** Input arguments:
**
** Word16 X[] Code target. (in Q0)
** Word16 Y[] Filtered innovation code. (in Q12)
**
** Output:
**
** Word16 *gain_q Gain of innovation code. (in Q0)
**
** Return value:
**
** Word16 index of innovation code gain
**
*/
Word16 G_code(Word16 X[], Word16 Y[], Word16 *gain_q)
{
Word16 i;
Word16 xy, yy, exp_xy, exp_yy, gain, gain_nq;
Word32 L_xy, L_yy;
Word16 dist, dist_min;
/* Scale down Y[] by 8 to avoid overflow */
for(i=0; i */
L_xy = 0L;
for(i=0; i */
L_yy = 0L;
for(i=0; i