Пример #1
0
/* MA filter */
void WebRtcIsacfix_NormLatticeFilterMa(int16_t orderCoef,
                                       int32_t *stateGQ15,
                                       int16_t *lat_inQ0,
                                       int16_t *filt_coefQ15,
                                       int32_t *gain_lo_hiQ17,
                                       int16_t lo_hi,
                                       int16_t *lat_outQ9)
{
  int16_t sthQ15[MAX_AR_MODEL_ORDER];
  int16_t cthQ15[MAX_AR_MODEL_ORDER];

  int u, i, k, n;
  int16_t temp2,temp3;
  int16_t ord_1 = orderCoef+1;
  int32_t inv_cthQ16[MAX_AR_MODEL_ORDER];

  int32_t gain32, fQtmp;
  int16_t gain16;
  int16_t gain_sh;

  int32_t tmp32, tmp32b;
  int32_t fQ15vec[HALF_SUBFRAMELEN];
  int32_t gQ15[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
  int16_t sh;
  int16_t t16a;
  int16_t t16b;

  for (u=0;u<SUBFRAMES;u++)
  {
    int32_t temp1 = WEBRTC_SPL_MUL_16_16(u, HALF_SUBFRAMELEN);

    /* set the Direct Form coefficients */
    temp2 = (int16_t)WEBRTC_SPL_MUL_16_16(u, orderCoef);
    temp3 = (int16_t)WEBRTC_SPL_MUL_16_16(2, u)+lo_hi;

    /* compute lattice filter coefficients */
    memcpy(sthQ15, &filt_coefQ15[temp2], orderCoef * sizeof(int16_t));

    WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15);

    /* compute the gain */
    gain32 = gain_lo_hiQ17[temp3];
    gain_sh = WebRtcSpl_NormW32(gain32);
    gain32 = WEBRTC_SPL_LSHIFT_W32(gain32, gain_sh); //Q(17+gain_sh)

    for (k=0;k<orderCoef;k++)
    {
      gain32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], gain32); //Q15*Q(17+gain_sh)>>15 = Q(17+gain_sh)
      inv_cthQ16[k] = WebRtcSpl_DivW32W16((int32_t)2147483647, cthQ15[k]); // 1/cth[k] in Q31/Q15 = Q16
    }
    gain16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(gain32, 16); //Q(1+gain_sh)

    /* normalized lattice filter */
    /*****************************/

    /* initial conditions */
    for (i=0;i<HALF_SUBFRAMELEN;i++)
    {
      fQ15vec[i] = WEBRTC_SPL_LSHIFT_W32((int32_t)lat_inQ0[i + temp1], 15); //Q15
      gQ15[0][i] = WEBRTC_SPL_LSHIFT_W32((int32_t)lat_inQ0[i + temp1], 15); //Q15
    }


    fQtmp = fQ15vec[0];

    /* get the state of f&g for the first input, for all orders */
    for (i=1;i<ord_1;i++)
    {
      // Calculate f[i][0] = inv_cth[i-1]*(f[i-1][0] + sth[i-1]*stateG[i-1]);
      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], stateGQ15[i-1]);//Q15*Q15>>15 = Q15
      tmp32b= fQtmp + tmp32; //Q15+Q15=Q15
      tmp32 = inv_cthQ16[i-1]; //Q16
      t16a = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32, 16);
      t16b = (int16_t) (tmp32-WEBRTC_SPL_LSHIFT_W32(((int32_t)t16a), 16));
      if (t16b<0) t16a++;
      tmp32 = LATTICE_MUL_32_32_RSFT16(t16a, t16b, tmp32b);
      fQtmp = tmp32; // Q15

      // Calculate g[i][0] = cth[i-1]*stateG[i-1] + sth[i-1]* f[i][0];
      tmp32  = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[i-1], stateGQ15[i-1]); //Q15*Q15>>15 = Q15
      tmp32b = WEBRTC_SPL_MUL_16_32_RSFT15(sthQ15[i-1], fQtmp); //Q15*Q15>>15 = Q15
      tmp32  = tmp32 + tmp32b;//Q15+Q15 = Q15
      gQ15[i][0] = tmp32; // Q15
    }

    /* filtering */
    /* save the states */
    for(k=0;k<orderCoef;k++)
    {
      // for 0 <= n < HALF_SUBFRAMELEN - 1:
      //   f[k+1][n+1] = inv_cth[k]*(f[k][n+1] + sth[k]*g[k][n]);
      //   g[k+1][n+1] = cth[k]*g[k][n] + sth[k]* f[k+1][n+1];
      WebRtcIsacfix_FilterMaLoopFix(sthQ15[k], cthQ15[k], inv_cthQ16[k],
                                    &gQ15[k][0], &gQ15[k+1][1], &fQ15vec[1]);
    }

    fQ15vec[0] = fQtmp;

    for(n=0;n<HALF_SUBFRAMELEN;n++)
    {
      //gain32 = WEBRTC_SPL_RSHIFT_W32(gain32, gain_sh); // Q(17+gain_sh) -> Q17
      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(gain16, fQ15vec[n]); //Q(1+gain_sh)*Q15>>16 = Q(gain_sh)
      sh = 9-gain_sh; //number of needed shifts to reach Q9
      t16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh);
      lat_outQ9[n + temp1] = t16a;
    }

    /* save the states */
    for (i=0;i<ord_1;i++)
    {
      stateGQ15[i] = gQ15[i][HALF_SUBFRAMELEN-1];
    }
    //process next frame
  }

  return;
}
Пример #2
0
int16_t WebRtcSpl_LevinsonW32_JSK(
    int32_t *R,  /* (i) Autocorrelation of length >= order+1 */
    int16_t *A,  /* (o) A[0..order] LPC coefficients (Q11) */
    int16_t *K,  /* (o) K[0...order-1] Reflection coefficients (Q15) */
    int16_t order /* (i) filter order */
                                        ) {
  int16_t i, j;
  int16_t R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1];
  /* Aurocorr coefficients in high precision */
  int16_t A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1];
  /* LPC coefficients in high precicion */
  int16_t A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1];
  /* LPC coefficients for next iteration */
  int16_t K_hi, K_low;      /* reflection coefficient in high precision */
  int16_t Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision
                                                   and with scale factor */
  int16_t tmp_hi, tmp_low;
  int32_t temp1W32, temp2W32, temp3W32;
  int16_t norm;

  /* Normalize the autocorrelation R[0]...R[order+1] */

  norm = WebRtcSpl_NormW32(R[0]);

  for (i=order;i>=0;i--) {
    temp1W32 = WEBRTC_SPL_LSHIFT_W32(R[i], norm);
    /* Put R in hi and low format */
    R_hi[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    R_low[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[i], 16)), 1);
  }

  /* K = A[1] = -R[1] / R[0] */

  temp2W32  = WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[1],16) +
      WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[1],1);     /* R[1] in Q31      */
  temp3W32  = WEBRTC_SPL_ABS_W32(temp2W32);      /* abs R[1]         */
  temp1W32  = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); /* abs(R[1])/R[0] in Q31 */
  /* Put back the sign on R[1] */
  if (temp2W32 > 0) {
    temp1W32 = -temp1W32;
  }

  /* Put K in hi and low format */
  K_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
  K_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)K_hi, 16)), 1);

  /* Store first reflection coefficient */
  K[0] = K_hi;

  temp1W32 = WEBRTC_SPL_RSHIFT_W32(temp1W32, 4);    /* A[1] in Q27      */

  /* Put A[1] in hi and low format */
  A_hi[1] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
  A_low[1] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[1], 16)), 1);

  /*  Alpha = R[0] * (1-K^2) */

  temp1W32  = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, K_low), 14) +
                                      WEBRTC_SPL_MUL_16_16(K_hi, K_hi)), 1); /* temp1W32 = k^2 in Q31 */

  temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32);    /* Guard against <0 */
  temp1W32 = (int32_t)0x7fffffffL - temp1W32;    /* temp1W32 = (1 - K[0]*K[0]) in Q31 */

  /* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */
  tmp_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
  tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1);

  /* Calculate Alpha in Q31 */
  temp1W32 = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_hi) +
                                     WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_low), 15) +
                                     WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_low[0], tmp_hi), 15) ), 1);

  /* Normalize Alpha and put it in hi and low format */

  Alpha_exp = WebRtcSpl_NormW32(temp1W32);
  temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, Alpha_exp);
  Alpha_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
  Alpha_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)Alpha_hi, 16)), 1);

  /* Perform the iterative calculations in the
     Levinson Durbin algorithm */

  for (i=2; i<=order; i++)
  {

    /*                    ----
                          \
                          temp1W32 =  R[i] + > R[j]*A[i-j]
                          /
                          ----
                          j=1..i-1
    */

    temp1W32 = 0;

    for(j=1; j<i; j++) {
      /* temp1W32 is in Q31 */
      temp1W32 += (WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[j], A_hi[i-j]), 1) +
                   WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[j], A_low[i-j]), 15) +
                                            WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_low[j], A_hi[i-j]), 15) ), 1));
    }

    temp1W32  = WEBRTC_SPL_LSHIFT_W32(temp1W32, 4);
    temp1W32 += (WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[i], 16) +
                 WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[i], 1));

    /* K = -temp1W32 / Alpha */
    temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32);      /* abs(temp1W32) */
    temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); /* abs(temp1W32)/Alpha */

    /* Put the sign of temp1W32 back again */
    if (temp1W32 > 0) {
      temp3W32 = -temp3W32;
    }

    /* Use the Alpha shifts from earlier to denormalize */
    norm = WebRtcSpl_NormW32(temp3W32);
    if ((Alpha_exp <= norm)||(temp3W32==0)) {
      temp3W32 = WEBRTC_SPL_LSHIFT_W32(temp3W32, Alpha_exp);
    } else {
      if (temp3W32 > 0)
      {
        temp3W32 = (int32_t)0x7fffffffL;
      } else
      {
        temp3W32 = (int32_t)0x80000000L;
      }
    }

    /* Put K on hi and low format */
    K_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
    K_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)K_hi, 16)), 1);

    /* Store Reflection coefficient in Q15 */
    K[i-1] = K_hi;

    /* Test for unstable filter. If unstable return 0 and let the
       user decide what to do in that case
    */

    if ((int32_t)WEBRTC_SPL_ABS_W16(K_hi) > (int32_t)32740) {
      return(-i); /* Unstable filter */
    }

    /*
      Compute updated LPC coefficient: Anew[i]
      Anew[j]= A[j] + K*A[i-j]   for j=1..i-1
      Anew[i]= K
    */

    for(j=1; j<i; j++)
    {
      temp1W32  = WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[j],16) +
          WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[j],1);    /* temp1W32 = A[j] in Q27 */

      temp1W32 += WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_MUL_16_16(K_hi, A_hi[i-j]) +
                                           WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, A_low[i-j]), 15) +
                                           WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_low, A_hi[i-j]), 15) ), 1); /* temp1W32 += K*A[i-j] in Q27 */

      /* Put Anew in hi and low format */
      A_upd_hi[j] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
      A_upd_low[j] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)A_upd_hi[j], 16)), 1);
    }

    temp3W32 = WEBRTC_SPL_RSHIFT_W32(temp3W32, 4);     /* temp3W32 = K in Q27 (Convert from Q31 to Q27) */

    /* Store Anew in hi and low format */
    A_upd_hi[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
    A_upd_low[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)A_upd_hi[i], 16)), 1);

    /*  Alpha = Alpha * (1-K^2) */

    temp1W32  = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, K_low), 14) +
                                        WEBRTC_SPL_MUL_16_16(K_hi, K_hi)), 1);  /* K*K in Q31 */

    temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32);      /* Guard against <0 */
    temp1W32 = (int32_t)0x7fffffffL - temp1W32;      /* 1 - K*K  in Q31 */

    /* Convert 1- K^2 in hi and low format */
    tmp_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1);

    /* Calculate Alpha = Alpha * (1-K^2) in Q31 */
    temp1W32 = WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_hi) +
                                        WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_low), 15) +
                                        WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(Alpha_low, tmp_hi), 15)), 1);

    /* Normalize Alpha and store it on hi and low format */

    norm = WebRtcSpl_NormW32(temp1W32);
    temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, norm);

    Alpha_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    Alpha_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)Alpha_hi, 16)), 1);

    /* Update the total nomalization of Alpha */
    Alpha_exp = Alpha_exp + norm;

    /* Update A[] */

    for(j=1; j<=i; j++)
    {
      A_hi[j] =A_upd_hi[j];
      A_low[j] =A_upd_low[j];
    }
  }

  /*
    Set A[0] to 1.0 and store the A[i] i=1...order in Q12
    (Convert from Q27 and use rounding)
  */

  A[0] = 2048;

  for(i=1; i<=order; i++) {
    /* temp1W32 in Q27 */
    temp1W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[i], 16) +
        WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[i], 1);
    /* Round and store upper word */
    A[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32+(int32_t)32768, 16);
  }
  return(1); /* Stable filters */
}
Пример #3
0
void WebRtcG729fix_Decod_ld8a(
  Decod_ld8a_state *st,
  int16_t  parm[],      /* (i)   : vector of synthesis parameters
                                  parm[0] = bad frame indicator (bfi)   */
  int16_t  synth[],     /* (o)   : synthesis speech                     */
  int16_t  A_t[],       /* (o)   : decoded LP filter in 2 subframes     */
  int16_t  *T2,         /* (o)   : decoded pitch lag in 2 subframes     */
  int16_t  *Vad,        /* (o)   : frame type                           */
  int16_t  bad_lsf      /* (i)   : bad LSF indicator                    */
)
{
  int16_t  *Az;                  /* Pointer on A_t   */
  int16_t  lsp_new[M];           /* LSPs             */
  int16_t  code[L_SUBFR];        /* ACELP codevector */

  /* Scalars */

  int16_t  i, j, i_subfr;
  int16_t  T0, T0_frac, index;
  int16_t  bfi;
  int32_t  L_temp;

  int16_t bad_pitch;             /* bad pitch indicator */

  /* for G.729B */
  int16_t ftyp;
  int16_t lsfq_mem[MA_NP][M];

  int Overflow;

  /* Test bad frame indicator (bfi) */

  bfi = *parm++;
  /* for G.729B */
  ftyp = *parm;

  if(bfi == 1) {
    if(st->past_ftyp == 1) {
      ftyp = 1;
      parm[4] = 1;    /* G.729 maintenance */
    }
    else ftyp = 0;
    *parm = ftyp;  /* modification introduced in version V1.3 */
  }
  
  *Vad = ftyp;

  /* Processing non active frames (SID & not transmitted) */
  if(ftyp != 1) {
    
    WebRtcG729fix_Get_decfreq_prev(st, lsfq_mem);
    WebRtcG729fix_Dec_cng(st, st->past_ftyp, st->sid_sav, st->sh_sid_sav,
            parm, st->exc, st->lsp_old, A_t, &st->seed, lsfq_mem);
    WebRtcG729fix_Update_decfreq_prev(st, lsfq_mem);

    Az = A_t;
    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) {
      Overflow = WebRtcG729fix_Syn_filt(Az, &st->exc[i_subfr], &synth[i_subfr], L_SUBFR, st->mem_syn, 0);
      if(Overflow != 0) {
        /* In case of overflow in the synthesis          */
        /* -> Scale down vector exc[] and redo synthesis */
        
        for (i = 0; i < PIT_MAX + L_INTERPOL + L_FRAME; i++)
          st->old_exc[i] = shr(st->old_exc[i], 2);
        
        WebRtcG729fix_Syn_filt(Az, &st->exc[i_subfr], &synth[i_subfr], L_SUBFR, st->mem_syn, 1);
      }
      else
        WEBRTC_SPL_MEMCPY_W16(st->mem_syn, &synth[i_subfr+L_SUBFR-M], M);
      
      Az += MP1;

      *T2++ = st->old_T0;
    }
    st->sharp = SHARPMIN;
    
  }
  /* Processing active frame */
  else {
    
    st->seed = INIT_SEED;
    parm++;

    /* Decode the LSPs */
    
    WebRtcG729fix_D_lsp(st, parm, lsp_new, WebRtcSpl_AddSatW16(bfi, bad_lsf));
    parm += 2;
    
    /*
       Note: "bad_lsf" is introduce in case the standard is used with
       channel protection.
       */
    
    /* Interpolation of LPC for the 2 subframes */
    
    WebRtcG729fix_Int_qlpc(st->lsp_old, lsp_new, A_t);
    
    /* update the LSFs for the next frame */
    
    WEBRTC_SPL_MEMCPY_W16(st->lsp_old, lsp_new, M);
    
    /*------------------------------------------------------------------------*
     *          Loop for every subframe in the analysis frame                 *
     *------------------------------------------------------------------------*
     * The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR  *
     *  times                                                                 *
     *     - decode the pitch delay                                           *
     *     - decode algebraic code                                            *
     *     - decode pitch and codebook gains                                  *
     *     - find the excitation and compute synthesis speech                 *
     *------------------------------------------------------------------------*/
    
    Az = A_t;            /* pointer to interpolated LPC parameters */
    
    for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
      {

        index = *parm++;        /* pitch index */

        if(i_subfr == 0)
          {
            i = *parm++;        /* get parity check result */
            bad_pitch = WebRtcSpl_AddSatW16(bfi, i);
            if( bad_pitch == 0)
              {
                WebRtcG729fix_Dec_lag3(index, PIT_MIN, PIT_MAX, i_subfr, &T0, &T0_frac);
                st->old_T0 = T0;
              }
            else                /* Bad frame, or parity error */
              {
                T0  = st->old_T0;
                T0_frac = 0;
                st->old_T0 = WebRtcSpl_AddSatW16(st->old_T0, 1);
                if(st->old_T0 > PIT_MAX) {
                  st->old_T0 = PIT_MAX;
                }
              }
          }
        else                    /* second subframe */
          {
            if(bfi == 0)
              {
                WebRtcG729fix_Dec_lag3(index, PIT_MIN, PIT_MAX, i_subfr, &T0, &T0_frac);
                st->old_T0 = T0;
              }
            else
              {
                T0 = st->old_T0;
                T0_frac = 0;
                st->old_T0 = WebRtcSpl_AddSatW16(st->old_T0, 1);
                if (st->old_T0 > PIT_MAX) {
                  st->old_T0 = PIT_MAX;
                }
              }
          }
        *T2++ = T0;

        /*-------------------------------------------------*
         * - Find the adaptive codebook vector.            *
         *-------------------------------------------------*/

        WebRtcG729fix_Pred_lt_3(&st->exc[i_subfr], T0, T0_frac, L_SUBFR);

        /*-------------------------------------------------------*
         * - Decode innovative codebook.                         *
         * - Add the fixed-gain pitch contribution to code[].    *
         *-------------------------------------------------------*/

        if(bfi != 0)            /* Bad frame */
          {

            parm[0] = WebRtcG729fix_Random(&st->seed_fer) & (int16_t)0x1fff; /* 13 bits random */
            parm[1] = WebRtcG729fix_Random(&st->seed_fer) & (int16_t)0x000f; /*  4 bits random */
          }

        WebRtcG729fix_Decod_ACELP(parm[1], parm[0], code);
        parm +=2;

        j = shl(st->sharp, 1);      /* From Q14 to Q15 */
        if(T0 < L_SUBFR) {
          for (i = T0; i < L_SUBFR; i++) {
            code[i] = WebRtcSpl_AddSatW16(code[i], mult(code[i-T0], j));
          }
        }

        /*-------------------------------------------------*
         * - Decode pitch and codebook gains.              *
         *-------------------------------------------------*/

        index = *parm++;        /* index of energy VQ */

        WebRtcG729fix_Dec_gain(st, index, code, L_SUBFR, bfi, &st->gain_pitch, &st->gain_code);

        /*-------------------------------------------------------------*
         * - Update pitch sharpening "sharp" with quantized gain_pitch *
         *-------------------------------------------------------------*/

        st->sharp = st->gain_pitch;
        if (st->sharp > SHARPMAX)      { st->sharp = SHARPMAX; }
        else if (st->sharp < SHARPMIN) { st->sharp = SHARPMIN; }

        /*-------------------------------------------------------*
         * - Find the total excitation.                          *
         * - Find synthesis speech corresponding to exc[].       *
         *-------------------------------------------------------*/

        for (i = 0; i < L_SUBFR;  i++)
          {
            /* exc[i] = gain_pitch*exc[i] + gain_code*code[i]; */
            /* exc[i]  in Q0   gain_pitch in Q14               */
            /* code[i] in Q13  gain_codeode in Q1              */
            
            L_temp = L_mult(st->exc[i+i_subfr], st->gain_pitch);
            L_temp = L_mac(L_temp, code[i], st->gain_code);
            L_temp = L_shl(L_temp, 1);
            st->exc[i+i_subfr] = L_round(L_temp);
          }
        
        Overflow = WebRtcG729fix_Syn_filt(Az, &st->exc[i_subfr], &synth[i_subfr], L_SUBFR, st->mem_syn, 0);
        if(Overflow != 0)
          {
            /* In case of overflow in the synthesis          */
            /* -> Scale down vector exc[] and redo synthesis */

            for (i = 0; i < PIT_MAX + L_INTERPOL + L_FRAME; i++)
              st->old_exc[i] = shr(st->old_exc[i], 2);

            WebRtcG729fix_Syn_filt(Az, &st->exc[i_subfr], &synth[i_subfr], L_SUBFR, st->mem_syn, 1);
          }
        else
          WEBRTC_SPL_MEMCPY_W16(st->mem_syn, &synth[i_subfr+L_SUBFR-M], M);

        Az += MP1;              /* interpolated LPC parameters for next subframe */
      }
  }
  
  /*------------*
   *  For G729b
   *-----------*/
  if(bfi == 0) {
    L_temp = 0L;
    for (i = 0; i < L_FRAME; i++) {
      L_temp = L_mac(L_temp, st->exc[i], st->exc[i]);
    } /* may overflow => last level of SID quantizer */
    st->sh_sid_sav = WebRtcSpl_NormW32(L_temp);
    st->sid_sav = L_round(L_shl(L_temp, st->sh_sid_sav));
    st->sh_sid_sav = WebRtcSpl_SubSatW16(16, st->sh_sid_sav);
  }

 /*--------------------------------------------------*
  * Update signal for next frame.                    *
  * -> shift to the left by L_FRAME  exc[]           *
  *--------------------------------------------------*/

  Copy(&st->old_exc[L_FRAME], &st->old_exc[0], PIT_MAX+L_INTERPOL);

  /* for G729b */
  st->past_ftyp = ftyp;

  return;
}
Пример #4
0
/* filter the signal using normalized lattice filter */
void WebRtcIsacfix_NormLatticeFilterAr(int16_t orderCoef,
                                       int16_t *stateGQ0,
                                       int32_t *lat_inQ25,
                                       int16_t *filt_coefQ15,
                                       int32_t *gain_lo_hiQ17,
                                       int16_t lo_hi,
                                       int16_t *lat_outQ0)
{
  int ii,n,k,i,u;
  int16_t sthQ15[MAX_AR_MODEL_ORDER];
  int16_t cthQ15[MAX_AR_MODEL_ORDER];
  int32_t tmp32;


  int16_t tmpAR;
  int16_t ARfQ0vec[HALF_SUBFRAMELEN];
  int16_t ARgQ0vec[MAX_AR_MODEL_ORDER+1];

  int32_t inv_gain32;
  int16_t inv_gain16;
  int16_t den16;
  int16_t sh;

  int16_t temp2,temp3;
  int16_t ord_1 = orderCoef+1;

  for (u=0;u<SUBFRAMES;u++)
  {
    int32_t temp1 = WEBRTC_SPL_MUL_16_16(u, HALF_SUBFRAMELEN);

    //set the denominator and numerator of the Direct Form
    temp2 = (int16_t)WEBRTC_SPL_MUL_16_16(u, orderCoef);
    temp3 = (int16_t)WEBRTC_SPL_MUL_16_16(2, u) + lo_hi;

    for (ii=0; ii<orderCoef; ii++) {
      sthQ15[ii] = filt_coefQ15[temp2+ii];
    }

    WebRtcSpl_SqrtOfOneMinusXSquared(sthQ15, orderCoef, cthQ15);

    /* Simulation of the 25 files shows that maximum value in
       the vector gain_lo_hiQ17[] is 441344, which means that
       it is log2((2^31)/441344) = 12.2 shifting bits from
       saturation. Therefore, it should be safe to use Q27 instead
       of Q17. */

    tmp32 = WEBRTC_SPL_LSHIFT_W32(gain_lo_hiQ17[temp3], 10); // Q27

    for (k=0;k<orderCoef;k++) {
      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT15(cthQ15[k], tmp32); // Q15*Q27>>15 = Q27
    }

    sh = WebRtcSpl_NormW32(tmp32); // tmp32 is the gain
    den16 = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32, sh-16); //Q(27+sh-16) = Q(sh+11) (all 16 bits are value bits)
    inv_gain32 = WebRtcSpl_DivW32W16((int32_t)2147483647, den16); // 1/gain in Q31/Q(sh+11) = Q(20-sh)

    //initial conditions
    inv_gain16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(inv_gain32, 2); // 1/gain in Q(20-sh-2) = Q(18-sh)

    for (i=0;i<HALF_SUBFRAMELEN;i++)
    {

      tmp32 = WEBRTC_SPL_LSHIFT_W32(lat_inQ25[i + temp1], 1); //Q25->Q26
      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(inv_gain16, tmp32); //lat_in[]*inv_gain in (Q(18-sh)*Q26)>>16 = Q(28-sh)
      tmp32 = WEBRTC_SPL_SHIFT_W32(tmp32, -(28-sh)); // lat_in[]*inv_gain in Q0

      ARfQ0vec[i] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0
    }

    for (i=orderCoef-1;i>=0;i--) //get the state of f&g for the first input, for all orders
    {
      tmp32 = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16(cthQ15[i],ARfQ0vec[0])) - (WEBRTC_SPL_MUL_16_16(sthQ15[i],stateGQ0[i])) + 16384), 15);
      tmpAR = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0

      tmp32 = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16(sthQ15[i],ARfQ0vec[0])) + (WEBRTC_SPL_MUL_16_16(cthQ15[i], stateGQ0[i])) + 16384), 15);
      ARgQ0vec[i+1] = (int16_t)WebRtcSpl_SatW32ToW16(tmp32); // Q0
      ARfQ0vec[0] = tmpAR;
    }
    ARgQ0vec[0] = ARfQ0vec[0];

    // Filter ARgQ0vec[] and ARfQ0vec[] through coefficients cthQ15[] and sthQ15[].
    WebRtcIsacfix_FilterArLoop(ARgQ0vec, ARfQ0vec, cthQ15, sthQ15, orderCoef);

    for(n=0;n<HALF_SUBFRAMELEN;n++)
    {
      lat_outQ0[n + temp1] = ARfQ0vec[n];
    }


    /* cannot use memcpy in the following */

    for (i=0;i<ord_1;i++)
    {
      stateGQ0[i] = ARgQ0vec[i];
    }
  }

  return;
}
Пример #5
0
int WebRtcIlbcfix_XcorrCoef(int16_t * target,	/* (i) first array */
			    int16_t * regressor,	/* (i) second array */
			    int16_t subl,	/* (i) dimension arrays */
			    int16_t searchLen,	/* (i) the search lenght */
			    int16_t offset,	/* (i) samples offset between arrays */
			    int16_t step	/* (i) +1 or -1 */
    )
{
	int k;
	int16_t maxlag;
	int16_t pos;
	int16_t max;
	int16_t crossCorrScale, Energyscale;
	int16_t crossCorrSqMod, crossCorrSqMod_Max;
	int32_t crossCorr, Energy;
	int16_t crossCorrmod, EnergyMod, EnergyMod_Max;
	int16_t *tp, *rp;
	int16_t *rp_beg, *rp_end;
	int16_t totscale, totscale_max;
	int16_t scalediff;
	int32_t newCrit, maxCrit;
	int shifts;

	/* Initializations, to make sure that the first one is selected */
	crossCorrSqMod_Max = 0;
	EnergyMod_Max = WEBRTC_SPL_WORD16_MAX;
	totscale_max = -500;
	maxlag = 0;
	pos = 0;

	/* Find scale value and start position */
	if (step == 1) {
		max =
		    WebRtcSpl_MaxAbsValueW16(regressor,
					     (int16_t) (subl + searchLen -
							      1));
		rp_beg = regressor;
		rp_end = &regressor[subl];
	} else {		/* step==-1 */
		max =
		    WebRtcSpl_MaxAbsValueW16(&regressor[-searchLen],
					     (int16_t) (subl + searchLen -
							      1));
		rp_beg = &regressor[-1];
		rp_end = &regressor[subl - 1];
	}

	/* Introduce a scale factor on the Energy in int32_t in
	   order to make sure that the calculation does not
	   overflow */

	if (max > 5000) {
		shifts = 2;
	} else {
		shifts = 0;
	}

	/* Calculate the first energy, then do a +/- to get the other energies */
	Energy =
	    WebRtcSpl_DotProductWithScale(regressor, regressor, subl, shifts);

	for (k = 0; k < searchLen; k++) {
		tp = target;
		rp = &regressor[pos];

		crossCorr = WebRtcSpl_DotProductWithScale(tp, rp, subl, shifts);

		if ((Energy > 0) && (crossCorr > 0)) {

			/* Put cross correlation and energy on 16 bit word */
			crossCorrScale =
			    (int16_t) WebRtcSpl_NormW32(crossCorr) - 16;
			crossCorrmod =
			    (int16_t) WEBRTC_SPL_SHIFT_W32(crossCorr,
								 crossCorrScale);
			Energyscale =
			    (int16_t) WebRtcSpl_NormW32(Energy) - 16;
			EnergyMod =
			    (int16_t) WEBRTC_SPL_SHIFT_W32(Energy,
								 Energyscale);

			/* Square cross correlation and store upper int16_t */
			crossCorrSqMod =
			    (int16_t)
			    WEBRTC_SPL_MUL_16_16_RSFT(crossCorrmod,
						      crossCorrmod, 16);

			/* Calculate the total number of (dynamic) right shifts that have
			   been performed on (crossCorr*crossCorr)/energy
			 */
			totscale = Energyscale - (crossCorrScale << 1);

			/* Calculate the shift difference in order to be able to compare the two
			   (crossCorr*crossCorr)/energy in the same domain
			 */
			scalediff = totscale - totscale_max;
			scalediff = WEBRTC_SPL_MIN(scalediff, 31);
			scalediff = WEBRTC_SPL_MAX(scalediff, -31);

			/* Compute the cross multiplication between the old best criteria
			   and the new one to be able to compare them without using a
			   division */

			if (scalediff < 0) {
				newCrit =
				    ((int32_t) crossCorrSqMod *
				     EnergyMod_Max) >> (-scalediff);
				maxCrit =
				    ((int32_t) crossCorrSqMod_Max *
				     EnergyMod);
			} else {
Пример #6
0
void WebRtcIlbcfix_CbUpdateBestIndex(
    int32_t CritNew,    /* (i) New Potentially best Criteria */
    int16_t CritNewSh,   /* (i) Shift value of above Criteria */
    int16_t IndexNew,   /* (i) Index of new Criteria */
    int32_t cDotNew,    /* (i) Cross dot of new index */
    int16_t invEnergyNew,  /* (i) Inversed energy new index */
    int16_t energyShiftNew,  /* (i) Energy shifts of new index */
    int32_t *CritMax,   /* (i/o) Maximum Criteria (so far) */
    int16_t *shTotMax,   /* (i/o) Shifts of maximum criteria */
    int16_t *bestIndex,   /* (i/o) Index that corresponds to
                                                   maximum criteria */
    int16_t *bestGain)   /* (i/o) Gain in Q14 that corresponds
                                                   to maximum criteria */
{
  int16_t shOld, shNew, tmp16;
  int16_t scaleTmp;
  int32_t gainW32;

  /* Normalize the new and old Criteria to the same domain */
  if (CritNewSh>(*shTotMax)) {
    shOld=WEBRTC_SPL_MIN(31,CritNewSh-(*shTotMax));
    shNew=0;
  } else {
    shOld=0;
    shNew=WEBRTC_SPL_MIN(31,(*shTotMax)-CritNewSh);
  }

  /* Compare the two criterias. If the new one is better,
     calculate the gain and store this index as the new best one
  */

  if (WEBRTC_SPL_RSHIFT_W32(CritNew, shNew)>
      WEBRTC_SPL_RSHIFT_W32((*CritMax),shOld)) {

    tmp16 = (int16_t)WebRtcSpl_NormW32(cDotNew);
    tmp16 = 16 - tmp16;

    /* Calculate the gain in Q14
       Compensate for inverseEnergyshift in Q29 and that the energy
       value was stored in a int16_t (shifted down 16 steps)
       => 29-14+16 = 31 */

    scaleTmp = -energyShiftNew-tmp16+31;
    scaleTmp = WEBRTC_SPL_MIN(31, scaleTmp);

    gainW32 = WEBRTC_SPL_MUL_16_16_RSFT(
        ((int16_t)WEBRTC_SPL_SHIFT_W32(cDotNew, -tmp16)), invEnergyNew, scaleTmp);

    /* Check if criteria satisfies Gain criteria (max 1.3)
       if it is larger set the gain to 1.3
       (slightly different from FLP version)
    */
    if (gainW32>21299) {
      *bestGain=21299;
    } else if (gainW32<-21299) {
      *bestGain=-21299;
    } else {
      *bestGain=(int16_t)gainW32;
    }

    *CritMax=CritNew;
    *shTotMax=CritNewSh;
    *bestIndex = IndexNew;
  }

  return;
}
Пример #7
0
// Compute speech/noise probability
// speech/noise probability is returned in: probSpeechFinal
//snrLocPrior is the prior SNR for each frequency (in Q11)
//snrLocPost is the post SNR for each frequency (in Q11)
void WebRtcNsx_SpeechNoiseProb(NsxInst_t* inst,
                               uint16_t* nonSpeechProbFinal,
                               uint32_t* priorLocSnr,
                               uint32_t* postLocSnr) {

  uint32_t zeros, num, den, tmpU32no1, tmpU32no2, tmpU32no3;
  int32_t invLrtFX, indPriorFX, tmp32, tmp32no1, tmp32no2, besselTmpFX32;
  int32_t frac32, logTmp;
  int32_t logLrtTimeAvgKsumFX;
  int16_t indPriorFX16;
  int16_t tmp16, tmp16no1, tmp16no2, tmpIndFX, tableIndex, frac, intPart;
  int i, normTmp, normTmp2, nShifts;

  // compute feature based on average LR factor
  // this is the average over all frequencies of the smooth log LRT
  logLrtTimeAvgKsumFX = 0;
  for (i = 0; i < inst->magnLen; i++) {
    besselTmpFX32 = (int32_t)postLocSnr[i]; // Q11
    normTmp = WebRtcSpl_NormU32(postLocSnr[i]);
    num = WEBRTC_SPL_LSHIFT_U32(postLocSnr[i], normTmp); // Q(11+normTmp)
    if (normTmp > 10) {
      den = WEBRTC_SPL_LSHIFT_U32(priorLocSnr[i], normTmp - 11); // Q(normTmp)
    } else {
      den = WEBRTC_SPL_RSHIFT_U32(priorLocSnr[i], 11 - normTmp); // Q(normTmp)
    }
    if (den > 0) {
      besselTmpFX32 -= num / den;  // Q11
    } else {
      besselTmpFX32 -= num; // Q11
    }

    // inst->logLrtTimeAvg[i] += LRT_TAVG * (besselTmp - log(snrLocPrior)
    //                                       - inst->logLrtTimeAvg[i]);
    // Here, LRT_TAVG = 0.5
    zeros = WebRtcSpl_NormU32(priorLocSnr[i]);
    frac32 = (int32_t)(((priorLocSnr[i] << zeros) & 0x7FFFFFFF) >> 19);
    tmp32 = WEBRTC_SPL_MUL(frac32, frac32);
    tmp32 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(tmp32, -43), 19);
    tmp32 += WEBRTC_SPL_MUL_16_16_RSFT((int16_t)frac32, 5412, 12);
    frac32 = tmp32 + 37;
    // tmp32 = log2(priorLocSnr[i])
    tmp32 = (int32_t)(((31 - zeros) << 12) + frac32) - (11 << 12); // Q12
    logTmp = (tmp32 * 178) >> 8;  // log2(priorLocSnr[i])*log(2)
    tmp32no1 = WEBRTC_SPL_RSHIFT_W32(logTmp + inst->logLrtTimeAvgW32[i], 1);
                                                  // Q12
    inst->logLrtTimeAvgW32[i] += (besselTmpFX32 - tmp32no1); // Q12

    logLrtTimeAvgKsumFX += inst->logLrtTimeAvgW32[i]; // Q12
  }
  inst->featureLogLrt = WEBRTC_SPL_RSHIFT_W32(logLrtTimeAvgKsumFX * 5,
                                              inst->stages + 10);
                                                  // 5 = BIN_SIZE_LRT / 2
  // done with computation of LR factor

  //
  //compute the indicator functions
  //

  // average LRT feature
  // FLOAT code
  // indicator0 = 0.5 * (tanh(widthPrior *
  //                      (logLrtTimeAvgKsum - threshPrior0)) + 1.0);
  tmpIndFX = 16384; // Q14(1.0)
  tmp32no1 = logLrtTimeAvgKsumFX - inst->thresholdLogLrt; // Q12
  nShifts = 7 - inst->stages; // WIDTH_PR_MAP_SHIFT - inst->stages + 5;
  //use larger width in tanh map for pause regions
  if (tmp32no1 < 0) {
    tmpIndFX = 0;
    tmp32no1 = -tmp32no1;
    //widthPrior = widthPrior * 2.0;
    nShifts++;
  }
  tmp32no1 = WEBRTC_SPL_SHIFT_W32(tmp32no1, nShifts); // Q14
  // compute indicator function: sigmoid map
  tableIndex = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32no1, 14);
  if ((tableIndex < 16) && (tableIndex >= 0)) {
    tmp16no2 = kIndicatorTable[tableIndex];
    tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex];
    frac = (int16_t)(tmp32no1 & 0x00003fff); // Q14
    tmp16no2 += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16no1, frac, 14);
    if (tmpIndFX == 0) {
      tmpIndFX = 8192 - tmp16no2; // Q14
    } else {
      tmpIndFX = 8192 + tmp16no2; // Q14
    }
  }
  indPriorFX = WEBRTC_SPL_MUL_16_16(inst->weightLogLrt, tmpIndFX); // 6*Q14

  //spectral flatness feature
  if (inst->weightSpecFlat) {
    tmpU32no1 = WEBRTC_SPL_UMUL(inst->featureSpecFlat, 400); // Q10
    tmpIndFX = 16384; // Q14(1.0)
    //use larger width in tanh map for pause regions
    tmpU32no2 = inst->thresholdSpecFlat - tmpU32no1; //Q10
    nShifts = 4;
    if (inst->thresholdSpecFlat < tmpU32no1) {
      tmpIndFX = 0;
      tmpU32no2 = tmpU32no1 - inst->thresholdSpecFlat;
      //widthPrior = widthPrior * 2.0;
      nShifts++;
    }
    tmp32no1 = (int32_t)WebRtcSpl_DivU32U16(WEBRTC_SPL_LSHIFT_U32(tmpU32no2,
                                                                  nShifts), 25);
                                                     //Q14
    tmpU32no1 = WebRtcSpl_DivU32U16(WEBRTC_SPL_LSHIFT_U32(tmpU32no2, nShifts),
                                    25); //Q14
    // compute indicator function: sigmoid map
    // FLOAT code
    // indicator1 = 0.5 * (tanh(sgnMap * widthPrior *
    //                          (threshPrior1 - tmpFloat1)) + 1.0);
    tableIndex = (int16_t)WEBRTC_SPL_RSHIFT_U32(tmpU32no1, 14);
    if (tableIndex < 16) {
      tmp16no2 = kIndicatorTable[tableIndex];
      tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex];
      frac = (int16_t)(tmpU32no1 & 0x00003fff); // Q14
      tmp16no2 += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp16no1, frac, 14);
      if (tmpIndFX) {
        tmpIndFX = 8192 + tmp16no2; // Q14
      } else {
        tmpIndFX = 8192 - tmp16no2; // Q14
      }
    }
    indPriorFX += WEBRTC_SPL_MUL_16_16(inst->weightSpecFlat, tmpIndFX); // 6*Q14
  }

  //for template spectral-difference
  if (inst->weightSpecDiff) {
    tmpU32no1 = 0;
    if (inst->featureSpecDiff) {
      normTmp = WEBRTC_SPL_MIN(20 - inst->stages,
                               WebRtcSpl_NormU32(inst->featureSpecDiff));
      tmpU32no1 = WEBRTC_SPL_LSHIFT_U32(inst->featureSpecDiff, normTmp);
                                                         // Q(normTmp-2*stages)
      tmpU32no2 = WEBRTC_SPL_RSHIFT_U32(inst->timeAvgMagnEnergy,
                                        20 - inst->stages - normTmp);
      if (tmpU32no2 > 0) {
        // Q(20 - inst->stages)
        tmpU32no1 /= tmpU32no2;
      } else {
        tmpU32no1 = (uint32_t)(0x7fffffff);
      }
    }
    tmpU32no3 = (inst->thresholdSpecDiff << 17) / 25;
    tmpU32no2 = tmpU32no1 - tmpU32no3;
    nShifts = 1;
    tmpIndFX = 16384; // Q14(1.0)
    //use larger width in tanh map for pause regions
    if (tmpU32no2 & 0x80000000) {
      tmpIndFX = 0;
      tmpU32no2 = tmpU32no3 - tmpU32no1;
      //widthPrior = widthPrior * 2.0;
      nShifts--;
    }
    tmpU32no1 = WEBRTC_SPL_RSHIFT_U32(tmpU32no2, nShifts);
    // compute indicator function: sigmoid map
    /* FLOAT code
     indicator2 = 0.5 * (tanh(widthPrior * (tmpFloat1 - threshPrior2)) + 1.0);
     */
    tableIndex = (int16_t)WEBRTC_SPL_RSHIFT_U32(tmpU32no1, 14);
    if (tableIndex < 16) {
      tmp16no2 = kIndicatorTable[tableIndex];
      tmp16no1 = kIndicatorTable[tableIndex + 1] - kIndicatorTable[tableIndex];
      frac = (int16_t)(tmpU32no1 & 0x00003fff); // Q14
      tmp16no2 += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(
                    tmp16no1, frac, 14);
      if (tmpIndFX) {
        tmpIndFX = 8192 + tmp16no2;
      } else {
        tmpIndFX = 8192 - tmp16no2;
      }
    }
    indPriorFX += WEBRTC_SPL_MUL_16_16(inst->weightSpecDiff, tmpIndFX); // 6*Q14
  }

  //combine the indicator function with the feature weights
  // FLOAT code
  // indPrior = 1 - (weightIndPrior0 * indicator0 + weightIndPrior1 *
  //                 indicator1 + weightIndPrior2 * indicator2);
  indPriorFX16 = WebRtcSpl_DivW32W16ResW16(98307 - indPriorFX, 6); // Q14
  // done with computing indicator function

  //compute the prior probability
  // FLOAT code
  // inst->priorNonSpeechProb += PRIOR_UPDATE *
  //                             (indPriorNonSpeech - inst->priorNonSpeechProb);
  tmp16 = indPriorFX16 - inst->priorNonSpeechProb; // Q14
  inst->priorNonSpeechProb += (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(
                                PRIOR_UPDATE_Q14, tmp16, 14); // Q14

  //final speech probability: combine prior model with LR factor:

  memset(nonSpeechProbFinal, 0, sizeof(uint16_t) * inst->magnLen);

  if (inst->priorNonSpeechProb > 0) {
    for (i = 0; i < inst->magnLen; i++) {
      // FLOAT code
      // invLrt = exp(inst->logLrtTimeAvg[i]);
      // invLrt = inst->priorSpeechProb * invLrt;
      // nonSpeechProbFinal[i] = (1.0 - inst->priorSpeechProb) /
      //                         (1.0 - inst->priorSpeechProb + invLrt);
      // invLrt = (1.0 - inst->priorNonSpeechProb) * invLrt;
      // nonSpeechProbFinal[i] = inst->priorNonSpeechProb /
      //                         (inst->priorNonSpeechProb + invLrt);
      if (inst->logLrtTimeAvgW32[i] < 65300) {
        tmp32no1 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(
                                           inst->logLrtTimeAvgW32[i], 23637),
                                         14); // Q12
        intPart = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmp32no1, 12);
        if (intPart < -8) {
          intPart = -8;
        }
        frac = (int16_t)(tmp32no1 & 0x00000fff); // Q12

        // Quadratic approximation of 2^frac
        tmp32no2 = WEBRTC_SPL_RSHIFT_W32(frac * frac * 44, 19); // Q12
        tmp32no2 += WEBRTC_SPL_MUL_16_16_RSFT(frac, 84, 7); // Q12
        invLrtFX = WEBRTC_SPL_LSHIFT_W32(1, 8 + intPart)
                   + WEBRTC_SPL_SHIFT_W32(tmp32no2, intPart - 4); // Q8

        normTmp = WebRtcSpl_NormW32(invLrtFX);
        normTmp2 = WebRtcSpl_NormW16((16384 - inst->priorNonSpeechProb));
        if (normTmp + normTmp2 >= 7) {
          if (normTmp + normTmp2 < 15) {
            invLrtFX = WEBRTC_SPL_RSHIFT_W32(invLrtFX, 15 - normTmp2 - normTmp);
            // Q(normTmp+normTmp2-7)
            tmp32no1 = invLrtFX * (16384 - inst->priorNonSpeechProb);
            // Q(normTmp+normTmp2+7)
            invLrtFX = WEBRTC_SPL_SHIFT_W32(tmp32no1, 7 - normTmp - normTmp2);
                                                                  // Q14
          } else {
            tmp32no1 = invLrtFX * (16384 - inst->priorNonSpeechProb);
                                                                  // Q22
            invLrtFX = WEBRTC_SPL_RSHIFT_W32(tmp32no1, 8); // Q14
          }

          tmp32no1 = WEBRTC_SPL_LSHIFT_W32((int32_t)inst->priorNonSpeechProb,
                                           8); // Q22

          nonSpeechProbFinal[i] = (uint16_t)WEBRTC_SPL_DIV(tmp32no1,
              (int32_t)inst->priorNonSpeechProb + invLrtFX); // Q8
        }
      }
    }
  }
}
Пример #8
0
void WebRtcIsacfix_Time2SpecC(int16_t *inre1Q9,
                              int16_t *inre2Q9,
                              int16_t *outreQ7,
                              int16_t *outimQ7)
{

  int k;
  int32_t tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2];
  int16_t tmp1rQ14, tmp1iQ14;
  int32_t xrQ16, xiQ16, yrQ16, yiQ16;
  int32_t v1Q16, v2Q16;
  int16_t factQ19, sh;

  /* Multiply with complex exponentials and combine into one complex vector */
  factQ19 = 16921; // 0.5/sqrt(240) in Q19 is round(.5/sqrt(240)*(2^19)) = 16921
  for (k = 0; k < FRAMESAMPLES/2; k++) {
    tmp1rQ14 = WebRtcIsacfix_kCosTab1[k];
    tmp1iQ14 = WebRtcIsacfix_kSinTab1[k];
    xrQ16 = (tmp1rQ14 * inre1Q9[k] + tmp1iQ14 * inre2Q9[k]) >> 7;
    xiQ16 = (tmp1rQ14 * inre2Q9[k] - tmp1iQ14 * inre1Q9[k]) >> 7;
    // Q-domains below: (Q16*Q19>>16)>>3 = Q16
    tmpreQ16[k] = (WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xrQ16) + 4) >> 3;
    tmpimQ16[k] = (WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xiQ16) + 4) >> 3;
  }


  xrQ16  = WebRtcSpl_MaxAbsValueW32(tmpreQ16, FRAMESAMPLES/2);
  yrQ16 = WebRtcSpl_MaxAbsValueW32(tmpimQ16, FRAMESAMPLES/2);
  if (yrQ16>xrQ16) {
    xrQ16 = yrQ16;
  }

  sh = WebRtcSpl_NormW32(xrQ16);
  sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
  //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)

  //"Fastest" vectors
  if (sh>=0) {
    for (k=0; k<FRAMESAMPLES/2; k++) {
      inre1Q9[k] = (int16_t)(tmpreQ16[k] << sh);  // Q(16+sh)
      inre2Q9[k] = (int16_t)(tmpimQ16[k] << sh);  // Q(16+sh)
    }
  } else {
    int32_t round = 1 << (-sh - 1);
    for (k=0; k<FRAMESAMPLES/2; k++) {
      inre1Q9[k] = (int16_t)((tmpreQ16[k] + round) >> -sh);  // Q(16+sh)
      inre2Q9[k] = (int16_t)((tmpimQ16[k] + round) >> -sh);  // Q(16+sh)
    }
  }

  /* Get DFT */
  WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1); // real call

  //"Fastest" vectors
  if (sh>=0) {
    for (k=0; k<FRAMESAMPLES/2; k++) {
      tmpreQ16[k] = inre1Q9[k] >> sh;  // Q(16+sh) -> Q16
      tmpimQ16[k] = inre2Q9[k] >> sh;  // Q(16+sh) -> Q16
    }
  } else {
    for (k=0; k<FRAMESAMPLES/2; k++) {
Пример #9
0
void WebRtcIsacfix_Spec2Time(WebRtc_Word16 *inreQ7, WebRtc_Word16 *inimQ7, WebRtc_Word32 *outre1Q16, WebRtc_Word32 *outre2Q16)
{

  int k;
  WebRtc_Word16 tmp1rQ14, tmp1iQ14;
  WebRtc_Word32 xrQ16, xiQ16, yrQ16, yiQ16;
  WebRtc_Word32 tmpInRe, tmpInIm, tmpInRe2, tmpInIm2;
  WebRtc_Word16 factQ11;
  WebRtc_Word16 sh;

  for (k = 0; k < FRAMESAMPLES/4; k++) {
    /* Move zero in time to beginning of frames */
    tmp1rQ14 = kCosTab2[k];
    tmp1iQ14 = kSinTab2[k];

    tmpInRe = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32) inreQ7[k], 9);  // Q7 -> Q16
    tmpInIm = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32) inimQ7[k], 9);  // Q7 -> Q16
    tmpInRe2 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32) inreQ7[FRAMESAMPLES/2 - 1 - k], 9);  // Q7 -> Q16
    tmpInIm2 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32) inimQ7[FRAMESAMPLES/2 - 1 - k], 9);  // Q7 -> Q16

    xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm);
    xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe);
    yrQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInIm2) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInRe2);
    yiQ16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, tmpInRe2) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, tmpInIm2);

    /* Combine into one vector,  z = x + j * y */
    outre1Q16[k] = xrQ16 - yiQ16;
    outre1Q16[FRAMESAMPLES/2 - 1 - k] = xrQ16 + yiQ16;
    outre2Q16[k] = xiQ16 + yrQ16;
    outre2Q16[FRAMESAMPLES/2 - 1 - k] = -xiQ16 + yrQ16;
  }

  /* Get IDFT */
  tmpInRe  = WebRtcSpl_MaxAbsValueW32(outre1Q16, 240);
  tmpInIm = WebRtcSpl_MaxAbsValueW32(outre2Q16, 240);
  if (tmpInIm>tmpInRe) {
    tmpInRe = tmpInIm;
  }

  sh = WebRtcSpl_NormW32(tmpInRe);
  sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
  //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)

  //"Fastest" vectors
  if (sh>=0) {
    for (k=0; k<240; k++) {
      inreQ7[k] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(outre1Q16[k], sh); //Q(16+sh)
      inimQ7[k] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(outre2Q16[k], sh); //Q(16+sh)
    }
  } else {
    WebRtc_Word32 round = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, -sh-1);
    for (k=0; k<240; k++) {
      inreQ7[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(outre1Q16[k]+round, -sh); //Q(16+sh)
      inimQ7[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(outre2Q16[k]+round, -sh); //Q(16+sh)
    }
  }

  WebRtcIsacfix_FftRadix16Fastest(inreQ7, inimQ7, 1); // real call

  //"Fastest" vectors
  if (sh>=0) {
    for (k=0; k<240; k++) {
      outre1Q16[k] = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)inreQ7[k], sh); //Q(16+sh) -> Q16
      outre2Q16[k] = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)inimQ7[k], sh); //Q(16+sh) -> Q16
    }
  } else {
    for (k=0; k<240; k++) {
      outre1Q16[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)inreQ7[k], -sh); //Q(16+sh) -> Q16
      outre2Q16[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)inimQ7[k], -sh); //Q(16+sh) -> Q16
    }
  }

  /* Divide through by the normalizing constant: */
  /* scale all values with 1/240, i.e. with 273 in Q16 */
  /* 273/65536 ~= 0.0041656                            */
  /*     1/240 ~= 0.0041666                            */
  for (k=0; k<240; k++) {
    outre1Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre1Q16[k]);
    outre2Q16[k] = WEBRTC_SPL_MUL_16_32_RSFT16(273, outre2Q16[k]);
  }

  /* Demodulate and separate */
  factQ11 = 31727; // sqrt(240) in Q11 is round(15.49193338482967*2048) = 31727
  for (k = 0; k < FRAMESAMPLES/2; k++) {
    tmp1rQ14 = kCosTab1[k];
    tmp1iQ14 = kSinTab1[k];
    xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre1Q16[k]) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre2Q16[k]);
    xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, outre2Q16[k]) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, outre1Q16[k]);
    xrQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xrQ16);
    xiQ16 = WEBRTC_SPL_MUL_16_32_RSFT11(factQ11, xiQ16);
    outre2Q16[k] = xiQ16;
    outre1Q16[k] = xrQ16;
  }
}
Пример #10
0
void WebRtcIsacfix_Time2Spec(WebRtc_Word16 *inre1Q9,
                             WebRtc_Word16 *inre2Q9,
                             WebRtc_Word16 *outreQ7,
                             WebRtc_Word16 *outimQ7)
{

  int k;
  WebRtc_Word32 tmpreQ16[FRAMESAMPLES/2], tmpimQ16[FRAMESAMPLES/2];
  WebRtc_Word16 tmp1rQ14, tmp1iQ14;
  WebRtc_Word32 xrQ16, xiQ16, yrQ16, yiQ16;
  WebRtc_Word32 v1Q16, v2Q16;
  WebRtc_Word16 factQ19, sh;

  /* Multiply with complex exponentials and combine into one complex vector */
  factQ19 = 16921; // 0.5/sqrt(240) in Q19 is round(.5/sqrt(240)*(2^19)) = 16921
  for (k = 0; k < FRAMESAMPLES/2; k++) {
    tmp1rQ14 = kCosTab1[k];
    tmp1iQ14 = kSinTab1[k];
    xrQ16 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(tmp1rQ14, inre1Q9[k]) + WEBRTC_SPL_MUL_16_16(tmp1iQ14, inre2Q9[k]), 7);
    xiQ16 = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(tmp1rQ14, inre2Q9[k]) - WEBRTC_SPL_MUL_16_16(tmp1iQ14, inre1Q9[k]), 7);
    tmpreQ16[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xrQ16)+4, 3); // (Q16*Q19>>16)>>3 = Q16
    tmpimQ16[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(factQ19, xiQ16)+4, 3); // (Q16*Q19>>16)>>3 = Q16
  }


  xrQ16  = WebRtcSpl_MaxAbsValueW32(tmpreQ16, FRAMESAMPLES/2);
  yrQ16 = WebRtcSpl_MaxAbsValueW32(tmpimQ16, FRAMESAMPLES/2);
  if (yrQ16>xrQ16) {
    xrQ16 = yrQ16;
  }

  sh = WebRtcSpl_NormW32(xrQ16);
  sh = sh-24; //if sh becomes >=0, then we should shift sh steps to the left, and the domain will become Q(16+sh)
  //if sh becomes <0, then we should shift -sh steps to the right, and the domain will become Q(16+sh)

  //"Fastest" vectors
  if (sh>=0) {
    for (k=0; k<FRAMESAMPLES/2; k++) {
      inre1Q9[k] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(tmpreQ16[k], sh); //Q(16+sh)
      inre2Q9[k] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(tmpimQ16[k], sh); //Q(16+sh)
    }
  } else {
    WebRtc_Word32 round = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)1, -sh-1);
    for (k=0; k<FRAMESAMPLES/2; k++) {
      inre1Q9[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmpreQ16[k]+round, -sh); //Q(16+sh)
      inre2Q9[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(tmpimQ16[k]+round, -sh); //Q(16+sh)
    }
  }

  /* Get DFT */
  WebRtcIsacfix_FftRadix16Fastest(inre1Q9, inre2Q9, -1); // real call

  //"Fastest" vectors
  if (sh>=0) {
    for (k=0; k<FRAMESAMPLES/2; k++) {
      tmpreQ16[k] = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)inre1Q9[k], sh); //Q(16+sh) -> Q16
      tmpimQ16[k] = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)inre2Q9[k], sh); //Q(16+sh) -> Q16
    }
  } else {
    for (k=0; k<FRAMESAMPLES/2; k++) {
      tmpreQ16[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)inre1Q9[k], -sh); //Q(16+sh) -> Q16
      tmpimQ16[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)inre2Q9[k], -sh); //Q(16+sh) -> Q16
    }
  }


  /* Use symmetry to separate into two complex vectors and center frames in time around zero */
  for (k = 0; k < FRAMESAMPLES/4; k++) {
    xrQ16 = tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k];
    yiQ16 = -tmpreQ16[k] + tmpreQ16[FRAMESAMPLES/2 - 1 - k];
    xiQ16 = tmpimQ16[k] - tmpimQ16[FRAMESAMPLES/2 - 1 - k];
    yrQ16 = tmpimQ16[k] + tmpimQ16[FRAMESAMPLES/2 - 1 - k];
    tmp1rQ14 = kCosTab2[k];
    tmp1iQ14 = kSinTab2[k];
    v1Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xiQ16);
    v2Q16 = WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, xrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, xiQ16);
    outreQ7[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(v1Q16, 9);
    outimQ7[k] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(v2Q16, 9);
    v1Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yrQ16) - WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yiQ16);
    v2Q16 = -WEBRTC_SPL_MUL_16_32_RSFT14(tmp1rQ14, yrQ16) + WEBRTC_SPL_MUL_16_32_RSFT14(tmp1iQ14, yiQ16);
    outreQ7[FRAMESAMPLES/2 - 1 - k] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(v1Q16, 9); //CalcLrIntQ(v1Q16, 9);
    outimQ7[FRAMESAMPLES/2 - 1 - k] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(v2Q16, 9); //CalcLrIntQ(v2Q16, 9);

  }
}
Пример #11
0
void WebRtcIlbcfix_CbSearch(
    iLBC_Enc_Inst_t *iLBCenc_inst,
    /* (i) the encoder state structure */
    WebRtc_Word16 *index,  /* (o) Codebook indices */
    WebRtc_Word16 *gain_index, /* (o) Gain quantization indices */
    WebRtc_Word16 *intarget, /* (i) Target vector for encoding */
    WebRtc_Word16 *decResidual,/* (i) Decoded residual for codebook construction */
    WebRtc_Word16 lMem,  /* (i) Length of buffer */
    WebRtc_Word16 lTarget,  /* (i) Length of vector */
    WebRtc_Word16 *weightDenum,/* (i) weighting filter coefficients in Q12 */
    WebRtc_Word16 block  /* (i) the subblock number */
                            ) {
  WebRtc_Word16 i, j, stage, range;
  WebRtc_Word16 *pp, scale, tmp;
  WebRtc_Word16 bits, temp1, temp2;
  WebRtc_Word16 base_size;
  WebRtc_Word32 codedEner, targetEner;
  WebRtc_Word16 gains[CB_NSTAGES+1];
  WebRtc_Word16 *cb_vecPtr;
  WebRtc_Word16 indexOffset, sInd, eInd;
  WebRtc_Word32 CritMax=0;
  WebRtc_Word16 shTotMax=WEBRTC_SPL_WORD16_MIN;
  WebRtc_Word16 bestIndex=0;
  WebRtc_Word16 bestGain=0;
  WebRtc_Word16 indexNew, CritNewSh;
  WebRtc_Word32 CritNew;
  WebRtc_Word32 *cDotPtr;
  WebRtc_Word16 noOfZeros;
  WebRtc_Word16 *gainPtr;
  WebRtc_Word32 t32, tmpW32;
  WebRtc_Word16 *WebRtcIlbcfix_kGainSq5_ptr;
  /* Stack based */
  WebRtc_Word16 CBbuf[CB_MEML+LPC_FILTERORDER+CB_HALFFILTERLEN];
  WebRtc_Word32 cDot[128];
  WebRtc_Word32 Crit[128];
  WebRtc_Word16 targetVec[SUBL+LPC_FILTERORDER];
  WebRtc_Word16 cbvectors[CB_MEML];
  WebRtc_Word16 codedVec[SUBL];
  WebRtc_Word16 interpSamples[20*4];
  WebRtc_Word16 interpSamplesFilt[20*4];
  WebRtc_Word16 energyW16[CB_EXPAND*128];
  WebRtc_Word16 energyShifts[CB_EXPAND*128];
  WebRtc_Word16 *inverseEnergy=energyW16;   /* Reuse memory */
  WebRtc_Word16 *inverseEnergyShifts=energyShifts; /* Reuse memory */
  WebRtc_Word16 *buf = &CBbuf[LPC_FILTERORDER];
  WebRtc_Word16 *target = &targetVec[LPC_FILTERORDER];
  WebRtc_Word16 *aug_vec = (WebRtc_Word16*)cDot;   /* length [SUBL], reuse memory */

  /* Determine size of codebook sections */

  base_size=lMem-lTarget+1;
  if (lTarget==SUBL) {
    base_size=lMem-19;
  }

  /* weighting of the CB memory */
  noOfZeros=lMem-WebRtcIlbcfix_kFilterRange[block];
  WebRtcSpl_MemSetW16(&buf[-LPC_FILTERORDER], 0, noOfZeros+LPC_FILTERORDER);
  WebRtcSpl_FilterARFastQ12(
      decResidual+noOfZeros, buf+noOfZeros,
      weightDenum, LPC_FILTERORDER+1, WebRtcIlbcfix_kFilterRange[block]);

  /* weighting of the target vector */
  WEBRTC_SPL_MEMCPY_W16(&target[-LPC_FILTERORDER], buf+noOfZeros+WebRtcIlbcfix_kFilterRange[block]-LPC_FILTERORDER, LPC_FILTERORDER);
  WebRtcSpl_FilterARFastQ12(
      intarget, target,
      weightDenum, LPC_FILTERORDER+1, lTarget);

  /* Store target, towards the end codedVec is calculated as
     the initial target minus the remaining target */
  WEBRTC_SPL_MEMCPY_W16(codedVec, target, lTarget);

  /* Find the highest absolute value to calculate proper
     vector scale factor (so that it uses 12 bits) */
  temp1 = WebRtcSpl_MaxAbsValueW16(buf, (WebRtc_Word16)lMem);
  temp2 = WebRtcSpl_MaxAbsValueW16(target, (WebRtc_Word16)lTarget);

  if ((temp1>0)&&(temp2>0)) {
    temp1 = WEBRTC_SPL_MAX(temp1, temp2);
    scale = WebRtcSpl_GetSizeInBits(WEBRTC_SPL_MUL_16_16(temp1, temp1));
  } else {
    /* temp1 or temp2 is negative (maximum was -32768) */
    scale = 30;
  }

  /* Scale to so that a mul-add 40 times does not overflow */
  scale = scale - 25;
  scale = WEBRTC_SPL_MAX(0, scale);

  /* Compute energy of the original target */
  targetEner = WebRtcSpl_DotProductWithScale(target, target, lTarget, scale);

  /* Prepare search over one more codebook section. This section
     is created by filtering the original buffer with a filter. */
  WebRtcIlbcfix_FilteredCbVecs(cbvectors, buf, lMem, WebRtcIlbcfix_kFilterRange[block]);

  range = WebRtcIlbcfix_kSearchRange[block][0];

  if(lTarget == SUBL) {
    /* Create the interpolated samples and store them for use in all stages */

    /* First section, non-filtered half of the cb */
    WebRtcIlbcfix_InterpolateSamples(interpSamples, buf, lMem);

    /* Second section, filtered half of the cb */
    WebRtcIlbcfix_InterpolateSamples(interpSamplesFilt, cbvectors, lMem);

    /* Compute the CB vectors' energies for the first cb section (non-filtered) */
    WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamples, buf,
                                          scale, 20, energyW16, energyShifts);

    /* Compute the CB vectors' energies for the second cb section (filtered cb) */
    WebRtcIlbcfix_CbMemEnergyAugmentation(interpSamplesFilt, cbvectors,
                                          scale, (WebRtc_Word16)(base_size+20), energyW16, energyShifts);

    /* Compute the CB vectors' energies and store them in the vector
     * energyW16. Also the corresponding shift values are stored. The
     * energy values are used in all three stages. */
    WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
                              lTarget, energyW16+20, energyShifts+20, scale, base_size);

  } else {
    /* Compute the CB vectors' energies and store them in the vector
     * energyW16. Also the corresponding shift values are stored. The
     * energy values are used in all three stages. */
    WebRtcIlbcfix_CbMemEnergy(range, buf, cbvectors, lMem,
                              lTarget, energyW16, energyShifts, scale, base_size);

    /* Set the energy positions 58-63 and 122-127 to zero
       (otherwise they are uninitialized) */
    WebRtcSpl_MemSetW16(energyW16+range, 0, (base_size-range));
    WebRtcSpl_MemSetW16(energyW16+range+base_size, 0, (base_size-range));
  }

  /* Calculate Inverse Energy (energyW16 is already normalized
     and will contain the inverse energy in Q29 after this call */
  WebRtcIlbcfix_EnergyInverse(energyW16, base_size*CB_EXPAND);

  /* The gain value computed in the previous stage is used
   * as an upper limit to what the next stage gain value
   * is allowed to be. In stage 0, 16384 (1.0 in Q14) is used as
   * the upper limit. */
  gains[0] = 16384;

  for (stage=0; stage<CB_NSTAGES; stage++) {

    /* Set up memories */
    range = WebRtcIlbcfix_kSearchRange[block][stage];

    /* initialize search measures */
    CritMax=0;
    shTotMax=-100;
    bestIndex=0;
    bestGain=0;

    /* loop over lags 40+ in the first codebook section, full search */
    cb_vecPtr = buf+lMem-lTarget;

    /* Calculate all the cross correlations (augmented part of CB) */
    if (lTarget==SUBL) {
      WebRtcIlbcfix_AugmentedCbCorr(target, buf+lMem,
                                    interpSamples, cDot,
                                    20, 39, scale);
      cDotPtr=&cDot[20];
    } else {
      cDotPtr=cDot;
    }
    /* Calculate all the cross correlations (main part of CB) */
    WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, range, scale, -1);

    /* Adjust the search range for the augmented vectors */
    if (lTarget==SUBL) {
      range=WebRtcIlbcfix_kSearchRange[block][stage]+20;
    } else {
      range=WebRtcIlbcfix_kSearchRange[block][stage];
    }

    indexOffset=0;

    /* Search for best index in this part of the vector */
    WebRtcIlbcfix_CbSearchCore(
        cDot, range, stage, inverseEnergy,
        inverseEnergyShifts, Crit,
        &indexNew, &CritNew, &CritNewSh);

    /* Update the global best index and the corresponding gain */
    WebRtcIlbcfix_CbUpdateBestIndex(
        CritNew, CritNewSh, (WebRtc_Word16)(indexNew+indexOffset), cDot[indexNew+indexOffset],
        inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
        &CritMax, &shTotMax, &bestIndex, &bestGain);

    sInd=bestIndex-(WebRtc_Word16)(CB_RESRANGE>>1);
    eInd=sInd+CB_RESRANGE;
    if (sInd<0) {
      eInd-=sInd;
      sInd=0;
    }
    if (eInd>=range) {
      eInd=range-1;
      sInd=eInd-CB_RESRANGE;
    }

    range = WebRtcIlbcfix_kSearchRange[block][stage];

    if (lTarget==SUBL) {
      i=sInd;
      if (sInd<20) {
        WebRtcIlbcfix_AugmentedCbCorr(target, cbvectors+lMem,
                                      interpSamplesFilt, cDot,
                                      (WebRtc_Word16)(sInd+20), (WebRtc_Word16)(WEBRTC_SPL_MIN(39, (eInd+20))), scale);
        i=20;
      }

      cDotPtr=&cDot[WEBRTC_SPL_MAX(0,(20-sInd))];
      cb_vecPtr = cbvectors+lMem-20-i;

      /* Calculate the cross correlations (main part of the filtered CB) */
      WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, (WebRtc_Word16)(eInd-i+1), scale, -1);

    } else {
      cDotPtr = cDot;
      cb_vecPtr = cbvectors+lMem-lTarget-sInd;

      /* Calculate the cross correlations (main part of the filtered CB) */
      WebRtcSpl_CrossCorrelation(cDotPtr, target, cb_vecPtr, lTarget, (WebRtc_Word16)(eInd-sInd+1), scale, -1);

    }

    /* Adjust the search range for the augmented vectors */
    indexOffset=base_size+sInd;

    /* Search for best index in this part of the vector */
    WebRtcIlbcfix_CbSearchCore(
        cDot, (WebRtc_Word16)(eInd-sInd+1), stage, inverseEnergy+indexOffset,
        inverseEnergyShifts+indexOffset, Crit,
        &indexNew, &CritNew, &CritNewSh);

    /* Update the global best index and the corresponding gain */
    WebRtcIlbcfix_CbUpdateBestIndex(
        CritNew, CritNewSh, (WebRtc_Word16)(indexNew+indexOffset), cDot[indexNew],
        inverseEnergy[indexNew+indexOffset], inverseEnergyShifts[indexNew+indexOffset],
        &CritMax, &shTotMax, &bestIndex, &bestGain);

    index[stage] = bestIndex;


    bestGain = WebRtcIlbcfix_GainQuant(bestGain,
                                       (WebRtc_Word16)WEBRTC_SPL_ABS_W16(gains[stage]), stage, &gain_index[stage]);

    /* Extract the best (according to measure) codebook vector
       Also adjust the index, so that the augmented vectors are last.
       Above these vectors were first...
    */

    if(lTarget==(STATE_LEN-iLBCenc_inst->state_short_len)) {

      if(index[stage]<base_size) {
        pp=buf+lMem-lTarget-index[stage];
      } else {
        pp=cbvectors+lMem-lTarget-
            index[stage]+base_size;
      }

    } else {

      if (index[stage]<base_size) {
        if (index[stage]>=20) {
          /* Adjust index and extract vector */
          index[stage]-=20;
          pp=buf+lMem-lTarget-index[stage];
        } else {
          /* Adjust index and extract vector */
          index[stage]+=(base_size-20);

          WebRtcIlbcfix_CreateAugmentedVec((WebRtc_Word16)(index[stage]-base_size+40),
                                           buf+lMem, aug_vec);
          pp = aug_vec;

        }
      } else {

        if ((index[stage] - base_size) >= 20) {
          /* Adjust index and extract vector */
          index[stage]-=20;
          pp=cbvectors+lMem-lTarget-
              index[stage]+base_size;
        } else {
          /* Adjust index and extract vector */
          index[stage]+=(base_size-20);
          WebRtcIlbcfix_CreateAugmentedVec((WebRtc_Word16)(index[stage]-2*base_size+40),
                                           cbvectors+lMem, aug_vec);
          pp = aug_vec;
        }
      }
    }

    /* Subtract the best codebook vector, according
       to measure, from the target vector */

    WebRtcSpl_AddAffineVectorToVector(target, pp, (WebRtc_Word16)(-bestGain), (WebRtc_Word32)8192, (WebRtc_Word16)14, (int)lTarget);

    /* record quantized gain */
    gains[stage+1] = bestGain;

  } /* end of Main Loop. for (stage=0;... */

  /* Calculte the coded vector (original target - what's left) */
  for (i=0;i<lTarget;i++) {
    codedVec[i]-=target[i];
  }

  /* Gain adjustment for energy matching */
  codedEner = WebRtcSpl_DotProductWithScale(codedVec, codedVec, lTarget, scale);

  j=gain_index[0];

  temp1 = (WebRtc_Word16)WebRtcSpl_NormW32(codedEner);
  temp2 = (WebRtc_Word16)WebRtcSpl_NormW32(targetEner);

  if(temp1 < temp2) {
    bits = 16 - temp1;
  } else {
    bits = 16 - temp2;
  }

  tmp = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(gains[1],gains[1], 14);

  targetEner = WEBRTC_SPL_MUL_16_16(
      WEBRTC_SPL_SHIFT_W32(targetEner, -bits), tmp);

  tmpW32 = ((WebRtc_Word32)(gains[1]-1))<<1;

  /* Pointer to the table that contains
     gain_sq5TblFIX * gain_sq5TblFIX in Q14 */
  gainPtr=(WebRtc_Word16*)WebRtcIlbcfix_kGainSq5Sq+gain_index[0];
  temp1 = (WebRtc_Word16)WEBRTC_SPL_SHIFT_W32(codedEner, -bits);

  WebRtcIlbcfix_kGainSq5_ptr = (WebRtc_Word16*)&WebRtcIlbcfix_kGainSq5[j];

  /* targetEner and codedEner are in Q(-2*scale) */
  for (i=gain_index[0];i<32;i++) {

    /* Change the index if
       (codedEnergy*gainTbl[i]*gainTbl[i])<(targetEn*gain[0]*gain[0]) AND
       gainTbl[i] < 2*gain[0]
    */

    t32 = WEBRTC_SPL_MUL_16_16(temp1, (*gainPtr));
    t32 = t32 - targetEner;
    if (t32 < 0) {
      if ((*WebRtcIlbcfix_kGainSq5_ptr) < tmpW32) {
        j=i;
        WebRtcIlbcfix_kGainSq5_ptr = (WebRtc_Word16*)&WebRtcIlbcfix_kGainSq5[i];
      }
    }
    gainPtr++;
  }
  gain_index[0]=j;

  return;
}
Пример #12
0
/*-----------------------------------------------------------*
 * procedure Calc_exc_rand                                   *
 *           ~~~~~~~~~~~~~                                   *
 *   Computes comfort noise excitation                       *
 *   for SID and not-transmitted frames                      *
 *-----------------------------------------------------------*/
void WebRtcG729fix_Calc_exc_rand(
  int32_t L_exc_err[],
  int16_t cur_gain,      /* (i)   :   target sample gain                 */
  int16_t *exc,          /* (i/o) :   excitation array                   */
  int16_t *seed,         /* (i)   :   current Vad decision               */
  int flag_cod           /* (i)   :   encoder/decoder flag               */
)
{
  int16_t i, j, i_subfr;
  int16_t temp1, temp2;
  int16_t pos[4];
  int16_t sign[4];
  int16_t t0, frac;
  int16_t *cur_exc;
  int16_t g, Gp, Gp2;
  int16_t excg[L_SUBFR], excs[L_SUBFR];
  int32_t L_acc, L_ener, L_k;
  int16_t max, hi, lo, inter_exc;
  int16_t sh;
  int16_t x1, x2;
  
  if (cur_gain == 0) {
    WebRtcSpl_ZerosArrayW16(exc, L_FRAME);
    Gp = 0;
    t0 = WebRtcSpl_AddSatW16(L_SUBFR,1);
    for (i_subfr = 0;  i_subfr < L_FRAME; i_subfr += L_SUBFR) {
      if (flag_cod != FLAG_DEC)
        WebRtcG729fix_update_exc_err(L_exc_err, Gp, t0);
    }
    return;
  }
  
  /* Loop on subframes */
  
  cur_exc = exc;
  
  for (i_subfr = 0;  i_subfr < L_FRAME; i_subfr += L_SUBFR) {

    /* generate random adaptive codebook & fixed codebook parameters */
    /*****************************************************************/
    temp1 = WebRtcG729fix_Random(seed);
    frac = WebRtcSpl_SubSatW16((temp1 & (int16_t)0x0003), 1);
    if(frac == 2) frac = 0;
    temp1 = shr(temp1, 2);
    t0 = WebRtcSpl_AddSatW16((temp1 & (int16_t)0x003F), 40);
    temp1 = shr(temp1, 6);
    temp2 = temp1 & (int16_t)0x0007;
    pos[0] = WebRtcSpl_AddSatW16(shl(temp2, 2), temp2); /* 5 * temp2 */
    temp1 = shr(temp1, 3);
    sign[0] = temp1 & (int16_t)0x0001;
    temp1 = shr(temp1, 1);
    temp2 = temp1 & (int16_t)0x0007;
    temp2 = WebRtcSpl_AddSatW16(shl(temp2, 2), temp2);
    pos[1] = WebRtcSpl_AddSatW16(temp2, 1);     /* 5 * x + 1 */
    temp1 = shr(temp1, 3);
    sign[1] = temp1 & (int16_t)0x0001;
    temp1 = WebRtcG729fix_Random(seed);
    temp2 = temp1 & (int16_t)0x0007;
    temp2 = WebRtcSpl_AddSatW16(shl(temp2, 2), temp2);
    pos[2] = WebRtcSpl_AddSatW16(temp2, 2);     /* 5 * x + 2 */
    temp1 = shr(temp1, 3);
    sign[2] = temp1 & (int16_t)0x0001;
    temp1 = shr(temp1, 1);
    temp2 = temp1 & (int16_t)0x000F;
    pos[3] = WebRtcSpl_AddSatW16((temp2 & (int16_t)1), 3); /* j+3*/
    temp2 = (shr(temp2, 1)) & (int16_t)7;
    temp2 = WebRtcSpl_AddSatW16(shl(temp2, 2), temp2); /* 5i */
    pos[3] = WebRtcSpl_AddSatW16(pos[3], temp2);
    temp1 = shr(temp1, 4);
    sign[3] = temp1 & (int16_t)0x0001;
    Gp = WebRtcG729fix_Random(seed) & (int16_t)0x1FFF; /* < 0.5 Q14 */
    Gp2 = shl(Gp, 1);           /* Q15 */


    /* Generate gaussian excitation */
    /********************************/
    L_acc = 0L;
    for(i=0; i<L_SUBFR; i++) {
      temp1 = Gauss(seed);
      L_acc = L_mac(L_acc, temp1, temp1);
      excg[i] = temp1;
    }

/*
    Compute fact = alpha x cur_gain * sqrt(L_SUBFR / Eg)
    with Eg = SUM(i=0->39) excg[i]^2
    and alpha = 0.5
    alpha x sqrt(L_SUBFR)/2 = 1 + FRAC1
*/
    L_acc = WebRtcG729fix_Inv_sqrt(L_shr(L_acc,1));  /* Q30 */
    WebRtcG729fix_L_Extract(L_acc, &hi, &lo);
    /* cur_gain = cur_gainR << 3 */
    temp1 = mult_r(cur_gain, FRAC1);
    temp1 = WebRtcSpl_AddSatW16(cur_gain, temp1);
    /* <=> alpha x cur_gainR x 2^2 x sqrt(L_SUBFR) */

    L_acc = WebRtcG729fix_Mpy_32_16(hi, lo, temp1);   /* fact << 17 */
    sh = WebRtcSpl_NormW32(L_acc);
    temp1 = extract_h(L_shl(L_acc, sh));  /* fact << (sh+1) */

    sh = WebRtcSpl_SubSatW16(sh, 14);
    for (i = 0; i < L_SUBFR; i++) {
      temp2 = mult_r(excg[i], temp1);
      temp2 = shr_r(temp2, sh);   /* shl if sh < 0 */
      excg[i] = temp2;
    }

    /* generate random  adaptive excitation */
    /****************************************/
    WebRtcG729fix_Pred_lt_3(cur_exc, t0, frac, L_SUBFR);


    /* compute adaptive + gaussian exc -> cur_exc */
    /**********************************************/
    max = 0;
    for(i = 0; i < L_SUBFR; i++) {
      temp1 = mult_r(cur_exc[i], Gp2);
      temp1 = WebRtcSpl_AddSatW16(temp1, excg[i]); /* may overflow */
      cur_exc[i] = temp1;
      temp1 = abs_s(temp1);
      if (temp1 > max)
        max = temp1;
    }

    /* rescale cur_exc -> excs */
    if (max == 0)
      sh = 0;
    else {
      sh = WebRtcSpl_SubSatW16(3, WebRtcSpl_NormW16(max));
      if (sh <= 0)
        sh = 0;
    }
    for (i = 0; i < L_SUBFR; i++) {
      excs[i] = shr(cur_exc[i], sh);
    }

    /* Compute fixed code gain */
    /***************************/

    /**********************************************************/
    /*** Solve EQ(X) = 4 X**2 + 2 b X + c                     */
    /**********************************************************/

    L_ener = 0L;
    for (i = 0; i < L_SUBFR; i++) {
      L_ener = L_mac(L_ener, excs[i], excs[i]);
    } /* ener x 2^(-2sh + 1) */

    /* inter_exc = b >> sh */
    inter_exc = 0;
    for (i = 0; i < 4; i++) {
      j = pos[i];
      if (sign[i] == 0) {
        inter_exc = WebRtcSpl_SubSatW16(inter_exc, excs[j]);
      }
      else {
        inter_exc = WebRtcSpl_AddSatW16(inter_exc, excs[j]);
      }
    }

    /* Compute k = cur_gainR x cur_gainR x L_SUBFR */
    L_acc = L_mult(cur_gain, L_SUBFR);
    L_acc = L_shr(L_acc, 6);
    temp1 = extract_l(L_acc);   /* cur_gainR x L_SUBFR x 2^(-2) */
    L_k   = L_mult(cur_gain, temp1); /* k << 2 */
    temp1 = WebRtcSpl_AddSatW16(1, shl(sh,1));
    L_acc = L_shr(L_k, temp1);  /* k x 2^(-2sh+1) */

    /* Compute delta = b^2 - 4 c */
    L_acc = WebRtcSpl_SubSatW32(L_acc, L_ener); /* - 4 c x 2^(-2sh-1) */
    inter_exc = shr(inter_exc, 1);
    L_acc = L_mac(L_acc, inter_exc, inter_exc); /* 2^(-2sh-1) */
    sh = WebRtcSpl_AddSatW16(sh, 1);
    /* inter_exc = b x 2^(-sh) */
    /* L_acc = delta x 2^(-2sh+1) */

    if (L_acc < 0) {

      /* adaptive excitation = 0 */
      WEBRTC_SPL_MEMCPY_W16(cur_exc, excg, L_SUBFR);
      temp1 = abs_s(excg[(int)pos[0]]) | abs_s(excg[(int)pos[1]]);
      temp2 = abs_s(excg[(int)pos[2]]) | abs_s(excg[(int)pos[3]]);
      temp1 = temp1 | temp2;
      sh = ((temp1 & (int16_t)0x4000) == 0) ? (int16_t)1 : (int16_t)2;
      inter_exc = 0;
      for(i=0; i<4; i++) {
        temp1 = shr(excg[(int)pos[i]], sh);
        if(sign[i] == 0) {
          inter_exc = WebRtcSpl_SubSatW16(inter_exc, temp1);
        }
        else {
          inter_exc = WebRtcSpl_AddSatW16(inter_exc, temp1);
        }
      } /* inter_exc = b >> sh */
      WebRtcG729fix_L_Extract(L_k, &hi, &lo);
      L_acc = WebRtcG729fix_Mpy_32_16(hi, lo, K0); /* k x (1- alpha^2) << 2 */
      temp1 = WebRtcSpl_SubSatW16(shl(sh, 1), 1); /* temp1 > 0 */
      L_acc = L_shr(L_acc, temp1); /* 4k x (1 - alpha^2) << (-2sh+1) */
      L_acc = L_mac(L_acc, inter_exc, inter_exc); /* delta << (-2sh+1) */
      Gp = 0;
    }

    temp2 = Sqrt(L_acc);        /* >> sh */
    x1 = WebRtcSpl_SubSatW16(temp2, inter_exc);
    x2 = negate(WebRtcSpl_AddSatW16(inter_exc, temp2)); /* x 2^(-sh+2) */
    if(abs_s(x2) < abs_s(x1)) x1 = x2;
    temp1 = WebRtcSpl_SubSatW16(2, sh);
    g = shr_r(x1, temp1);       /* shl if temp1 < 0 */
    if (g >= 0) {
      if (g > G_MAX)
        g = G_MAX;
    }
    else {
      if (WebRtcSpl_AddSatW16(g, G_MAX) < 0)
        g = negate(G_MAX);
    }

    /* Update cur_exc with ACELP excitation */
    for (i = 0; i < 4; i++) {
      j = pos[i];
      if (sign[i] != 0) {
        cur_exc[j] = WebRtcSpl_AddSatW16(cur_exc[j], g);
      }
      else {
        cur_exc[j] = WebRtcSpl_SubSatW16(cur_exc[j], g);
      }
    }

    if (flag_cod != FLAG_DEC)
      WebRtcG729fix_update_exc_err(L_exc_err, Gp, t0);

    cur_exc += L_SUBFR;
  } /* end of loop on subframes */
  
  return;
}
Пример #13
0
void WebRtcIlbcfix_Poly2Lsp(
    int16_t *a,  /* (o) A coefficients in Q12 */
    int16_t *lsp, /* (i) LSP coefficients in Q15 */
    int16_t *old_lsp /* (i) old LSP coefficients that are used if the new
                              coefficients turn out to be unstable */
                            ) {
  int16_t f[2][6]; /* f[0][] represents f1 and f[1][] represents f2 */
  int16_t *a_i_ptr, *a_10mi_ptr;
  int16_t *f1ptr, *f2ptr;
  int32_t tmpW32;
  int16_t x, y, xlow, ylow, xmid, ymid, xhigh, yhigh, xint;
  int16_t shifts, sign;
  int i, j;
  int foundFreqs;
  int fi_select;

  /*
     Calculate the two polynomials f1(z) and f2(z)
     (the sum and the diff polynomial)
     f1[0] = f2[0] = 1.0;
     f1[i+1] = a[i+1] + a[10-i] - f1[i];
     f2[i+1] = a[i+1] - a[10-i] - f1[i];
  */

  a_i_ptr = a + 1;
  a_10mi_ptr = a + 10;
  f1ptr = f[0];
  f2ptr = f[1];
  (*f1ptr) = 1024; /* 1.0 in Q10 */
  (*f2ptr) = 1024; /* 1.0 in Q10 */
  for (i = 0; i < 5; i++) {
    (*(f1ptr+1)) = (int16_t)(WEBRTC_SPL_RSHIFT_W32(((int32_t)(*a_i_ptr)+(*a_10mi_ptr)), 2) - (*f1ptr));
    (*(f2ptr+1)) = (int16_t)(WEBRTC_SPL_RSHIFT_W32(((int32_t)(*a_i_ptr)-(*a_10mi_ptr)), 2) + (*f2ptr));
    a_i_ptr++;
    a_10mi_ptr--;
    f1ptr++;
    f2ptr++;
  }

  /*
    find the LSPs using the Chebychev pol. evaluation
  */

  fi_select = 0; /* selector between f1 and f2, start with f1 */

  foundFreqs = 0;

  xlow = WebRtcIlbcfix_kCosGrid[0];
  ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);

  /*
     Iterate until all the 10 LSP's have been found or
     all the grid points have been tried. If the 10 LSP's can
     not be found, set the LSP vector to previous LSP
  */

  for (j = 1; j < COS_GRID_POINTS && foundFreqs < 10; j++) {
    xhigh = xlow;
    yhigh = ylow;
    xlow = WebRtcIlbcfix_kCosGrid[j];
    ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);

    if (WEBRTC_SPL_MUL_16_16(ylow, yhigh) <= 0) {
      /* Run 4 times to reduce the interval */
      for (i = 0; i < 4; i++) {
        /* xmid =(xlow + xhigh)/2 */
        xmid = WEBRTC_SPL_RSHIFT_W16(xlow, 1) + WEBRTC_SPL_RSHIFT_W16(xhigh, 1);
        ymid = WebRtcIlbcfix_Chebyshev(xmid, f[fi_select]);

        if (WEBRTC_SPL_MUL_16_16(ylow, ymid) <= 0) {
          yhigh = ymid;
          xhigh = xmid;
        } else {
          ylow = ymid;
          xlow = xmid;
        }
      }

      /*
        Calculater xint by linear interpolation:
        xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow);
      */

      x = xhigh - xlow;
      y = yhigh - ylow;

      if (y == 0) {
        xint = xlow;
      } else {
        sign = y;
        y = WEBRTC_SPL_ABS_W16(y);
        shifts = (int16_t)WebRtcSpl_NormW32(y)-16;
        y = WEBRTC_SPL_LSHIFT_W16(y, shifts);
        y = (int16_t)WebRtcSpl_DivW32W16(536838144, y); /* 1/(yhigh-ylow) */

        tmpW32 = WEBRTC_SPL_MUL_16_16_RSFT(x, y, (19-shifts));

        /* y=(xhigh-xlow)/(yhigh-ylow) */
        y = (int16_t)(tmpW32&0xFFFF);

        if (sign < 0) {
          y = -y;
        }
        /* tmpW32 = ylow*(xhigh-xlow)/(yhigh-ylow) */
        tmpW32 = WEBRTC_SPL_MUL_16_16_RSFT(ylow, y, 10);
        xint = xlow-(int16_t)(tmpW32&0xFFFF);
      }

      /* Store the calculated lsp */
      lsp[foundFreqs] = (int16_t)xint;
      foundFreqs++;

      /* if needed, set xlow and ylow for next recursion */
      if (foundFreqs<10) {
        xlow = xint;
        /* Swap between f1 and f2 (f[0][] and f[1][]) */
        fi_select = ((fi_select+1)&0x1);

        ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);
      }
    }
  }

  /* Check if M roots found, if not then use the old LSP */
  if (foundFreqs < 10) {
    WEBRTC_SPL_MEMCPY_W16(lsp, old_lsp, 10);
  }
  return;
}