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     WebRtc_Word16 *a16, /* Q11 */
     28     WebRtc_Word16 useOrder,
     29     WebRtc_Word16 *k16  /* Q15 */
     30                         )
     31 {
     32   int m, k;
     33   WebRtc_Word32 tmp32[MAX_AR_MODEL_ORDER];
     34   WebRtc_Word32 tmp32b;
     35   WebRtc_Word32 tmp_inv_denum32;
     36   WebRtc_Word16 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 = ((WebRtc_Word32) 1073741823) - WEBRTC_SPL_MUL_16_16(k16[m], k16[m]); // (1 - k^2) in Q30
     42     tmp_inv_denum16 = (WebRtc_Word16) 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((WebRtc_Word32)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] = (WebRtc_Word16) 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] = (WebRtc_Word16) WEBRTC_SPL_LSHIFT_W32(tmp32[m], 3); //Q12<<3 => Q15
     57   }
     58 
     59   return;
     60 }
     61 
     62 
     63 
     64 
     65 
     66 WebRtc_Word16 WebRtcSpl_LevinsonW32_JSK(
     67     WebRtc_Word32 *R,  /* (i) Autocorrelation of length >= order+1 */
     68     WebRtc_Word16 *A,  /* (o) A[0..order] LPC coefficients (Q11) */
     69     WebRtc_Word16 *K,  /* (o) K[0...order-1] Reflection coefficients (Q15) */
     70     WebRtc_Word16 order /* (i) filter order */
     71                                         ) {
     72   WebRtc_Word16 i, j;
     73   WebRtc_Word16 R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1];
     74   /* Aurocorr coefficients in high precision */
     75   WebRtc_Word16 A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1];
     76   /* LPC coefficients in high precicion */
     77   WebRtc_Word16 A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1];
     78   /* LPC coefficients for next iteration */
     79   WebRtc_Word16 K_hi, K_low;      /* reflection coefficient in high precision */
     80   WebRtc_Word16 Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision
     81                                                    and with scale factor */
     82   WebRtc_Word16 tmp_hi, tmp_low;
     83   WebRtc_Word32 temp1W32, temp2W32, temp3W32;
     84   WebRtc_Word16 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] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
     94     R_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16)), 1);
     95   }
     96 
     97   /* K = A[1] = -R[1] / R[0] */
     98 
     99   temp2W32  = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[1],16) +
    100       WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    110   K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    119   A_low[1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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 = (WebRtc_Word32)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 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    131   tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    143   Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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((WebRtc_Word32)R_hi[i], 16) +
    170                  WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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 = (WebRtc_Word32)0x7fffffffL;
    189       } else
    190       {
    191         temp3W32 = (WebRtc_Word32)0x80000000L;
    192       }
    193     }
    194 
    195     /* Put K on hi and low format */
    196     K_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
    197     K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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 ((WebRtc_Word32)WEBRTC_SPL_ABS_W16(K_hi) > (WebRtc_Word32)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((WebRtc_Word32)A_hi[j],16) +
    219           WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    227       A_upd_low[j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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] = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
    234     A_upd_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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 = (WebRtc_Word32)0x7fffffffL - temp1W32;      /* 1 - K*K  in Q31 */
    243 
    244     /* Convert 1- K^2 in hi and low format */
    245     tmp_hi = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    246     tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
    259     Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32 - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)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((WebRtc_Word32)A_hi[i], 16) +
    283         WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[i], 1);
    284     /* Round and store upper word */
    285     A[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32+(WebRtc_Word32)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 WebRtc_Word16 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 WebRtc_Word16 kPolyVecLo[12] = {
    341   29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425, 10283, 9255
    342 };
    343 static const WebRtc_Word16 kPolyVecHi[6] = {
    344   26214, 20972, 16777, 13422, 10737, 8590
    345 };
    346 
    347 static __inline WebRtc_Word32 log2_Q8_LPC( WebRtc_UWord32 x ) {
    348 
    349   WebRtc_Word32 zeros, lg2;
    350   WebRtc_Word16 frac;
    351 
    352   zeros=WebRtcSpl_NormU32(x);
    353   frac=(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(((WebRtc_UWord32)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 WebRtc_Word16 kMulPitchGain = -25; /* 200/256 in Q5 */
    363 static const WebRtc_Word16 kChngFactor = 3523; /* log10(2)*10/4*0.4/1.4=log10(2)/1.4= 0.2150 in Q14 */
    364 static const WebRtc_Word16 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 WebRtc_Word16 *input, const WebRtc_Word16 *pitchGains_Q12,
    369                            WebRtc_UWord32 *oldEnergy, WebRtc_Word16 *varscale)
    370 {
    371   int k;
    372   WebRtc_UWord32 nrgQ[4];
    373   WebRtc_Word16 nrgQlog[4];
    374   WebRtc_Word16 tmp16, chng1, chng2, chng3, chng4, tmp, chngQ, oldNrgQlog, pgQ, pg3;
    375   WebRtc_Word32 expPg32;
    376   WebRtc_Word16 expPg, divVal;
    377   WebRtc_Word16 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] = (WebRtc_Word16)log2_Q8_LPC(nrgQ[k]); /* log2(nrgQ) */
    399   }
    400   oldNrgQlog = (WebRtc_Word16)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 = (WebRtc_Word16)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 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(pgQ, pgQ,11); /* pgQ in Q(12+2)=Q14. Q14*Q14>>11 => Q17 */
    419   pg3 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(pgQ, pg3,13); /* Q17*Q14>>13 =>Q18  */
    420   pg3 = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(pg3, kMulPitchGain ,5); /* Q10  kMulPitchGain = -25 = -200 in Q-3. */
    421 
    422   tmp16=(WebRtc_Word16)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((WebRtc_UWord16)(tmp16 ^ 0xFFFF), 10)-3); /* Gives result in Q14 */
    426     if (tmp16_1<0)
    427       expPg=(WebRtc_Word16) -WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
    428     else
    429       expPg=(WebRtc_Word16) -WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
    430   } else
    431     expPg = (WebRtc_Word16) -16384; /* 1 in Q14, since 2^0=1 */
    432 
    433   expPg32 = (WebRtc_Word32)WEBRTC_SPL_LSHIFT_W16((WebRtc_Word32)expPg, 8); /* Q22 */
    434   divVal = WebRtcSpl_DivW32W16ResW16(expPg32, chngQ); /* Q22/Q12=Q10 */
    435 
    436   tmp16=(WebRtc_Word16)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((WebRtc_UWord16)(tmp16 ^ 0xFFFF), 10)-3); /* Gives result in Q14 */
    440     if (tmp16_1<0)
    441       expPg=(WebRtc_Word16) WEBRTC_SPL_LSHIFT_W16(tmp16_2, -tmp16_1);
    442     else
    443       expPg=(WebRtc_Word16) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
    444   } else
    445     expPg = (WebRtc_Word16) 16384; /* 1 in Q14, since 2^0=1 */
    446 
    447   *varscale = expPg-1;
    448   *oldEnergy = nrgQ[3];
    449 }
    450 
    451 
    452 
    453 static __inline WebRtc_Word16  exp2_Q10_T(WebRtc_Word16 x) { // Both in and out in Q10
    454 
    455   WebRtc_Word16 tmp16_1, tmp16_2;
    456 
    457   tmp16_2=(WebRtc_Word16)(0x0400|(x&0x03FF));
    458   tmp16_1=-(WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(x,10);
    459   if(tmp16_1>0)
    460     return (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W16(tmp16_2, tmp16_1);
    461   else
    462     return (WebRtc_Word16) 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(WebRtc_Word16 *inLoQ0,
    542                               WebRtc_Word16 *inHiQ0,
    543                               MaskFiltstr_enc *maskdata,
    544                               WebRtc_Word16 snrQ10,
    545                               const WebRtc_Word16 *pitchGains_Q12,
    546                               WebRtc_Word32 *gain_lo_hiQ17,
    547                               WebRtc_Word16 *lo_coeffQ15,
    548                               WebRtc_Word16 *hi_coeffQ15)
    549 {
    550   int k, n, ii;
    551   int pos1, pos2;
    552   int sh_lo, sh_hi, sh, ssh, shMem;
    553   WebRtc_Word16 varscaleQ14;
    554 
    555   WebRtc_Word16 tmpQQlo, tmpQQhi;
    556   WebRtc_Word32 tmp32;
    557   WebRtc_Word16 tmp16,tmp16b;
    558 
    559   WebRtc_Word16 polyHI[ORDERHI+1];
    560   WebRtc_Word16 rcQ15_lo[ORDERLO], rcQ15_hi[ORDERHI];
    561 
    562 
    563   WebRtc_Word16 DataLoQ6[WINLEN], DataHiQ6[WINLEN];
    564   WebRtc_Word32 corrloQQ[ORDERLO+2];
    565   WebRtc_Word32 corrhiQQ[ORDERHI+1];
    566   WebRtc_Word32 corrlo2QQ[ORDERLO+1];
    567   WebRtc_Word16 scale;
    568   WebRtc_Word16 QdomLO, QdomHI, newQdomHI, newQdomLO;
    569 
    570   WebRtc_Word32 res_nrgQQ;
    571   WebRtc_Word32 sqrt_nrg;
    572 
    573   /* less-noise-at-low-frequencies factor */
    574   WebRtc_Word16 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   WebRtc_Word16 snrq;
    580   int shft;
    581 
    582   WebRtc_Word16 tmp16a;
    583   WebRtc_Word32 tmp32a, tmp32b, tmp32c;
    584 
    585   WebRtc_Word16 a_LOQ11[ORDERLO+1];
    586   WebRtc_Word16 k_vecloQ15[ORDERLO];
    587   WebRtc_Word16 a_HIQ12[ORDERHI+1];
    588   WebRtc_Word16 k_vechiQ15[ORDERHI];
    589 
    590   WebRtc_Word16 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 = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(snrq, 172, 10); // Q10
    596   tmp16b = exp2_Q10_T(tmp16); // Q10
    597   snrq = (WebRtc_Word16) 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 = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(
    608       (WEBRTC_SPL_MUL_16_16(22938, (8192 + WEBRTC_SPL_RSHIFT_W32(varscaleQ14, 1)))
    609        + ((WebRtc_Word32)32768)), 16);
    610 
    611   /* Calculate tmp = (1.0 + aa*aa); in Q12 */
    612   tmp16 = (WebRtc_Word16) 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 = (WebRtc_Word16) 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] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(
    631           maskdata->DataBufferLoQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
    632       DataHiQ6[pos1] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(
    633           maskdata->DataBufferHiQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
    634     }
    635     pos2 = (WebRtc_Word16)(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] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT(
    640           maskdata->DataBufferLoQ0[pos1], kWindowAutocorr[pos1], 15); // Q0*Q21>>15 = Q6
    641       DataHiQ6[pos1] = (WebRtc_Word16) 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((WebRtc_Word32) 1, QdomLO-20);
    704     corrlo2QQ[0] += tmp32;
    705     tmp32 = WEBRTC_SPL_SHIFT_W32((WebRtc_Word32) 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       WebRtc_Word32 tmp, tmpB, tmpCorr;
    725       WebRtc_Word16 alpha=328; //0.01 in Q15
    726       WebRtc_Word16 beta=324; //(1-0.01)*0.01=0.0099 in Q15
    727       WebRtc_Word16 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       WebRtc_Word32 tmp, tmpB, tmpCorr;
    772       WebRtc_Word16 alpha=328; //0.01 in Q15
    773       WebRtc_Word16 beta=324; //(1-0.01)*0.01=0.0099 in Q15
    774       WebRtc_Word16 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] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT_WITH_FIXROUND(kPolyVecLo[n-1], a_LOQ11[n]);
    838     }
    839 
    840 
    841     polyHI[0] = a_HIQ12[0];
    842     for (n = 1; n <= ORDERHI; n++) {
    843       a_HIQ12[n] = (WebRtc_Word16) WEBRTC_SPL_MUL_16_16_RSFT_WITH_FIXROUND(kPolyVecHi[n-1], a_HIQ12[n]);
    844       polyHI[n] = a_HIQ12[n];
    845     }
    846 
    847     /* Normalize the corrlo2 vector */
    848     sh = WebRtcSpl_NormW32(corrlo2QQ[0]);
    849     for (n = 0; n <= ORDERLO; n++) {
    850       corrlo2QQ[n] = WEBRTC_SPL_LSHIFT_W32(corrlo2QQ[n], sh);
    851     }
    852     QdomLO += sh; /* Now, corrlo2QQ is still in Q(QdomLO) */
    853 
    854 
    855     /* residual energy */
    856 
    857     sh_lo = 31;
    858     res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERLO, QdomLO,
    859         kShiftLowerBand, a_LOQ11, corrlo2QQ, &sh_lo);
    860 
    861     /* Convert to reflection coefficients */
    862     WebRtcSpl_AToK_JSK(a_LOQ11, ORDERLO, rcQ15_lo);
    863 
    864     if (sh_lo & 0x0001) {
    865       res_nrgQQ=WEBRTC_SPL_RSHIFT_W32(res_nrgQQ, 1);
    866       sh_lo-=1;
    867     }
    868 
    869 
    870     if( res_nrgQQ > 0 )
    871     {
    872       sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
    873 
    874       /* add hearing threshold and compute the gain */
    875       /* lo_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
    876 
    877 
    878       //tmp32a=WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, H_T_HQ19, 17);  // Q14
    879       tmp32a=WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32) varscaleQ14,1);  // H_T_HQ19=65536 (16-17=-1)   ssh= WEBRTC_SPL_RSHIFT_W16(sh_lo, 1);  // sqrt_nrg is in Qssh
    880       ssh= WEBRTC_SPL_RSHIFT_W16(sh_lo, 1);  // sqrt_nrg is in Qssh
    881       sh = ssh - 14;
    882       tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
    883       tmp32c = sqrt_nrg + tmp32b;  // Qssh  (denominator)
    884       tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, snrq, 0);  //Q24 (numerator)
    885 
    886       sh = WebRtcSpl_NormW32(tmp32c);
    887       shft = 16 - sh;
    888       tmp16a = (WebRtc_Word16) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft)  (denominator)
    889 
    890       tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
    891       sh = ssh-shft-7;
    892       *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh);  // Gains in Q17
    893     }
    894     else
    895     {
    896       *gain_lo_hiQ17 = 100; //(WebRtc_Word32)WEBRTC_SPL_LSHIFT_W32( (WebRtc_Word32)1, 17);  // Gains in Q17
    897     }
    898     gain_lo_hiQ17++;
    899 
    900     /* copy coefficients to output array */
    901     for (n = 0; n < ORDERLO; n++) {
    902       *lo_coeffQ15 = (WebRtc_Word16) (rcQ15_lo[n]);
    903       lo_coeffQ15++;
    904     }
    905     /* residual energy */
    906     sh_hi = 31;
    907     res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERHI, QdomHI,
    908         kShiftHigherBand, a_HIQ12, corrhiQQ, &sh_hi);
    909 
    910     /* Convert to reflection coefficients */
    911     WebRtcSpl_LpcToReflCoef(polyHI, ORDERHI, rcQ15_hi);
    912 
    913     if (sh_hi & 0x0001) {
    914       res_nrgQQ=WEBRTC_SPL_RSHIFT_W32(res_nrgQQ, 1);
    915       sh_hi-=1;
    916     }
    917 
    918 
    919     if( res_nrgQQ > 0 )
    920     {
    921       sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ);
    922 
    923 
    924       /* add hearing threshold and compute the gain */
    925       /* hi_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */
    926 
    927       //tmp32a=WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, H_T_HQ19, 17);  // Q14
    928       tmp32a=WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32) varscaleQ14,1);  // H_T_HQ19=65536 (16-17=-1)
    929 
    930       ssh= WEBRTC_SPL_RSHIFT_W32(sh_hi, 1);  // sqrt_nrg is in Qssh
    931       sh = ssh - 14;
    932       tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh
    933       tmp32c = sqrt_nrg + tmp32b;  // Qssh  (denominator)
    934       tmp32a = WEBRTC_SPL_MUL_16_16_RSFT(varscaleQ14, snrq, 0);  //Q24 (numerator)
    935 
    936       sh = WebRtcSpl_NormW32(tmp32c);
    937       shft = 16 - sh;
    938       tmp16a = (WebRtc_Word16) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft)  (denominator)
    939 
    940       tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft)
    941       sh = ssh-shft-7;
    942       *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh);  // Gains in Q17
    943     }
    944     else
    945     {
    946       *gain_lo_hiQ17 = 100; //(WebRtc_Word32)WEBRTC_SPL_LSHIFT_W32( (WebRtc_Word32)1, 17);  // Gains in Q17
    947     }
    948     gain_lo_hiQ17++;
    949 
    950 
    951     /* copy coefficients to output array */
    952     for (n = 0; n < ORDERHI; n++) {
    953       *hi_coeffQ15 = rcQ15_hi[n];
    954       hi_coeffQ15++;
    955     }
    956   }
    957 }
    958