Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 /*
     12  * lpc_masking_model.c
     13  *
     14  * LPC analysis and filtering functions
     15  *
     16  */
     17 
     18 #include "lpc_masking_model.h"
     19 
     20 #include <limits.h>  /* For LLONG_MAX and LLONG_MIN. */
     21 #include "codec.h"
     22 #include "entropy_coding.h"
     23 #include "settings.h"
     24 
     25 /* The conversion is implemented by the step-down algorithm */
     26 void WebRtcSpl_AToK_JSK(
     27     int16_t *a16, /* Q11 */
     28     int16_t useOrder,
     29     int16_t *k16  /* Q15 */
     30                         )
     31 {
     32   int m, k;
     33   int32_t tmp32[MAX_AR_MODEL_ORDER];
     34   int32_t tmp32b;
     35   int32_t tmp_inv_denum32;
     36   int16_t tmp_inv_denum16;
     37 
     38   k16[useOrder-1]= WEBRTC_SPL_LSHIFT_W16(a16[useOrder], 4); //Q11<<4 => Q15
     39 
     40   for (m=useOrder-1; m>0; m--) {
     41     tmp_inv_denum32 = ((int32_t) 1073741823) - WEBRTC_SPL_MUL_16_16(k16[m], k16[m]); // (1 - k^2) in Q30
     42     tmp_inv_denum16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp_inv_denum32, 15); // (1 - k^2) in Q15
     43 
     44     for (k=1; k<=m; k++) {
     45       tmp32b = WEBRTC_SPL_LSHIFT_W32((int32_t)a16[k], 16) -
     46           WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(k16[m], a16[m-k+1]), 1);
     47 
     48       tmp32[k] = WebRtcSpl_DivW32W16(tmp32b, tmp_inv_denum16); //Q27/Q15 = Q12
     49     }
     50 
     51     for (k=1; k<m; k++) {
     52       a16[k] = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32[k], 1); //Q12>>1 => Q11
     53     }
     54 
     55     tmp32[m] = WEBRTC_SPL_SAT(4092, tmp32[m], -4092);
     56     k16[m-1] = (int16_t) WEBRTC_SPL_LSHIFT_W32(tmp32[m], 3); //Q12<<3 => Q15
     57   }
     58 
     59   return;
     60 }
     61 
     62 
     63 
     64 
     65 
     66 int16_t WebRtcSpl_LevinsonW32_JSK(
     67     int32_t *R,  /* (i) Autocorrelation of length >= order+1 */
     68     int16_t *A,  /* (o) A[0..order] LPC coefficients (Q11) */
     69     int16_t *K,  /* (o) K[0...order-1] Reflection coefficients (Q15) */
     70     int16_t order /* (i) filter order */
     71                                         ) {
     72   int16_t i, j;
     73   int16_t R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1];
     74   /* Aurocorr coefficients in high precision */
     75   int16_t A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1];
     76   /* LPC coefficients in high precicion */
     77   int16_t A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1];
     78   /* LPC coefficients for next iteration */
     79   int16_t K_hi, K_low;      /* reflection coefficient in high precision */
     80   int16_t Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision
     81                                                    and with scale factor */
     82   int16_t tmp_hi, tmp_low;
     83   int32_t temp1W32, temp2W32, temp3W32;
     84   int16_t norm;
     85 
     86   /* Normalize the autocorrelation R[0]...R[order+1] */
     87 
     88   norm = WebRtcSpl_NormW32(R[0]);
     89 
     90   for (i=order;i>=0;i--) {
     91     temp1W32 = WEBRTC_SPL_LSHIFT_W32(R[i], norm);
     92     /* Put R in hi and low format */
     93     R_hi[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
     94     R_low[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[i], 16)), 1);
     95   }
     96 
     97   /* K = A[1] = -R[1] / R[0] */
     98 
     99   temp2W32  = WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[1],16) +
    100       WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[1],1);     /* R[1] in Q31      */
    101   temp3W32  = WEBRTC_SPL_ABS_W32(temp2W32);      /* abs R[1]         */
    102   temp1W32  = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); /* abs(R[1])/R[0] in Q31 */
    103   /* Put back the sign on R[1] */
    104   if (temp2W32 > 0) {
    105     temp1W32 = -temp1W32;
    106   }
    107 
    108   /* Put K in hi and low format */
    109   K_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    110   K_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)K_hi, 16)), 1);
    111 
    112   /* Store first reflection coefficient */
    113   K[0] = K_hi;
    114 
    115   temp1W32 = WEBRTC_SPL_RSHIFT_W32(temp1W32, 4);    /* A[1] in Q27      */
    116 
    117   /* Put A[1] in hi and low format */
    118   A_hi[1] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    119   A_low[1] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[1], 16)), 1);
    120 
    121   /*  Alpha = R[0] * (1-K^2) */
    122 
    123   temp1W32  = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, K_low), 14) +
    124                                       WEBRTC_SPL_MUL_16_16(K_hi, K_hi)), 1); /* temp1W32 = k^2 in Q31 */
    125 
    126   temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32);    /* Guard against <0 */
    127   temp1W32 = (int32_t)0x7fffffffL - temp1W32;    /* temp1W32 = (1 - K[0]*K[0]) in Q31 */
    128 
    129   /* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */
    130   tmp_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    131   tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1);
    132 
    133   /* Calculate Alpha in Q31 */
    134   temp1W32 = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_hi) +
    135                                      WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_low), 15) +
    136                                      WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_low[0], tmp_hi), 15) ), 1);
    137 
    138   /* Normalize Alpha and put it in hi and low format */
    139 
    140   Alpha_exp = WebRtcSpl_NormW32(temp1W32);
    141   temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, Alpha_exp);
    142   Alpha_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    143   Alpha_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)Alpha_hi, 16)), 1);
    144 
    145   /* Perform the iterative calculations in the
    146      Levinson Durbin algorithm */
    147 
    148   for (i=2; i<=order; i++)
    149   {
    150 
    151     /*                    ----
    152                           \
    153                           temp1W32 =  R[i] + > R[j]*A[i-j]
    154                           /
    155                           ----
    156                           j=1..i-1
    157     */
    158 
    159     temp1W32 = 0;
    160 
    161     for(j=1; j<i; j++) {
    162       /* temp1W32 is in Q31 */
    163       temp1W32 += (WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[j], A_hi[i-j]), 1) +
    164                    WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_hi[j], A_low[i-j]), 15) +
    165                                             WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(R_low[j], A_hi[i-j]), 15) ), 1));
    166     }
    167 
    168     temp1W32  = WEBRTC_SPL_LSHIFT_W32(temp1W32, 4);
    169     temp1W32 += (WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[i], 16) +
    170                  WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[i], 1));
    171 
    172     /* K = -temp1W32 / Alpha */
    173     temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32);      /* abs(temp1W32) */
    174     temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); /* abs(temp1W32)/Alpha */
    175 
    176     /* Put the sign of temp1W32 back again */
    177     if (temp1W32 > 0) {
    178       temp3W32 = -temp3W32;
    179     }
    180 
    181     /* Use the Alpha shifts from earlier to denormalize */
    182     norm = WebRtcSpl_NormW32(temp3W32);
    183     if ((Alpha_exp <= norm)||(temp3W32==0)) {
    184       temp3W32 = WEBRTC_SPL_LSHIFT_W32(temp3W32, Alpha_exp);
    185     } else {
    186       if (temp3W32 > 0)
    187       {
    188         temp3W32 = (int32_t)0x7fffffffL;
    189       } else
    190       {
    191         temp3W32 = (int32_t)0x80000000L;
    192       }
    193     }
    194 
    195     /* Put K on hi and low format */
    196     K_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
    197     K_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)K_hi, 16)), 1);
    198 
    199     /* Store Reflection coefficient in Q15 */
    200     K[i-1] = K_hi;
    201 
    202     /* Test for unstable filter. If unstable return 0 and let the
    203        user decide what to do in that case
    204     */
    205 
    206     if ((int32_t)WEBRTC_SPL_ABS_W16(K_hi) > (int32_t)32740) {
    207       return(-i); /* Unstable filter */
    208     }
    209 
    210     /*
    211       Compute updated LPC coefficient: Anew[i]
    212       Anew[j]= A[j] + K*A[i-j]   for j=1..i-1
    213       Anew[i]= K
    214     */
    215 
    216     for(j=1; j<i; j++)
    217     {
    218       temp1W32  = WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[j],16) +
    219           WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[j],1);    /* temp1W32 = A[j] in Q27 */
    220 
    221       temp1W32 += WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_MUL_16_16(K_hi, A_hi[i-j]) +
    222                                            WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, A_low[i-j]), 15) +
    223                                            WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_low, A_hi[i-j]), 15) ), 1); /* temp1W32 += K*A[i-j] in Q27 */
    224 
    225       /* Put Anew in hi and low format */
    226       A_upd_hi[j] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    227       A_upd_low[j] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)A_upd_hi[j], 16)), 1);
    228     }
    229 
    230     temp3W32 = WEBRTC_SPL_RSHIFT_W32(temp3W32, 4);     /* temp3W32 = K in Q27 (Convert from Q31 to Q27) */
    231 
    232     /* Store Anew in hi and low format */
    233     A_upd_hi[i] = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
    234     A_upd_low[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)A_upd_hi[i], 16)), 1);
    235 
    236     /*  Alpha = Alpha * (1-K^2) */
    237 
    238     temp1W32  = WEBRTC_SPL_LSHIFT_W32((WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(K_hi, K_low), 14) +
    239                                         WEBRTC_SPL_MUL_16_16(K_hi, K_hi)), 1);  /* K*K in Q31 */
    240 
    241     temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32);      /* Guard against <0 */
    242     temp1W32 = (int32_t)0x7fffffffL - temp1W32;      /* 1 - K*K  in Q31 */
    243 
    244     /* Convert 1- K^2 in hi and low format */
    245     tmp_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    246     tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1);
    247 
    248     /* Calculate Alpha = Alpha * (1-K^2) in Q31 */
    249     temp1W32 = WEBRTC_SPL_LSHIFT_W32(( WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_hi) +
    250                                         WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_low), 15) +
    251                                         WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_16(Alpha_low, tmp_hi), 15)), 1);
    252 
    253     /* Normalize Alpha and store it on hi and low format */
    254 
    255     norm = WebRtcSpl_NormW32(temp1W32);
    256     temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, norm);
    257 
    258     Alpha_hi = (int16_t) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    259     Alpha_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((int32_t)Alpha_hi, 16)), 1);
    260 
    261     /* Update the total nomalization of Alpha */
    262     Alpha_exp = Alpha_exp + norm;
    263 
    264     /* Update A[] */
    265 
    266     for(j=1; j<=i; j++)
    267     {
    268       A_hi[j] =A_upd_hi[j];
    269       A_low[j] =A_upd_low[j];
    270     }
    271   }
    272 
    273   /*
    274     Set A[0] to 1.0 and store the A[i] i=1...order in Q12
    275     (Convert from Q27 and use rounding)
    276   */
    277 
    278   A[0] = 2048;
    279 
    280   for(i=1; i<=order; i++) {
    281     /* temp1W32 in Q27 */
    282     temp1W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[i], 16) +
    283         WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[i], 1);
    284     /* Round and store upper word */
    285     A[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32+(int32_t)32768, 16);
    286   }
    287   return(1); /* Stable filters */
    288 }
    289 
    290 
    291 
    292 
    293 
    294 /* window */
    295 /* Matlab generation of floating point code:
    296  *  t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid;
    297  *  for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end
    298  * All values are multiplyed with 2^21 in fixed point code.
    299  */
    300 static const int16_t kWindowAutocorr[WINLEN] = {
    301   0,     0,     0,     0,     0,     1,     1,     2,     2,     3,     5,     6,
    302   8,    10,    12,    14,    17,    20,    24,    28,    33,    38,    43,    49,
    303   56,    63,    71,    79,    88,    98,   108,   119,   131,   143,   157,   171,
    304   186,   202,   219,   237,   256,   275,   296,   318,   341,   365,   390,   416,
    305   444,   472,   502,   533,   566,   600,   635,   671,   709,   748,   789,   831,
    306   875,   920,   967,  1015,  1065,  1116,  1170,  1224,  1281,  1339,  1399,  1461,
    307   1525,  1590,  1657,  1726,  1797,  1870,  1945,  2021,  2100,  2181,  2263,  2348,
    308   2434,  2523,  2614,  2706,  2801,  2898,  2997,  3099,  3202,  3307,  3415,  3525,
    309   3637,  3751,  3867,  3986,  4106,  4229,  4354,  4481,  4611,  4742,  4876,  5012,
    310   5150,  5291,  5433,  5578,  5725,  5874,  6025,  6178,  6333,  6490,  6650,  6811,
    311   6974,  7140,  7307,  7476,  7647,  7820,  7995,  8171,  8349,  8529,  8711,  8894,
    312   9079,  9265,  9453,  9642,  9833, 10024, 10217, 10412, 10607, 10803, 11000, 11199,
    313   11398, 11597, 11797, 11998, 12200, 12401, 12603, 12805, 13008, 13210, 13412, 13614,
    314   13815, 14016, 14216, 14416, 14615, 14813, 15009, 15205, 15399, 15591, 15782, 15971,
    315   16157, 16342, 16524, 16704, 16881, 17056, 17227, 17395, 17559, 17720, 17877, 18030,
    316   18179, 18323, 18462, 18597, 18727, 18851, 18970, 19082, 19189, 19290, 19384, 19471,
    317   19551, 19623, 19689, 19746, 19795, 19835, 19867, 19890, 19904, 19908, 19902, 19886,
    318   19860, 19823, 19775, 19715, 19644, 19561, 19465, 19357, 19237, 19102, 18955, 18793,
    319   18618, 18428, 18223, 18004, 17769, 17518, 17252, 16970, 16672, 16357, 16025, 15677,
    320   15311, 14929, 14529, 14111, 13677, 13225, 12755, 12268, 11764, 11243, 10706, 10152,
    321   9583,  8998,  8399,  7787,  7162,  6527,  5883,  5231,  4576,  3919,  3265,  2620,
    322   1990,  1386,   825,   333
    323 };
    324 
    325 
    326 /* By using a hearing threshold level in dB of -28 dB (higher value gives more noise),
    327    the H_T_H (in float) can be calculated as:
    328    H_T_H = pow(10.0, 0.05 * (-28.0)) = 0.039810717055350
    329    In Q19, H_T_H becomes round(0.039810717055350*2^19) ~= 20872, i.e.
    330    H_T_H = 20872/524288.0, and H_T_HQ19 = 20872;
    331 */
    332 
    333 
    334 /* The bandwidth expansion vectors are created from:
    335    kPolyVecLo=[0.900000,0.810000,0.729000,0.656100,0.590490,0.531441,0.478297,0.430467,0.387420,0.348678,0.313811,0.282430];
    336    kPolyVecHi=[0.800000,0.640000,0.512000,0.409600,0.327680,0.262144];
    337    round(kPolyVecLo*32768)
    338    round(kPolyVecHi*32768)
    339 */
    340 static const int16_t kPolyVecLo[12] = {
    341   29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425, 10283, 9255
    342 };
    343 static const int16_t kPolyVecHi[6] = {
    344   26214, 20972, 16777, 13422, 10737, 8590
    345 };
    346 
    347 static __inline int32_t log2_Q8_LPC( uint32_t x ) {
    348 
    349   int32_t zeros, lg2;
    350   int16_t frac;
    351 
    352   zeros=WebRtcSpl_NormU32(x);
    353   frac=(int16_t)WEBRTC_SPL_RSHIFT_W32(((uint32_t)WEBRTC_SPL_LSHIFT_W32(x, zeros)&0x7FFFFFFF), 23);
    354 
    355   /* log2(x) */
    356 
    357   lg2= (WEBRTC_SPL_LSHIFT_W16((31-zeros), 8)+frac);
    358   return lg2;
    359 
    360 }
    361 
    362 static const int16_t kMulPitchGain = -25; /* 200/256 in Q5 */
    363 static const int16_t kChngFactor = 3523; /* log10(2)*10/4*0.4/1.4=log10(2)/1.4= 0.2150 in Q14 */
    364 static const int16_t kExp2 = 11819; /* 1/log(2) */
    365 const int kShiftLowerBand = 11;  /* Shift value for lower band in Q domain. */
    366 const int kShiftHigherBand = 12;  /* Shift value for higher band in Q domain. */
    367 
    368 void WebRtcIsacfix_GetVars(const int16_t *input, const int16_t *pitchGains_Q12,
    369                            uint32_t *oldEnergy, int16_t *varscale)
    370 {
    371   int k;
    372   uint32_t nrgQ[4];
    373   int16_t nrgQlog[4];
    374   int16_t tmp16, chng1, chng2, chng3, chng4, tmp, chngQ, oldNrgQlog, pgQ, pg3;
    375   int32_t expPg32;
    376   int16_t expPg, divVal;
    377   int16_t tmp16_1, tmp16_2;
    378 
    379   /* Calculate energies of first and second frame halfs */
    380   nrgQ[0]=0;
    381   for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES/4 + QLOOKAHEAD) / 2; k++) {
    382     nrgQ[0] +=WEBRTC_SPL_MUL_16_16(input[k],input[k]);
    383   }
    384   nrgQ[1]=0;
    385   for ( ; k < (FRAMESAMPLES/2 + QLOOKAHEAD) / 2; k++) {
    386     nrgQ[1] +=WEBRTC_SPL_MUL_16_16(input[k],input[k]);
    387   }
    388   nrgQ[2]=0;
    389   for ( ; k < (WEBRTC_SPL_MUL_16_16(FRAMESAMPLES, 3)/4 + QLOOKAHEAD) / 2; k++) {
    390     nrgQ[2] +=WEBRTC_SPL_MUL_16_16(input[k],input[k]);
    391   }
    392   nrgQ[3]=0;
    393   for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
    394     nrgQ[3] +=WEBRTC_SPL_MUL_16_16(input[k],input[k]);
    395   }
    396 
    397   for ( k=0; k<4; k++) {
    398     nrgQlog[k] = (int16_t)log2_Q8_LPC(nrgQ[k]); /* log2(nrgQ) */
    399   }
    400   oldNrgQlog = (int16_t)log2_Q8_LPC(*oldEnergy);
    401 
    402   /* Calculate average level change */
    403   chng1 = WEBRTC_SPL_ABS_W16(nrgQlog[3]-nrgQlog[2]);
    404   chng2 = WEBRTC_SPL_ABS_W16(nrgQlog[2]-nrgQlog[1]);
    405   chng3 = WEBRTC_SPL_ABS_W16(nrgQlog[1]-nrgQlog[0]);
    406   chng4 = WEBRTC_SPL_ABS_W16(nrgQlog[0]-oldNrgQlog);
    407   tmp = chng1+chng2+chng3+chng4;
    408   chngQ = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(tmp, kChngFactor, 10); /* Q12 */
    409   chngQ += 2926; /* + 1.0/1.4 in Q12 */
    410 
    411   /* Find average pitch gain */
    412   pgQ = 0;
    413   for (k=0; k<4; k++)
    414   {
    415     pgQ += pitchGains_Q12[k];
    416   }
    417 
    418   pg3 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(pgQ, pgQ,11); /* pgQ in Q(12+2)=Q14. Q14*Q14>>11 => Q17 */
    419   pg3 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(pgQ, pg3,13); /* Q17*Q14>>13 =>Q18  */
    420   pg3 = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(pg3, kMulPitchGain ,5); /* Q10  kMulPitchGain = -25 = -200 in Q-3. */
    421 
    422   tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,pg3,13);/* Q13*Q10>>13 => Q10*/
    423   if (tmp16<0) {
    424     tmp16_2 = (0x0400 | (tmp16 & 0x03FF));
    425     tmp16_1 = (WEBRTC_SPL_RSHIFT_W16((uint16_t)(tmp16 ^ 0xFFFF), 10)-3); /* Gives result in Q14 */
    426     if (tmp16_1<0)
    427       expPg=(int16_t) -WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
    428     else
    429       expPg=(int16_t) -WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
    430   } else
    431     expPg = (int16_t) -16384; /* 1 in Q14, since 2^0=1 */
    432 
    433   expPg32 = (int32_t)WEBRTC_SPL_LSHIFT_W16((int32_t)expPg, 8); /* Q22 */
    434   divVal = WebRtcSpl_DivW32W16ResW16(expPg32, chngQ); /* Q22/Q12=Q10 */
    435 
    436   tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,divVal,13);/* Q13*Q10>>13 => Q10*/
    437   if (tmp16<0) {
    438     tmp16_2 = (0x0400 | (tmp16 & 0x03FF));
    439     tmp16_1 = (WEBRTC_SPL_RSHIFT_W16((uint16_t)(tmp16 ^ 0xFFFF), 10)-3); /* Gives result in Q14 */
    440     if (tmp16_1<0)
    441       expPg=(int16_t) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
    442     else
    443       expPg=(int16_t) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
    444   } else
    445     expPg = (int16_t) 16384; /* 1 in Q14, since 2^0=1 */
    446 
    447   *varscale = expPg-1;
    448   *oldEnergy = nrgQ[3];
    449 }
    450 
    451 
    452 
    453 static __inline int16_t  exp2_Q10_T(int16_t x) { // Both in and out in Q10
    454 
    455   int16_t tmp16_1, tmp16_2;
    456 
    457   tmp16_2=(int16_t)(0x0400|(x&0x03FF));
    458   tmp16_1=-(int16_t)WEBRTC_SPL_RSHIFT_W16(x,10);
    459   if(tmp16_1>0)
    460     return (int16_t) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
    461   else
    462     return (int16_t) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
    463 
    464 }
    465 
    466 
    467 // Declare function pointers.
    468 AutocorrFix WebRtcIsacfix_AutocorrFix;
    469 CalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy;
    470 
    471 /* This routine calculates the residual energy for LPC.
    472  * Formula as shown in comments inside.
    473  */
    474 int32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order,
    475                                                int32_t q_val_corr,
    476                                                int q_val_polynomial,
    477                                                int16_t* a_polynomial,
    478                                                int32_t* corr_coeffs,
    479                                                int* q_val_residual_energy) {
    480   int i = 0, j = 0;
    481   int shift_internal = 0, shift_norm = 0;
    482   int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0;
    483   int64_t sum64 = 0, sum64_tmp = 0;
    484 
    485   for (i = 0; i <= lpc_order; i++) {
    486     for (j = i; j <= lpc_order; j++) {
    487       /* For the case of i == 0: residual_energy +=
    488        *    a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i];
    489        * For the case of i != 0: residual_energy +=
    490        *    a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2;
    491        */
    492 
    493       tmp32 = WEBRTC_SPL_MUL_16_16(a_polynomial[j], a_polynomial[j - i]);
    494                                    /* tmp32 in Q(q_val_polynomial * 2). */
    495       if (i != 0) {
    496         tmp32 <<= 1;
    497       }
    498       sum64_tmp = (int64_t)tmp32 * (int64_t)corr_coeffs[i];
    499       sum64_tmp >>= shift_internal;
    500 
    501       /* Test overflow and sum the result. */
    502       if(((sum64_tmp > 0 && sum64 > 0) && (LLONG_MAX - sum64 < sum64_tmp)) ||
    503          ((sum64_tmp < 0 && sum64 < 0) && (LLONG_MIN - sum64 > sum64_tmp))) {
    504         /* Shift right for overflow. */
    505         shift_internal += 1;
    506         sum64 >>= 1;
    507         sum64 += sum64_tmp >> 1;
    508       } else {
    509         sum64 += sum64_tmp;
    510       }
    511     }
    512   }
    513 
    514   word32_high = (int32_t)(sum64 >> 32);
    515   word32_low = (int32_t)sum64;
    516 
    517   // Calculate the value of shifting (shift_norm) for the 64-bit sum.
    518   if(word32_high != 0) {
    519     shift_norm = 32 - WebRtcSpl_NormW32(word32_high);
    520     residual_energy = (int32_t)(sum64 >> shift_norm);
    521   } else {
    522     if((word32_low & 0x80000000) != 0) {
    523       shift_norm = 1;
    524       residual_energy = (uint32_t)word32_low >> 1;
    525     } else {
    526       shift_norm = WebRtcSpl_NormW32(word32_low);
    527       residual_energy = word32_low << shift_norm;
    528       shift_norm = -shift_norm;
    529     }
    530   }
    531 
    532   /* Q(q_val_polynomial * 2) * Q(q_val_corr) >> shift_internal >> shift_norm
    533    *   = Q(q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2)
    534    */
    535   *q_val_residual_energy = q_val_corr - shift_internal - shift_norm
    536                            + q_val_polynomial * 2;
    537 
    538   return residual_energy;
    539 }
    540 
    541 void WebRtcIsacfix_GetLpcCoef(int16_t *inLoQ0,
    542                               int16_t *inHiQ0,
    543                               MaskFiltstr_enc *maskdata,
    544                               int16_t snrQ10,
    545                               const int16_t *pitchGains_Q12,
    546                               int32_t *gain_lo_hiQ17,
    547                               int16_t *lo_coeffQ15,
    548                               int16_t *hi_coeffQ15)
    549 {
    550   int k, n, ii;
    551   int pos1, pos2;
    552   int sh_lo, sh_hi, sh, ssh, shMem;
    553   int16_t varscaleQ14;
    554 
    555   int16_t tmpQQlo, tmpQQhi;
    556   int32_t tmp32;
    557   int16_t tmp16,tmp16b;
    558 
    559   int16_t polyHI[ORDERHI+1];
    560   int16_t rcQ15_lo[ORDERLO], rcQ15_hi[ORDERHI];
    561 
    562 
    563   int16_t DataLoQ6[WINLEN], DataHiQ6[WINLEN];
    564   int32_t corrloQQ[ORDERLO+2];
    565   int32_t corrhiQQ[ORDERHI+1];
    566   int32_t corrlo2QQ[ORDERLO+1];
    567   int16_t scale;
    568   int16_t QdomLO, QdomHI, newQdomHI, newQdomLO;
    569 
    570   int32_t res_nrgQQ;
    571   int32_t sqrt_nrg;
    572 
    573   /* less-noise-at-low-frequencies factor */
    574   int16_t aaQ14;
    575 
    576   /* Multiplication with 1/sqrt(12) ~= 0.28901734104046 can be done by convertion to
    577      Q15, i.e. round(0.28901734104046*32768) = 9471, and use 9471/32768.0 ~= 0.289032
    578   */
    579   int16_t snrq;
    580   int shft;
    581 
    582   int16_t tmp16a;
    583   int32_t tmp32a, tmp32b, tmp32c;
    584 
    585   int16_t a_LOQ11[ORDERLO+1];
    586   int16_t k_vecloQ15[ORDERLO];
    587   int16_t a_HIQ12[ORDERHI+1];
    588   int16_t k_vechiQ15[ORDERHI];
    589 
    590   int16_t stab;
    591 
    592   snrq=snrQ10;
    593 
    594   /* SNR= C * 2 ^ (D * snrq) ; C=0.289, D=0.05*log2(10)=0.166 (~=172 in Q10)*/
    595   tmp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(snrq, 172, 10); // Q10
    596   tmp16b = exp2_Q10_T(tmp16); // Q10
    597   snrq = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp16b, 285, 10); // Q10
    598 
    599   /* change quallevel depending on pitch gains and level fluctuations */
    600   WebRtcIsacfix_GetVars(inLoQ0, pitchGains_Q12, &(maskdata->OldEnergy), &varscaleQ14);
    601 
    602   /* less-noise-at-low-frequencies factor */
    603   /* Calculation of 0.35 * (0.5 + 0.5 * varscale) in fixpoint:
    604      With 0.35 in Q16 (0.35 ~= 22938/65536.0 = 0.3500061) and varscaleQ14 in Q14,
    605      we get Q16*Q14>>16 = Q14
    606   */
    607   aaQ14 = (int16_t) WEBRTC_SPL_RSHIFT_W32(
    608       (WEBRTC_SPL_MUL_16_16(22938, (8192 + WEBRTC_SPL_RSHIFT_W32(varscaleQ14, 1)))
    609        + ((int32_t)32768)), 16);
    610 
    611   /* Calculate tmp = (1.0 + aa*aa); in Q12 */
    612   tmp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(aaQ14, aaQ14, 15); //Q14*Q14>>15 = Q13
    613   tmpQQlo = 4096 + WEBRTC_SPL_RSHIFT_W16(tmp16, 1); // Q12 + Q13>>1 = Q12
    614 
    615   /* Calculate tmp = (1.0+aa) * (1.0+aa); */
    616   tmp16 = 8192 + WEBRTC_SPL_RSHIFT_W16(aaQ14, 1); // 1+a in Q13
    617   tmpQQhi = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp16, tmp16, 14); //Q13*Q13>>14 = Q12
    618 
    619   /* replace data in buffer by new look-ahead data */
    620   for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++) {
    621     maskdata->DataBufferLoQ0[pos1 + WINLEN - QLOOKAHEAD] = inLoQ0[pos1];
    622   }
    623 
    624   for (k = 0; k < SUBFRAMES; k++) {
    625 
    626     /* Update input buffer and multiply signal with window */
    627     for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
    628       maskdata->DataBufferLoQ0[pos1] = maskdata->DataBufferLoQ0[pos1 + UPDATE/2];
    629       maskdata->DataBufferHiQ0[pos1] = maskdata->DataBufferHiQ0[pos1 + UPDATE/2];
    630       DataLoQ6[pos1] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
    631           maskdata->DataBufferLoQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
    632       DataHiQ6[pos1] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
    633           maskdata->DataBufferHiQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
    634     }
    635     pos2 = (int16_t)(WEBRTC_SPL_MUL_16_16(k, UPDATE)/2);
    636     for (n = 0; n < UPDATE/2; n++, pos1++) {
    637       maskdata->DataBufferLoQ0[pos1] = inLoQ0[QLOOKAHEAD + pos2];
    638       maskdata->DataBufferHiQ0[pos1] = inHiQ0[pos2++];
    639       DataLoQ6[pos1] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
    640           maskdata->DataBufferLoQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
    641       DataHiQ6[pos1] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(
    642           maskdata->DataBufferHiQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
    643     }
    644 
    645     /* Get correlation coefficients */
    646     /* The highest absolute value measured inside DataLo in the test set
    647        For DataHi, corresponding value was 160.
    648 
    649        This means that it should be possible to represent the input values
    650        to WebRtcSpl_AutoCorrelation() as Q6 values (since 307*2^6 =
    651        19648). Of course, Q0 will also work, but due to the low energy in
    652        DataLo and DataHi, the outputted autocorrelation will be more accurate
    653        and mimic the floating point code better, by being in an high as possible
    654        Q-domain.
    655     */
    656 
    657     WebRtcIsacfix_AutocorrFix(corrloQQ,DataLoQ6,WINLEN, ORDERLO+1, &scale);
    658     QdomLO = 12-scale; // QdomLO is the Q-domain of corrloQQ
    659     sh_lo = WebRtcSpl_NormW32(corrloQQ[0]);
    660     QdomLO += sh_lo;
    661     for (ii=0; ii<ORDERLO+2; ii++) {
    662       corrloQQ[ii] = WEBRTC_SPL_LSHIFT_W32(corrloQQ[ii], sh_lo);
    663     }
    664     /* It is investigated whether it was possible to use 16 bits for the
    665        32-bit vector corrloQQ, but it didn't work. */
    666 
    667     WebRtcIsacfix_AutocorrFix(corrhiQQ,DataHiQ6,WINLEN, ORDERHI, &scale);
    668 
    669     QdomHI = 12-scale; // QdomHI is the Q-domain of corrhiQQ
    670     sh_hi = WebRtcSpl_NormW32(corrhiQQ[0]);
    671     QdomHI += sh_hi;
    672     for (ii=0; ii<ORDERHI+1; ii++) {
    673       corrhiQQ[ii] = WEBRTC_SPL_LSHIFT_W32(corrhiQQ[ii], sh_hi);
    674     }
    675 
    676     /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
    677 
    678     /* Calculate corrlo2[0] = tmpQQlo * corrlo[0] - 2.0*tmpQQlo * corrlo[1];*/
    679     corrlo2QQ[0] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[0]), 1)- // Q(12+QdomLO-16)>>1 = Q(QdomLO-5)
    680         WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, corrloQQ[1]), 2); // 2*Q(14+QdomLO-16)>>3 = Q(QdomLO-2)>>2 = Q(QdomLO-5)
    681 
    682     /* Calculate corrlo2[n] = tmpQQlo * corrlo[n] - tmpQQlo * (corrlo[n-1] + corrlo[n+1]);*/
    683     for (n = 1; n <= ORDERLO; n++) {
    684 
    685       tmp32 = WEBRTC_SPL_RSHIFT_W32(corrloQQ[n-1], 1) + WEBRTC_SPL_RSHIFT_W32(corrloQQ[n+1], 1); // Q(QdomLO-1)
    686       corrlo2QQ[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[n]), 1)- // Q(12+QdomLO-16)>>1 = Q(QdomLO-5)
    687           WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, tmp32), 2); // Q(14+QdomLO-1-16)>>2 = Q(QdomLO-3)>>2 = Q(QdomLO-5)
    688 
    689     }
    690     QdomLO -= 5;
    691 
    692     /* Calculate corrhi[n] = tmpQQhi * corrhi[n]; */
    693     for (n = 0; n <= ORDERHI; n++) {
    694       corrhiQQ[n] = WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQhi, corrhiQQ[n]); // Q(12+QdomHI-16) = Q(QdomHI-4)
    695     }
    696     QdomHI -= 4;
    697 
    698     /* add white noise floor */
    699     /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) */
    700     /* Calculate corrlo2[0] += 9.5367431640625e-7; and
    701        corrhi[0]  += 9.5367431640625e-7, where the constant is 1/2^20 */
    702 
    703     tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomLO-20);
    704     corrlo2QQ[0] += tmp32;
    705     tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomHI-20);
    706     corrhiQQ[0]  += tmp32;
    707 
    708     /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) before the following
    709        code segment, where we want to make sure we get a 1-bit margin */
    710     for (n = 0; n <= ORDERLO; n++) {
    711       corrlo2QQ[n] = WEBRTC_SPL_RSHIFT_W32(corrlo2QQ[n], 1); // Make sure we have a 1-bit margin
    712     }
    713     QdomLO -= 1; // Now, corrlo2QQ is in Q(QdomLO), with a 1-bit margin
    714 
    715     for (n = 0; n <= ORDERHI; n++) {
    716       corrhiQQ[n] = WEBRTC_SPL_RSHIFT_W32(corrhiQQ[n], 1); // Make sure we have a 1-bit margin
    717     }
    718     QdomHI -= 1; // Now, corrhiQQ is in Q(QdomHI), with a 1-bit margin
    719 
    720 
    721     newQdomLO = QdomLO;
    722 
    723     for (n = 0; n <= ORDERLO; n++) {
    724       int32_t tmp, tmpB, tmpCorr;
    725       int16_t alpha=328; //0.01 in Q15
    726       int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15
    727       int16_t gamma=32440; //(1-0.01)=0.99 in Q15
    728 
    729       if (maskdata->CorrBufLoQQ[n] != 0) {
    730         shMem=WebRtcSpl_NormW32(maskdata->CorrBufLoQQ[n]);
    731         sh = QdomLO - maskdata->CorrBufLoQdom[n];
    732         if (sh<=shMem) {
    733           tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], sh); // Get CorrBufLoQQ to same domain as corrlo2
    734           tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp);
    735         } else if ((sh-shMem)<7){
    736           tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufLoQQ as much as possible
    737           tmp = WEBRTC_SPL_MUL_16_32_RSFT15(WEBRTC_SPL_LSHIFT_W16(alpha, (sh-shMem)), tmp); // Shift alpha the number of times required to get tmp in QdomLO
    738         } else {
    739           tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
    740           tmp = WEBRTC_SPL_MUL_16_32_RSFT15(WEBRTC_SPL_LSHIFT_W16(alpha, 6), tmp); // Shift alpha as much as possible without overflow the number of times required to get tmp in QdomHI
    741           tmpCorr = WEBRTC_SPL_RSHIFT_W32(corrloQQ[n], sh-shMem-6);
    742           tmp = tmp + tmpCorr;
    743           maskdata->CorrBufLoQQ[n] = tmp;
    744           newQdomLO = QdomLO-(sh-shMem-6);
    745           maskdata->CorrBufLoQdom[n] = newQdomLO;
    746         }
    747       } else
    748         tmp = 0;
    749 
    750       tmp = tmp + corrlo2QQ[n];
    751 
    752       maskdata->CorrBufLoQQ[n] = tmp;
    753       maskdata->CorrBufLoQdom[n] = QdomLO;
    754 
    755       tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp);
    756       tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, corrlo2QQ[n]);
    757       corrlo2QQ[n] = tmp + tmpB;
    758     }
    759     if( newQdomLO!=QdomLO) {
    760       for (n = 0; n <= ORDERLO; n++) {
    761         if (maskdata->CorrBufLoQdom[n] != newQdomLO)
    762           corrloQQ[n] = WEBRTC_SPL_RSHIFT_W32(corrloQQ[n], maskdata->CorrBufLoQdom[n]-newQdomLO);
    763       }
    764       QdomLO = newQdomLO;
    765     }
    766 
    767 
    768     newQdomHI = QdomHI;
    769 
    770     for (n = 0; n <= ORDERHI; n++) {
    771       int32_t tmp, tmpB, tmpCorr;
    772       int16_t alpha=328; //0.01 in Q15
    773       int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15
    774       int16_t gamma=32440; //(1-0.01)=0.99 in Q1
    775       if (maskdata->CorrBufHiQQ[n] != 0) {
    776         shMem=WebRtcSpl_NormW32(maskdata->CorrBufHiQQ[n]);
    777         sh = QdomHI - maskdata->CorrBufHiQdom[n];
    778         if (sh<=shMem) {
    779           tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], sh); // Get CorrBufHiQQ to same domain as corrhi
    780           tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp);
    781           tmpCorr = corrhiQQ[n];
    782           tmp = tmp + tmpCorr;
    783           maskdata->CorrBufHiQQ[n] = tmp;
    784           maskdata->CorrBufHiQdom[n] = QdomHI;
    785         } else if ((sh-shMem)<7) {
    786           tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
    787           tmp = WEBRTC_SPL_MUL_16_32_RSFT15(WEBRTC_SPL_LSHIFT_W16(alpha, (sh-shMem)), tmp); // Shift alpha the number of times required to get tmp in QdomHI
    788           tmpCorr = corrhiQQ[n];
    789           tmp = tmp + tmpCorr;
    790           maskdata->CorrBufHiQQ[n] = tmp;
    791           maskdata->CorrBufHiQdom[n] = QdomHI;
    792         } else {
    793           tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible
    794           tmp = WEBRTC_SPL_MUL_16_32_RSFT15(WEBRTC_SPL_LSHIFT_W16(alpha, 6), tmp); // Shift alpha as much as possible without overflow the number of times required to get tmp in QdomHI
    795           tmpCorr = WEBRTC_SPL_RSHIFT_W32(corrhiQQ[n], sh-shMem-6);
    796           tmp = tmp + tmpCorr;
    797           maskdata->CorrBufHiQQ[n] = tmp;
    798           newQdomHI = QdomHI-(sh-shMem-6);
    799           maskdata->CorrBufHiQdom[n] = newQdomHI;
    800         }
    801       } else {
    802         tmp = corrhiQQ[n];
    803         tmpCorr = tmp;
    804         maskdata->CorrBufHiQQ[n] = tmp;
    805         maskdata->CorrBufHiQdom[n] = QdomHI;
    806       }
    807 
    808       tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp);
    809       tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, tmpCorr);
    810       corrhiQQ[n] = tmp + tmpB;
    811     }
    812 
    813     if( newQdomHI!=QdomHI) {
    814       for (n = 0; n <= ORDERHI; n++) {
    815         if (maskdata->CorrBufHiQdom[n] != newQdomHI)
    816           corrhiQQ[n] = WEBRTC_SPL_RSHIFT_W32(corrhiQQ[n], maskdata->CorrBufHiQdom[n]-newQdomHI);
    817       }
    818       QdomHI = newQdomHI;
    819     }
    820 
    821     stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, ORDERLO);
    822 
    823     if (stab<0) {  // If unstable use lower order
    824       a_LOQ11[0]=2048;
    825       for (n = 1; n <= ORDERLO; n++) {
    826         a_LOQ11[n]=0;
    827       }
    828 
    829       stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, 8);
    830     }
    831 
    832 
    833     WebRtcSpl_LevinsonDurbin(corrhiQQ,  a_HIQ12,  k_vechiQ15, ORDERHI);
    834 
    835     /* bandwidth expansion */
    836     for (n = 1; n <= ORDERLO; n++) {
    837       a_LOQ11[n] = (int16_t) ((WEBRTC_SPL_MUL_16_16(
    838           kPolyVecLo[n-1], a_LOQ11[n]) + ((int32_t) (1 << 14))) >> 15);
    839     }
    840 
    841 
    842     polyHI[0] = a_HIQ12[0];
    843     for (n = 1; n <= ORDERHI; n++) {
    844       a_HIQ12[n] = (int16_t) ((WEBRTC_SPL_MUL_16_16(
    845           kPolyVecHi[n-1], a_HIQ12[n]) + ((int32_t) (1 << 14))) >> 15);
    846       polyHI[n] = a_HIQ12[n];
    847     }
    848 
    849     /* Normalize the corrlo2 vector */
    850     sh = WebRtcSpl_NormW32(corrlo2QQ[0]);
    851     for (n = 0; n <= ORDERLO; n++) {
    852       corrlo2QQ[n] = WEBRTC_SPL_LSHIFT_W32(corrlo2QQ[n], sh);
    853     }
    854     QdomLO += sh; /* Now, corrlo2QQ is still in Q(QdomLO) */
    855 
    856 
    857     /* residual energy */
    858 
    859     sh_lo = 31;
    860     res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERLO, QdomLO,
    861         kShiftLowerBand, a_LOQ11, corrlo2QQ, &sh_lo);
    862 
    863     /* Convert to reflection coefficients */
    864     WebRtcSpl_AToK_JSK(a_LOQ11, ORDERLO, rcQ15_lo);
    865 
    866     if (sh_lo & 0x0001) {
    867       res_nrgQQ=WEBRTC_SPL_RSHIFT_W32(res_nrgQQ, 1);
    868       sh_lo-=1;
    869     }
    870 
    871 
    872     if( res_nrgQQ > 0 )
    873     {
    874       sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
    875 
    876       /* add hearing threshold and compute the gain */
    877       /* lo_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
    878 
    879 
    880       //tmp32a=WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, H_T_HQ19, 17);  // Q14
    881       tmp32a=WEBRTC_SPL_RSHIFT_W32((int32_t) varscaleQ14,1);  // H_T_HQ19=65536 (16-17=-1)   ssh= WEBRTC_SPL_RSHIFT_W16(sh_lo, 1);  // sqrt_nrg is in Qssh
    882       ssh= WEBRTC_SPL_RSHIFT_W16(sh_lo, 1);  // sqrt_nrg is in Qssh
    883       sh = ssh - 14;
    884       tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
    885       tmp32c = sqrt_nrg + tmp32b;  // Qssh  (denominator)
    886       tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, snrq, 0);  //Q24 (numerator)
    887 
    888       sh = WebRtcSpl_NormW32(tmp32c);
    889       shft = 16 - sh;
    890       tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft)  (denominator)
    891 
    892       tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
    893       sh = ssh-shft-7;
    894       *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh);  // Gains in Q17
    895     }
    896     else
    897     {
    898       *gain_lo_hiQ17 = 100; //(int32_t)WEBRTC_SPL_LSHIFT_W32( (int32_t)1, 17);  // Gains in Q17
    899     }
    900     gain_lo_hiQ17++;
    901 
    902     /* copy coefficients to output array */
    903     for (n = 0; n < ORDERLO; n++) {
    904       *lo_coeffQ15 = (int16_t) (rcQ15_lo[n]);
    905       lo_coeffQ15++;
    906     }
    907     /* residual energy */
    908     sh_hi = 31;
    909     res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERHI, QdomHI,
    910         kShiftHigherBand, a_HIQ12, corrhiQQ, &sh_hi);
    911 
    912     /* Convert to reflection coefficients */
    913     WebRtcSpl_LpcToReflCoef(polyHI, ORDERHI, rcQ15_hi);
    914 
    915     if (sh_hi & 0x0001) {
    916       res_nrgQQ=WEBRTC_SPL_RSHIFT_W32(res_nrgQQ, 1);
    917       sh_hi-=1;
    918     }
    919 
    920 
    921     if( res_nrgQQ > 0 )
    922     {
    923       sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
    924 
    925 
    926       /* add hearing threshold and compute the gain */
    927       /* hi_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
    928 
    929       //tmp32a=WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, H_T_HQ19, 17);  // Q14
    930       tmp32a=WEBRTC_SPL_RSHIFT_W32((int32_t) varscaleQ14,1);  // H_T_HQ19=65536 (16-17=-1)
    931 
    932       ssh= WEBRTC_SPL_RSHIFT_W32(sh_hi, 1);  // sqrt_nrg is in Qssh
    933       sh = ssh - 14;
    934       tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
    935       tmp32c = sqrt_nrg + tmp32b;  // Qssh  (denominator)
    936       tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, snrq, 0);  //Q24 (numerator)
    937 
    938       sh = WebRtcSpl_NormW32(tmp32c);
    939       shft = 16 - sh;
    940       tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft)  (denominator)
    941 
    942       tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
    943       sh = ssh-shft-7;
    944       *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh);  // Gains in Q17
    945     }
    946     else
    947     {
    948       *gain_lo_hiQ17 = 100; //(int32_t)WEBRTC_SPL_LSHIFT_W32( (int32_t)1, 17);  // Gains in Q17
    949     }
    950     gain_lo_hiQ17++;
    951 
    952 
    953     /* copy coefficients to output array */
    954     for (n = 0; n < ORDERHI; n++) {
    955       *hi_coeffQ15 = rcQ15_hi[n];
    956       hi_coeffQ15++;
    957     }
    958   }
    959 }
    960