16f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/*
26f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
36f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
46f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  Use of this source code is governed by a BSD-style license
56f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  that can be found in the LICENSE file in the root of the source
66f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  tree. An additional intellectual property rights grant can be found
76f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  in the file PATENTS.  All contributing project authors may
86f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  be found in the AUTHORS file in the root of the source tree.
96f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include "lpc_analysis.h"
126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include "settings.h"
136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include "codec.h"
146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include "entropy_coding.h"
156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include <math.h>
176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#include <string.h>
186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin#define LEVINSON_EPS    1.0e-10
206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/* window */
236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/* Matlab generation code:
246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid;
256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *  for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end
266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinstatic const double kLpcCorrWindow[WINLEN] = {
286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00000000, 0.00000001, 0.00000004, 0.00000010, 0.00000020,
296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00000035, 0.00000055, 0.00000083, 0.00000118, 0.00000163,
306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00000218, 0.00000283, 0.00000361, 0.00000453, 0.00000558, 0.00000679,
316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00000817, 0.00000973, 0.00001147, 0.00001342, 0.00001558,
326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00001796, 0.00002058, 0.00002344, 0.00002657, 0.00002997,
336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00003365, 0.00003762, 0.00004190, 0.00004651, 0.00005144, 0.00005673,
346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00006236, 0.00006837, 0.00007476, 0.00008155, 0.00008875,
356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00009636, 0.00010441, 0.00011290, 0.00012186, 0.00013128,
366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00014119, 0.00015160, 0.00016252, 0.00017396, 0.00018594, 0.00019846,
376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00021155, 0.00022521, 0.00023946, 0.00025432, 0.00026978,
386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00028587, 0.00030260, 0.00031998, 0.00033802, 0.00035674,
396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00037615, 0.00039626, 0.00041708, 0.00043863, 0.00046092, 0.00048396,
406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00050775, 0.00053233, 0.00055768, 0.00058384, 0.00061080,
416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00063858, 0.00066720, 0.00069665, 0.00072696, 0.00075813,
426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00079017, 0.00082310, 0.00085692, 0.00089164, 0.00092728, 0.00096384,
436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00100133, 0.00103976, 0.00107914, 0.00111947, 0.00116077,
446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00120304, 0.00124630, 0.00129053, 0.00133577, 0.00138200,
456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00142924, 0.00147749, 0.00152676, 0.00157705, 0.00162836, 0.00168070,
466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00173408, 0.00178850, 0.00184395, 0.00190045, 0.00195799,
476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00201658, 0.00207621, 0.00213688, 0.00219860, 0.00226137,
486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00232518, 0.00239003, 0.00245591, 0.00252284, 0.00259079, 0.00265977,
496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00272977, 0.00280078, 0.00287280, 0.00294582, 0.00301984,
506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00309484, 0.00317081, 0.00324774, 0.00332563, 0.00340446,
516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00348421, 0.00356488, 0.00364644, 0.00372889, 0.00381220, 0.00389636,
526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00398135, 0.00406715, 0.00415374, 0.00424109, 0.00432920,
536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00441802, 0.00450754, 0.00459773, 0.00468857, 0.00478001,
546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00487205, 0.00496464, 0.00505775, 0.00515136, 0.00524542, 0.00533990,
556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00543476, 0.00552997, 0.00562548, 0.00572125, 0.00581725,
566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00591342, 0.00600973, 0.00610612, 0.00620254, 0.00629895,
576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00639530, 0.00649153, 0.00658758, 0.00668341, 0.00677894, 0.00687413,
586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00696891, 0.00706322, 0.00715699, 0.00725016, 0.00734266,
596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00743441, 0.00752535, 0.00761540, 0.00770449, 0.00779254,
606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00787947, 0.00796519, 0.00804963, 0.00813270, 0.00821431, 0.00829437,
616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00837280, 0.00844949, 0.00852436, 0.00859730, 0.00866822,
626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00873701, 0.00880358, 0.00886781, 0.00892960, 0.00898884,
636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00904542, 0.00909923, 0.00915014, 0.00919805, 0.00924283, 0.00928436,
646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00932252, 0.00935718, 0.00938821, 0.00941550, 0.00943890,
656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00945828, 0.00947351, 0.00948446, 0.00949098, 0.00949294,
666f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00949020, 0.00948262, 0.00947005, 0.00945235, 0.00942938, 0.00940099,
676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00936704, 0.00932738, 0.00928186, 0.00923034, 0.00917268,
686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00910872, 0.00903832, 0.00896134, 0.00887763, 0.00878706,
696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00868949, 0.00858478, 0.00847280, 0.00835343, 0.00822653, 0.00809199,
706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00794970, 0.00779956, 0.00764145, 0.00747530, 0.00730103,
716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00711857, 0.00692787, 0.00672888, 0.00652158, 0.00630597,
726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00608208, 0.00584994, 0.00560962, 0.00536124, 0.00510493, 0.00484089,
736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00456935, 0.00429062, 0.00400505, 0.00371310, 0.00341532,
746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00311238, 0.00280511, 0.00249452, 0.00218184, 0.00186864,
756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  0.00155690, 0.00124918, 0.00094895, 0.00066112, 0.00039320, 0.00015881
766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin};
776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkindouble WebRtcIsac_LevDurb(double *a, double *k, double *r, int order)
796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin{
806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double  sum, alpha;
826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int     m, m_h, i;
836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  alpha = 0; //warning -DH
846f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  a[0] = 1.0;
856f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  if (r[0] < LEVINSON_EPS) { /* if r[0] <= 0, set LPC coeff. to zero */
866f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (i = 0; i < order; i++) {
876f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      k[i] = 0;
886f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      a[i+1] = 0;
896f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
906f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  } else {
916f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    a[1] = k[0] = -r[1]/r[0];
926f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    alpha = r[0] + r[1] * k[0];
936f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (m = 1; m < order; m++){
946f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      sum = r[m + 1];
956f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (i = 0; i < m; i++){
966f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        sum += a[i+1] * r[m - i];
976f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
986f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      k[m] = -sum / alpha;
996f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      alpha += k[m] * sum;
1006f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      m_h = (m + 1) >> 1;
1016f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (i = 0; i < m_h; i++){
1026f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        sum = a[i+1] + k[m] * a[m - i];
1036f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        a[m - i] += k[m] * a[i+1];
1046f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        a[i+1] = sum;
1056f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
1066f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      a[m+1] = k[m];
1076f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
1086f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1096f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  return alpha;
1106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
1116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin//was static before, but didn't work with MEX file
1146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid WebRtcIsac_GetVars(const double *input, const WebRtc_Word16 *pitchGains_Q12,
1156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                       double *oldEnergy, double *varscale)
1166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin{
1176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double nrg[4], chng, pg;
1186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int k;
1196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double pitchGains[4]={0,0,0,0};;
1216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Calculate energies of first and second frame halfs */
1236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  nrg[0] = 0.0001;
1246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES_QUARTER + QLOOKAHEAD) / 2; k++) {
1256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    nrg[0] += input[k]*input[k];
1266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  nrg[1] = 0.0001;
1286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for ( ; k < (FRAMESAMPLES_HALF + QLOOKAHEAD) / 2; k++) {
1296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    nrg[1] += input[k]*input[k];
1306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  nrg[2] = 0.0001;
1326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for ( ; k < (FRAMESAMPLES*3/4 + QLOOKAHEAD) / 2; k++) {
1336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    nrg[2] += input[k]*input[k];
1346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  nrg[3] = 0.0001;
1366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
1376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    nrg[3] += input[k]*input[k];
1386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Calculate average level change */
1416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
1426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                 fabs(10.0 * log10(nrg[2] / nrg[1])) +
1436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                 fabs(10.0 * log10(nrg[1] / nrg[0])) +
1446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                 fabs(10.0 * log10(nrg[0] / *oldEnergy)));
1456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Find average pitch gain */
1486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  pg = 0.0;
1496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for (k=0; k<4; k++)
1506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  {
1516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    pitchGains[k] = ((float)pitchGains_Q12[k])/4096;
1526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    pg += pitchGains[k];
1536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  pg *= 0.25;
1556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* If pitch gain is low and energy constant - increase noise level*/
1576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Matlab code:
1586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
1596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  */
1606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  *varscale = 0.0 + 1.0 * exp( -1.4 * exp(-200.0 * pg*pg*pg) / (1.0 + 0.4 * chng) );
1616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  *oldEnergy = nrg[3];
1636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
1646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid
1666f12fff925188ced26e518cd2252aff3e93bb04eAlexander GutkinWebRtcIsac_GetVarsUB(
1676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    const double* input,
1686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double*       oldEnergy,
1696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double*       varscale)
1706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin{
1716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double nrg[4], chng;
1726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int k;
1736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Calculate energies of first and second frame halfs */
1756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  nrg[0] = 0.0001;
1766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for (k = 0; k < (FRAMESAMPLES_QUARTER) / 2; k++) {
1776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    nrg[0] += input[k]*input[k];
1786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  nrg[1] = 0.0001;
1806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for ( ; k < (FRAMESAMPLES_HALF) / 2; k++) {
1816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    nrg[1] += input[k]*input[k];
1826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  nrg[2] = 0.0001;
1846f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for ( ; k < (FRAMESAMPLES*3/4) / 2; k++) {
1856f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    nrg[2] += input[k]*input[k];
1866f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1876f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  nrg[3] = 0.0001;
1886f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for ( ; k < (FRAMESAMPLES) / 2; k++) {
1896f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    nrg[3] += input[k]*input[k];
1906f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
1916f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1926f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Calculate average level change */
1936f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
1946f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                 fabs(10.0 * log10(nrg[2] / nrg[1])) +
1956f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                 fabs(10.0 * log10(nrg[1] / nrg[0])) +
1966f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                 fabs(10.0 * log10(nrg[0] / *oldEnergy)));
1976f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1986f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
1996f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* If pitch gain is low and energy constant - increase noise level*/
2006f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* Matlab code:
2016f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin     pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
2026f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  */
2036f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  *varscale = exp( -1.4 / (1.0 + 0.4 * chng) );
2046f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2056f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  *oldEnergy = nrg[3];
2066f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
2076f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2086f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid WebRtcIsac_GetLpcCoefLb(double *inLo, double *inHi, MaskFiltstr *maskdata,
2096f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                             double signal_noise_ratio, const WebRtc_Word16 *pitchGains_Q12,
2106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                             double *lo_coeff, double *hi_coeff)
2116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin{
2126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int k, n, j, pos1, pos2;
2136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double varscale;
2146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double DataLo[WINLEN], DataHi[WINLEN];
2166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double corrlo[ORDERLO+2], corrlo2[ORDERLO+1];
2176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double corrhi[ORDERHI+1];
2186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double k_veclo[ORDERLO], k_vechi[ORDERHI];
2196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double a_LO[ORDERLO+1], a_HI[ORDERHI+1];
2216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double tmp, res_nrg;
2226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double FwdA, FwdB;
2246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* hearing threshold level in dB; higher value gives more noise */
2266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double HearThresOffset = -28.0;
2276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* bandwdith expansion factors for low- and high band */
2296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double gammaLo = 0.9;
2306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double gammaHi = 0.8;
2316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* less-noise-at-low-frequencies factor */
2336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double aa;
2346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* convert from dB to signal level */
2376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
2386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46;    /* divide by sqrt(12) */
2396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* change quallevel depending on pitch gains and level fluctuations */
2416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  WebRtcIsac_GetVars(inLo, pitchGains_Q12, &(maskdata->OldEnergy), &varscale);
2426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* less-noise-at-low-frequencies factor */
2446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  aa = 0.35 * (0.5 + 0.5 * varscale);
2456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* replace data in buffer by new look-ahead data */
2476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++)
2486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    maskdata->DataBufferLo[pos1 + WINLEN - QLOOKAHEAD] = inLo[pos1];
2496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for (k = 0; k < SUBFRAMES; k++) {
2516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Update input buffer and multiply signal with window */
2536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
2546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 + UPDATE/2];
2556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      maskdata->DataBufferHi[pos1] = maskdata->DataBufferHi[pos1 + UPDATE/2];
2566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
2576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
2586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    pos2 = k * UPDATE/2;
2606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 0; n < UPDATE/2; n++, pos1++) {
2616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      maskdata->DataBufferLo[pos1] = inLo[QLOOKAHEAD + pos2];
2626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      maskdata->DataBufferHi[pos1] = inHi[pos2++];
2636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
2646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
2656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2666f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Get correlation coefficients */
2686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    WebRtcIsac_AutoCorr(corrlo, DataLo, WINLEN, ORDERLO+1); /* computing autocorrelation */
2696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    WebRtcIsac_AutoCorr(corrhi, DataHi, WINLEN, ORDERHI);
2706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
2736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    corrlo2[0] = (1.0+aa*aa) * corrlo[0] - 2.0*aa * corrlo[1];
2746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    tmp = (1.0 + aa*aa);
2756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 1; n <= ORDERLO; n++) {
2766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      corrlo2[n] = tmp * corrlo[n] - aa * (corrlo[n-1] + corrlo[n+1]);
2776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    tmp = (1.0+aa) * (1.0+aa);
2796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 0; n <= ORDERHI; n++) {
2806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      corrhi[n] = tmp * corrhi[n];
2816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* add white noise floor */
2846f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    corrlo2[0] += 1e-6;
2856f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    corrhi[0] += 1e-6;
2866f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2876f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2886f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    FwdA = 0.01;
2896f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    FwdB = 0.01;
2906f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
2916f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* recursive filtering of correlation over subframes */
2926f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 0; n <= ORDERLO; n++) {
2936f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      maskdata->CorrBufLo[n] = FwdA * maskdata->CorrBufLo[n] + corrlo2[n];
2946f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      corrlo2[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufLo[n] + (1.0-FwdB) * corrlo2[n];
2956f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
2966f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 0; n <= ORDERHI; n++) {
2976f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      maskdata->CorrBufHi[n] = FwdA * maskdata->CorrBufHi[n] + corrhi[n];
2986f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      corrhi[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufHi[n] + (1.0-FwdB) * corrhi[n];
2996f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3006f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3016f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* compute prediction coefficients */
3026f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    WebRtcIsac_LevDurb(a_LO, k_veclo, corrlo2, ORDERLO);
3036f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    WebRtcIsac_LevDurb(a_HI, k_vechi, corrhi, ORDERHI);
3046f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3056f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* bandwidth expansion */
3066f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    tmp = gammaLo;
3076f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 1; n <= ORDERLO; n++) {
3086f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      a_LO[n] *= tmp;
3096f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      tmp *= gammaLo;
3106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* residual energy */
3136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    res_nrg = 0.0;
3146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (j = 0; j <= ORDERLO; j++) {
3156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (n = 0; n <= j; n++) {
3166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        res_nrg += a_LO[j] * corrlo2[j-n] * a_LO[n];
3176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
3186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (n = j+1; n <= ORDERLO; n++) {
3196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        res_nrg += a_LO[j] * corrlo2[n-j] * a_LO[n];
3206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
3216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* add hearing threshold and compute the gain */
3246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    *lo_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
3256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* copy coefficients to output array */
3276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 1; n <= ORDERLO; n++) {
3286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      *lo_coeff++ = a_LO[n];
3296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* bandwidth expansion */
3336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    tmp = gammaHi;
3346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 1; n <= ORDERHI; n++) {
3356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      a_HI[n] *= tmp;
3366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      tmp *= gammaHi;
3376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* residual energy */
3406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    res_nrg = 0.0;
3416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (j = 0; j <= ORDERHI; j++) {
3426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (n = 0; n <= j; n++) {
3436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        res_nrg += a_HI[j] * corrhi[j-n] * a_HI[n];
3446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
3456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (n = j+1; n <= ORDERHI; n++) {
3466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        res_nrg += a_HI[j] * corrhi[n-j] * a_HI[n];
3476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
3486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* add hearing threshold and compute of the gain */
3516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    *hi_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
3526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* copy coefficients to output array */
3546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for (n = 1; n <= ORDERHI; n++) {
3556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      *hi_coeff++ = a_HI[n];
3566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
3576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
3586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
3596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
3626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/******************************************************************************
3636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * WebRtcIsac_GetLpcCoefUb()
3646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
3656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Compute LP coefficients and correlation coefficients. At 12 kHz LP
3666f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * coefficients of the first and the last sub-frame is computed. At 16 kHz
3676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * LP coefficients of 4th, 8th and 12th sub-frames are computed. We always
3686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * compute correlation coefficients of all sub-frames.
3696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
3706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Inputs:
3716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -inSignal           : Input signal
3726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -maskdata           : a structure keeping signal from previous frame.
3736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -bandwidth          : specifies if the codec is in 0-16 kHz mode or
3746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                             0-12 kHz mode.
3756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
3766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Outputs:
3776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -lpCoeff            : pointer to a buffer where A-polynomials are
3786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                             written to (first coeff is 1 and it is not
3796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                             written)
3806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -corrMat            : a matrix where correlation coefficients of each
3816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                             sub-frame are written to one row.
3826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -varscale           : a scale used to compute LPC gains.
3836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
3846f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid
3856f12fff925188ced26e518cd2252aff3e93bb04eAlexander GutkinWebRtcIsac_GetLpcCoefUb(
3866f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double*      inSignal,
3876f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    MaskFiltstr* maskdata,
3886f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double*      lpCoeff,
3896f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double       corrMat[][UB_LPC_ORDER + 1],
3906f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double*      varscale,
3916f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    WebRtc_Word16  bandwidth)
3926f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin{
3936f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  int frameCntr, activeFrameCntr, n, pos1, pos2;
3946f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  WebRtc_Word16 criterion1;
3956f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  WebRtc_Word16 criterion2;
3966f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  WebRtc_Word16 numSubFrames = SUBFRAMES * (1 + (bandwidth == isac16kHz));
3976f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double data[WINLEN];
3986f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double corrSubFrame[UB_LPC_ORDER+2];
3996f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double reflecCoeff[UB_LPC_ORDER];
4006f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4016f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double aPolynom[UB_LPC_ORDER+1];
4026f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double tmp;
4036f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4046f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* bandwdith expansion factors */
4056f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double gamma = 0.9;
4066f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4076f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* change quallevel depending on pitch gains and level fluctuations */
4086f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  WebRtcIsac_GetVarsUB(inSignal, &(maskdata->OldEnergy), varscale);
4096f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* replace data in buffer by new look-ahead data */
4116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for(frameCntr = 0, activeFrameCntr = 0; frameCntr < numSubFrames;
4126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      frameCntr++)
4136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  {
4146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    if(frameCntr == SUBFRAMES)
4156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {
4166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      // we are in 16 kHz
4176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      varscale++;
4186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      WebRtcIsac_GetVarsUB(&inSignal[FRAMESAMPLES_HALF],
4196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                          &(maskdata->OldEnergy), varscale);
4206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
4216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Update input buffer and multiply signal with window */
4226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for(pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++)
4236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {
4246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 +
4256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                                                            UPDATE/2];
4266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
4276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
4286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    pos2 = frameCntr * UPDATE/2;
4296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for(n = 0; n < UPDATE/2; n++, pos1++, pos2++)
4306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {
4316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      maskdata->DataBufferLo[pos1] = inSignal[pos2];
4326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
4336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
4346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* Get correlation coefficients */
4366f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* computing autocorrelation    */
4376f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    WebRtcIsac_AutoCorr(corrSubFrame, data, WINLEN, UB_LPC_ORDER+1);
4386f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    memcpy(corrMat[frameCntr], corrSubFrame,
4396f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin           (UB_LPC_ORDER+1)*sizeof(double));
4406f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4416f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    criterion1 = ((frameCntr == 0) || (frameCntr == (SUBFRAMES - 1))) &&
4426f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        (bandwidth == isac12kHz);
4436f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    criterion2 = (((frameCntr+1) % 4) == 0) &&
4446f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        (bandwidth == isac16kHz);
4456f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    if(criterion1 || criterion2)
4466f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {
4476f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      /* add noise */
4486f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      corrSubFrame[0] += 1e-6;
4496f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      /* compute prediction coefficients */
4506f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      WebRtcIsac_LevDurb(aPolynom, reflecCoeff, corrSubFrame,
4516f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                        UB_LPC_ORDER);
4526f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4536f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      /* bandwidth expansion */
4546f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      tmp = gamma;
4556f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for (n = 1; n <= UB_LPC_ORDER; n++)
4566f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      {
4576f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        *lpCoeff++ = aPolynom[n] * tmp;
4586f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        tmp *= gamma;
4596f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
4606f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      activeFrameCntr++;
4616f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
4626f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
4636f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
4646f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4656f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4666f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
4676f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin/******************************************************************************
4686f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * WebRtcIsac_GetLpcGain()
4696f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
4706f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Compute the LPC gains for each sub-frame, given the LPC of each sub-frame
4716f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * and the corresponding correlation coefficients.
4726f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
4736f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Inputs:
4746f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -signal_noise_ratio : the desired SNR in dB.
4756f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -numVecs            : number of sub-frames
4766f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -corrMat             : a matrix of correlation coefficients where
4776f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                             each row is a set of correlation coefficients of
4786f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                             one sub-frame.
4796f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -varscale           : a scale computed when WebRtcIsac_GetLpcCoefUb()
4806f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *                             is called.
4816f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
4826f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin * Outputs:
4836f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *       -gain               : pointer to a buffer where LP gains are written.
4846f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin *
4856f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin */
4866f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkinvoid
4876f12fff925188ced26e518cd2252aff3e93bb04eAlexander GutkinWebRtcIsac_GetLpcGain(
4886f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double        signal_noise_ratio,
4896f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    const double* filtCoeffVecs,
4906f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    int           numVecs,
4916f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double*       gain,
4926f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    double        corrMat[][UB_LPC_ORDER + 1],
4936f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    const double* varscale)
4946f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin{
4956f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  WebRtc_Word16 j, n;
4966f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  WebRtc_Word16 subFrameCntr;
4976f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double aPolynom[ORDERLO + 1];
4986f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  double res_nrg;
4996f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
5006f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double HearThresOffset = -28.0;
5016f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
5026f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  /* divide by sqrt(12) = 3.46 */
5036f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  const double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46;
5046f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
5056f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  aPolynom[0] = 1;
5066f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  for(subFrameCntr = 0; subFrameCntr < numVecs; subFrameCntr++)
5076f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  {
5086f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    if(subFrameCntr == SUBFRAMES)
5096f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {
5106f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      // we are in second half of a SWB frame. use new varscale
5116f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      varscale++;
5126f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
5136f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    memcpy(&aPolynom[1], &filtCoeffVecs[(subFrameCntr * (UB_LPC_ORDER + 1)) +
5146f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin                                        1], sizeof(double) * UB_LPC_ORDER);
5156f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
5166f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* residual energy */
5176f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    res_nrg = 0.0;
5186f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    for(j = 0; j <= UB_LPC_ORDER; j++)
5196f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    {
5206f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for(n = 0; n <= j; n++)
5216f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      {
5226f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        res_nrg += aPolynom[j] * corrMat[subFrameCntr][j-n] *
5236f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin            aPolynom[n];
5246f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
5256f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      for(n = j+1; n <= UB_LPC_ORDER; n++)
5266f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      {
5276f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin        res_nrg += aPolynom[j] * corrMat[subFrameCntr][n-j] *
5286f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin            aPolynom[n];
5296f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin      }
5306f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    }
5316f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin
5326f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    /* add hearing threshold and compute the gain */
5336f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin    gain[subFrameCntr] = S_N_R / (sqrt(res_nrg) / *varscale + H_T_H);
5346f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin  }
5356f12fff925188ced26e518cd2252aff3e93bb04eAlexander Gutkin}
536