www.pudn.com > g729.rar > acelp_ca.c


/* 
   ITU-T G.729A Speech Coder    ANSI-C Source Code 
   Version 1.1    Last modified: September 1996 
 
   Copyright (c) 1996, 
   AT&T, France Telecom, NTT, Universite de Sherbrooke 
   All rights reserved. 
*/ 
 
/*---------------------------------------------------------------------------* 
 *  Function  ACELP_Code_A()                                                 * 
 *  ~~~~~~~~~~~~~~~~~~~~~~~~                                                 * 
 *   Find Algebraic codebook for G.729A                                      * 
 *--------------------------------------------------------------------------*/ 
 
#include "typedef.h" 
#include "basic_op.h" 
#include "ld8a.h" 
 
/* Constants defined in ld8a.h */ 
/*  L_SUBFR   -> Lenght of subframe.                                        */ 
/*  NB_POS    -> Number of positions for each pulse.                        */ 
/*  STEP      -> Step betweem position of the same pulse.                   */ 
/*  MSIZE     -> Size of vectors for cross-correlation between two pulses.  */ 
 
 
/* local routines definition */ 
 
static void Cor_h( 
     Word16 *H,         /* (i) Q12 :Impulse response of filters */ 
     Word16 *rr         /* (o)     :Correlations of H[]         */ 
); 
static Word16 D4i40_17_fast(/*(o) : Index of pulses positions.               */ 
  Word16 dn[],          /* (i)    : Correlations between h[] and Xn[].       */ 
  Word16 *rr,           /* (i)    : Correlations of impulse response h[].    */ 
  Word16 h[],           /* (i) Q12: Impulse response of filters.             */ 
  Word16 cod[],         /* (o) Q13: Selected algebraic codeword.             */ 
  Word16 y[],           /* (o) Q12: Filtered algebraic codeword.             */ 
  Word16 *sign          /* (o)    : Signs of 4 pulses.                       */ 
); 
 
 /*-----------------------------------------------------------------* 
  * Main ACELP function.                                            * 
  *-----------------------------------------------------------------*/ 
 
Word16  ACELP_Code_A(    /* (o)     :index of pulses positions    */ 
  Word16 x[],            /* (i)     :Target vector                */ 
  Word16 h[],            /* (i) Q12 :Inpulse response of filters  */ 
  Word16 T0,             /* (i)     :Pitch lag                    */ 
  Word16 pitch_sharp,    /* (i) Q14 :Last quantized pitch gain    */ 
  Word16 code[],         /* (o) Q13 :Innovative codebook          */ 
  Word16 y[],            /* (o) Q12 :Filtered innovative codebook */ 
  Word16 *sign           /* (o)     :Signs of 4 pulses            */ 
) 
{ 
  Word16 i, index, sharp; 
  Word16 Dn[L_SUBFR]; 
  Word16 rr[DIM_RR]; 
 
 /*-----------------------------------------------------------------* 
  * Include fixed-gain pitch contribution into impulse resp. h[]    * 
  * Find correlations of h[] needed for the codebook search.        * 
  *-----------------------------------------------------------------*/ 
 
  sharp = shl(pitch_sharp, 1);          /* From Q14 to Q15 */ 
  if (T0 < L_SUBFR) 
     for (i = T0; i < L_SUBFR; i++)     /* h[i] += pitch_sharp*h[i-T0] */ 
       h[i] = myadd(h[i], mult(h[i-T0], sharp));  //modified 
 
  Cor_h(h, rr); 
 
 /*-----------------------------------------------------------------* 
  * Compute correlation of target vector with impulse response.     * 
  *-----------------------------------------------------------------*/ 
 
  Cor_h_X(h, x, Dn); 
 
 /*-----------------------------------------------------------------* 
  * Find innovative codebook.                                       * 
  *-----------------------------------------------------------------*/ 
 
  index = D4i40_17_fast(Dn, rr, h, code, y, sign); 
 
 /*-----------------------------------------------------------------* 
  * Compute innovation vector gain.                                 * 
  * Include fixed-gain pitch contribution into code[].              * 
  *-----------------------------------------------------------------*/ 
 
  if(T0 < L_SUBFR) 
     for (i = T0; i < L_SUBFR; i++) {   /* code[i] += pitch_sharp*code[i-T0] */ 
       code[i] = myadd(code[i], mult(code[i-T0], sharp)); 
     } 
  return index; 
} 
 
 
 
/*--------------------------------------------------------------------------* 
 *  Function  Cor_h()                                                       * 
 *  ~~~~~~~~~~~~~~~~~                                                       * 
 * Compute  correlations of h[]  needed for the codebook search.            * 
 *--------------------------------------------------------------------------*/ 
 
static void Cor_h( 
  Word16 *H,     /* (i) Q12 :Impulse response of filters */ 
  Word16 *rr     /* (o)     :Correlations of H[]         */ 
) 
{ 
  Word16 *rri0i0, *rri1i1, *rri2i2, *rri3i3, *rri4i4; 
  Word16 *rri0i1, *rri0i2, *rri0i3, *rri0i4; 
  Word16 *rri1i2, *rri1i3, *rri1i4; 
  Word16 *rri2i3, *rri2i4; 
 
  Word16 *p0, *p1, *p2, *p3, *p4; 
 
  Word16 *ptr_hd, *ptr_hf, *ptr_h1, *ptr_h2; 
  Word32 cor; 
  Word16 i, k, ldec, l_fin_sup, l_fin_inf; 
  Word16 h[L_SUBFR]; 
 
 /* Scaling h[] for maximum precision */ 
 
  cor = 0; 
  for(i=0; i 0) 
  { 
    for(i=0; i 17 bits; 4 pulses in a frame of 40 samples                         * 
 *                                                                        * 
 *------------------------------------------------------------------------* 
 * The code length is 40, containing 4 nonzero pulses i0, i1, i2, i3.     * 
 * Each pulses can have 8 possible positions (positive or negative)       * 
 * except i3 that have 16 possible positions.                             * 
 *                                                                        * 
 * i0 (+-1) : 0, 5, 10, 15, 20, 25, 30, 35                                * 
 * i1 (+-1) : 1, 6, 11, 16, 21, 26, 31, 36                                * 
 * i2 (+-1) : 2, 7, 12, 17, 22, 27, 32, 37                                * 
 * i3 (+-1) : 3, 8, 13, 18, 23, 28, 33, 38                                * 
 *            4, 9, 14, 19, 24, 29, 34, 39                                * 
 *------------------------------------------------------------------------*/ 
 
static Word16 D4i40_17_fast(/*(o) : Index of pulses positions.               */ 
  Word16 dn[],          /* (i)    : Correlations between h[] and Xn[].       */ 
  Word16 rr[],          /* (i)    : Correlations of impulse response h[].    */ 
  Word16 h[],           /* (i) Q12: Impulse response of filters.             */ 
  Word16 cod[],         /* (o) Q13: Selected algebraic codeword.             */ 
  Word16 y[],           /* (o) Q12: Filtered algebraic codeword.             */ 
  Word16 *sign          /* (o)    : Signs of 4 pulses.                       */ 
) 
{ 
  Word16 i0, i1, i2, i3, ip0, ip1, ip2, ip3; 
  Word16 i, j, ix, iy, track, trk, max; 
  Word16 prev_i0, i1_offset; 
  Word16 psk, ps, ps0, ps1, ps2, sq, sq2; 
  Word16 alpk, alp, alp_16; 
  Word32 s, alp0, alp1, alp2; 
  Word16 *p0, *p1, *p2, *p3, *p4; 
  Word16 sign_dn[L_SUBFR], sign_dn_inv[L_SUBFR], *psign; 
  Word16 tmp_vect[NB_POS]; 
  Word16 *rri0i0, *rri1i1, *rri2i2, *rri3i3, *rri4i4; 
  Word16 *rri0i1, *rri0i2, *rri0i3, *rri0i4; 
  Word16 *rri1i2, *rri1i3, *rri1i4; 
  Word16 *rri2i3, *rri2i4; 
 
  Word16  *ptr_rri0i3_i4; 
  Word16  *ptr_rri1i3_i4; 
  Word16  *ptr_rri2i3_i4; 
  Word16  *ptr_rri3i3_i4; 
 
     /* Init pointers */ 
   rri0i0 = rr; 
   rri1i1 = rri0i0 + NB_POS; 
   rri2i2 = rri1i1 + NB_POS; 
   rri3i3 = rri2i2 + NB_POS; 
   rri4i4 = rri3i3 + NB_POS; 
   rri0i1 = rri4i4 + NB_POS; 
   rri0i2 = rri0i1 + MSIZE; 
   rri0i3 = rri0i2 + MSIZE; 
   rri0i4 = rri0i3 + MSIZE; 
   rri1i2 = rri0i4 + MSIZE; 
   rri1i3 = rri1i2 + MSIZE; 
   rri1i4 = rri1i3 + MSIZE; 
   rri2i3 = rri1i4 + MSIZE; 
   rri2i4 = rri2i3 + MSIZE; 
 
 /*-----------------------------------------------------------------------* 
  * Chose the sign of the impulse.                                        * 
  *-----------------------------------------------------------------------*/ 
 
   for (i=0; i= 0) 
     { 
       sign_dn[i] = MAX_16; 
       sign_dn_inv[i] = MIN_16; 
     } 
     else 
     { 
       sign_dn[i] = MIN_16; 
       sign_dn_inv[i] = MAX_16; 
       dn[i] = negate(dn[i]); 
     } 
   } 
 
 /*-------------------------------------------------------------------* 
  * Modification of rrixiy[] to take signs into account.              * 
  *-------------------------------------------------------------------*/ 
 
  p0 = rri0i1; 
  p1 = rri0i2; 
  p2 = rri0i3; 
  p3 = rri0i4; 
 
  for(i0=0; i0 0) && (mysub(prev_i0,j) != 0)) 
        { 
          max = dn[j]; 
          i0 = j; 
        } 
      } 
      prev_i0 = i0; 
 
      j = mult(i0, 6554);        /* j = i0/5 */ 
      p0 = rri2i2 + j; 
 
      ps1 = dn[i0]; 
      alp1 = L_mult(*p0, _1_4); 
 
      /* i1 loop: 8 positions in track 2 */ 
 
      p0 = ptr_rri2i3_i4 + shl(j, 3); 
      p1 = ptr_rri3i3_i4; 
 
      for (i1=track; i1 0) 
        { 
          sq = sq2; 
          ps = ps2; 
          alp = alp_16; 
          ix = i0; 
          iy = i1; 
        } 
      } 
    } 
 
    i0 = ix; 
    i1 = iy; 
    i1_offset = shl(mult(i1, 6554), 3);       /* j = 8*(i1/5) */ 
 
   /*------------------------------------------------------------------* 
    * depth first search 3, phase B: track 0 and 1.                    * 
    *------------------------------------------------------------------*/ 
 
    ps0 = ps; 
    alp0 = L_mult(alp, _1_4); 
 
    sq = -1; 
    alp = 1; 
 
    /* build vector for next loop to decrease complexity */ 
 
    p0 = rri1i2 + mult(i0, 6554); 
    p1 = ptr_rri1i3_i4 + mult(i1, 6554); 
    p2 = rri1i1; 
    p3 = tmp_vect; 
 
    for (i3=1; i3 0) 
        { 
          sq = sq2; 
          alp = alp_16; 
          ix = i2; 
          iy = i3; 
        } 
      } 
    } 
 
   /*----------------------------------------------------------------* 
    * depth first search 3: compare codevector with the best case.   * 
    *----------------------------------------------------------------*/ 
 
    s = L_msu(L_mult(alpk,sq),psk,alp); 
    if (s > 0) 
    { 
      psk = sq; 
      alpk = alp; 
      ip2 = i0; 
      ip3 = i1; 
      ip0 = ix; 
      ip1 = iy; 
    } 
 
   /*------------------------------------------------------------------* 
    * depth first search 4, phase A: track 3 and 0.                    * 
    *------------------------------------------------------------------*/ 
 
    sq = -1; 
    alp = 1; 
 
    /* i0 loop: 2 positions in track 3/4 */ 
 
    prev_i0  = -1; 
 
    for (i=0; i<2; i++) 
    { 
      max = -1; 
      /* search "dn[]" maximum position in track 3/4 */ 
      for (j=track; j 0) && (mysub(prev_i0,j) != 0)) 
        { 
          max = dn[j]; 
          i0 = j; 
        } 
      } 
      prev_i0 = i0; 
 
      j = mult(i0, 6554);        /* j = i0/5 */ 
      p0 = ptr_rri3i3_i4 + j; 
 
      ps1 = dn[i0]; 
      alp1 = L_mult(*p0, _1_4); 
 
      /* i1 loop: 8 positions in track 0 */ 
 
      p0 = ptr_rri0i3_i4 + j; 
      p1 = rri0i0; 
 
      for (i1=0; i1 0) 
        { 
          sq = sq2; 
          ps = ps2; 
          alp = alp_16; 
          ix = i0; 
          iy = i1; 
        } 
      } 
    } 
 
    i0 = ix; 
    i1 = iy; 
    i1_offset = shl(mult(i1, 6554), 3);       /* j = 8*(i1/5) */ 
 
   /*------------------------------------------------------------------* 
    * depth first search 4, phase B: track 1 and 2.                    * 
    *------------------------------------------------------------------*/ 
 
    ps0 = ps; 
    alp0 = L_mult(alp, _1_4); 
 
    sq = -1; 
    alp = 1; 
 
    /* build vector for next loop to decrease complexity */ 
 
    p0 = ptr_rri2i3_i4 + mult(i0, 6554); 
    p1 = rri0i2 + i1_offset; 
    p2 = rri2i2; 
    p3 = tmp_vect; 
 
    for (i3=2; i3 0) 
        { 
          sq = sq2; 
          alp = alp_16; 
          ix = i2; 
          iy = i3; 
        } 
      } 
    } 
 
   /*----------------------------------------------------------------* 
    * depth first search 1: compare codevector with the best case.   * 
    *----------------------------------------------------------------*/ 
 
    s = L_msu(L_mult(alpk,sq),psk,alp); 
    if (s > 0) 
    { 
      psk = sq; 
      alpk = alp; 
      ip3 = i0; 
      ip0 = i1; 
      ip1 = ix; 
      ip2 = iy; 
    } 
 
  ptr_rri0i3_i4 = rri0i4; 
  ptr_rri1i3_i4 = rri1i4; 
  ptr_rri2i3_i4 = rri2i4; 
  ptr_rri3i3_i4 = rri4i4; 
 
  } 
 
 
 /* Set the sign of impulses */ 
 
 i0 = sign_dn[ip0]; 
 i1 = sign_dn[ip1]; 
 i2 = sign_dn[ip2]; 
 i3 = sign_dn[ip3]; 
 
 /* Find the codeword corresponding to the selected positions */ 
 
 
 for(i=0; i 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) i = myadd(i, 1); 
 if(i1 > 0) i = myadd(i, 2); 
 if(i2 > 0) i = myadd(i, 4); 
 if(i3 > 0) i = myadd(i, 8);*/ 
 
 if(i0 > 0) i = i+1; 
 if(i1 > 0) i = i+2; 
 if(i2 > 0) i = i+4; 
 if(i3 > 0) i = i+8; 
 *sign = i; 
 
 ip0 = mult(ip0, 6554);         /* ip0/5 */ 
 ip1 = mult(ip1, 6554);         /* ip1/5 */ 
 ip2 = mult(ip2, 6554);         /* ip2/5 */ 
 i   = mult(ip3, 6554);         /* ip3/5 */ 
 j   = myadd(i, shl(i, 2));       /* j = i*5 */ 
 j   = mysub(ip3, myadd(j, 3));     /* j= ip3%5 -3 */ 
 ip3 = myadd(shl(i, 1), j); 
 
 i = myadd(ip0, shl(ip1, 3)); 
 i = myadd(i  , shl(ip2, 6)); 
 i = myadd(i  , shl(ip3, 9)); 
 
 return i; 
}