1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * entropy_coding.c
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * This header file defines all of the functions used to arithmetically
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * encode the iSAC bistream
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "entropy_coding.h"
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "settings.h"
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "arith_routines.h"
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "signal_processing_library.h"
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "spectrum_ar_model_tables.h"
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_tables.h"
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pitch_gain_tables.h"
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pitch_lag_tables.h"
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "encode_lpc_swb.h"
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_shape_swb12_tables.h"
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_shape_swb16_tables.h"
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_gain_swb_tables.h"
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "os_specific_inline.h"
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <math.h>
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h>
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
37fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const uint16_t kLpcVecPerSegmentUb12 = 5;
38fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const uint16_t kLpcVecPerSegmentUb16 = 4;
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* CDF array for encoder bandwidth (12 vs 16 kHz) indicator. */
41fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const uint16_t kOneBitEqualProbCdf[3] = {
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0, 32768, 65535 };
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Pointer to cdf array for encoder bandwidth (12 vs 16 kHz) indicator. */
45fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const uint16_t* kOneBitEqualProbCdf_ptr[1] = {
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    kOneBitEqualProbCdf };
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Initial cdf index for decoder of encoded bandwidth
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * (12 vs 16 kHz) indicator.
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
52fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const uint16_t kOneBitEqualProbInitIndex[1] = { 1 };
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic const int kIsSWB12 = 1;
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* compute correlation from power spectrum */
58fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void FindCorrelation(int32_t* PSpecQ12, int32_t* CorrQ7) {
59fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t summ[FRAMESAMPLES / 8];
60fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t diff[FRAMESAMPLES / 8];
61fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t* CS_ptrQ9;
62fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sum;
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, n;
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES / 8; k++) {
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES_QUARTER - 1 - k] + 16) >> 5;
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES_QUARTER - 1 - k] + 16) >> 5;
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = 2;
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES / 8; n++) {
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += summ[n];
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CorrQ7[0] = sum;
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < AR_ORDER; k += 2) {
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = 0;
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CS_ptrQ9 = WebRtcIsac_kCos[k];
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES / 8; n++)
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum += (CS_ptrQ9[n] * diff[n] + 256) >> 9;
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CorrQ7[k + 1] = sum;
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 1; k < AR_ORDER; k += 2) {
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = 0;
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CS_ptrQ9 = WebRtcIsac_kCos[k];
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES / 8; n++)
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum += (CS_ptrQ9[n] * summ[n] + 256) >> 9;
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CorrQ7[k + 1] = sum;
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* compute inverse AR power spectrum */
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Changed to the function used in iSAC FIX for compatibility reasons */
95fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void FindInvArSpec(const int16_t* ARCoefQ12,
96fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          const int32_t gainQ10,
97fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int32_t* CurveQ16) {
98fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t CorrQ11[AR_ORDER + 1];
99fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sum, tmpGain;
100fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t diffQ16[FRAMESAMPLES / 8];
101fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t* CS_ptrQ9;
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, n;
103fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t round, shftVal = 0, sh;
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = 0;
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < AR_ORDER + 1; n++) {
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]);   /* Q24 */
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(sum, 6),
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             65) + 32768, 16); /* Q8 */
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CorrQ11[0] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, gainQ10) + 256, 9);
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* To avoid overflow, we shift down gainQ10 if it is large.
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * We will not lose any precision */
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (gainQ10 > 400000) {
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpGain = WEBRTC_SPL_RSHIFT_W32(gainQ10, 3);
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    round = 32;
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 6;
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpGain = gainQ10;
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    round = 256;
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 9;
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 1; k < AR_ORDER + 1; k++) {
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = 16384;
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = k; n < AR_ORDER + 1; n++)
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum += WEBRTC_SPL_MUL(ARCoefQ12[n - k], ARCoefQ12[n]); /* Q24 */
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = WEBRTC_SPL_RSHIFT_W32(sum, 15);
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CorrQ11[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, tmpGain) + round,
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       shftVal);
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = WEBRTC_SPL_LSHIFT_W32(CorrQ11[0], 7);
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES / 8; n++) {
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CurveQ16[n] = sum;
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 1; k < AR_ORDER; k += 2) {
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES / 8; n++) {
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      CurveQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          WebRtcIsac_kCos[k][n], CorrQ11[k + 1]) + 2, 2);
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CS_ptrQ9 = WebRtcIsac_kCos[0];
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If CorrQ11[1] too large we avoid getting overflow in the
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * calculation by shifting */
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sh = WebRtcSpl_NormW32(CorrQ11[1]);
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (CorrQ11[1] == 0) { /* Use next correlation */
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sh = WebRtcSpl_NormW32(CorrQ11[2]);
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (sh < 9) {
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 9 - sh;
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 0;
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES / 8; n++) {
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    diffQ16[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[1], shftVal)) + 2, 2);
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 2; k < AR_ORDER; k += 2) {
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CS_ptrQ9 = WebRtcIsac_kCos[k];
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES / 8; n++) {
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      diffQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[k + 1], shftVal)) + 2, 2);
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES / 8; k++) {
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CurveQ16[FRAMESAMPLES_QUARTER - 1 - k] = CurveQ16[k] -
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CurveQ16[k] += WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Generate array of dither samples in Q7. */
177fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void GenerateDitherQ7Lb(int16_t* bufQ7, uint32_t seed,
178fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                               int length, int16_t AvgPitchGain_Q12) {
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int   k, shft;
180fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t dither1_Q7, dither2_Q7, dither_gain_Q14;
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* This threshold should be equal to that in decode_spec(). */
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (AvgPitchGain_Q12 < 614) {
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < length - 2; k += 3) {
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* New random unsigned int. */
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      seed = (seed * 196314165) + 907633515;
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Fixed-point dither sample between -64 and 64 (Q7). */
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* dither = seed * 128 / 4294967295 */
190fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      dither1_Q7 = (int16_t)(((int)seed + 16777216) >> 25);
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* New random unsigned int. */
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      seed = (seed * 196314165) + 907633515;
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Fixed-point dither sample between -64 and 64. */
196fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      dither2_Q7 = (int16_t)(((int)seed + 16777216) >> 25);
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      shft = (seed >> 25) & 15;
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (shft < 5) {
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k]   = dither1_Q7;
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k + 1] = dither2_Q7;
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k + 2] = 0;
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      } else if (shft < 10) {
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k]   = dither1_Q7;
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k + 1] = 0;
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k + 2] = dither2_Q7;
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      } else {
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k]   = 0;
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k + 1] = dither1_Q7;
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k + 2] = dither2_Q7;
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
214fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    dither_gain_Q14 = (int16_t)(22528 - 10 * AvgPitchGain_Q12);
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Dither on half of the coefficients. */
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < length - 1; k += 2) {
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* New random unsigned int */
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      seed = (seed * 196314165) + 907633515;
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Fixed-point dither sample between -64 and 64. */
222fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      dither1_Q7 = (int16_t)(((int)seed + 16777216) >> 25);
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Dither sample is placed in either even or odd index. */
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      shft = (seed >> 25) & 1;     /* Either 0 or 1 */
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bufQ7[k + shft] = (((dither_gain_Q14 * dither1_Q7) + 8192) >> 14);
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bufQ7[k + 1 - shft] = 0;
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/******************************************************************************
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * GenerateDitherQ7LbUB()
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * generate array of dither samples in Q7 There are less zeros in dither
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * vector compared to GenerateDitherQ7Lb.
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * A uniform random number generator with the range of [-64 64] is employed
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * but the generated dithers are scaled by 0.35, a heuristic scaling.
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Input:
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *      -seed               : the initial seed for the random number generator.
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *      -length             : the number of dither values to be generated.
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Output:
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *      -bufQ7              : pointer to a buffer where dithers are written to.
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic void GenerateDitherQ7LbUB(
252fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int16_t* bufQ7,
253fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    uint32_t seed,
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int length) {
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < length; k++) {
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* new random unsigned int */
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    seed = (seed * 196314165) + 907633515;
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Fixed-point dither sample between -64 and 64 (Q7). */
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* bufQ7 = seed * 128 / 4294967295 */
262fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    bufQ7[k] = (int16_t)(((int)seed + 16777216) >> 25);
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Scale by 0.35. */
265fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    bufQ7[k] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT(bufQ7[k], 2048, 13);
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Function to decode the complex spectrum from the bit stream
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * returns the total number of bytes in the stream.
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
273fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_DecodeSpec(Bitstr* streamdata, int16_t AvgPitchGain_Q12,
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          enum ISACBand band, double* fr, double* fi) {
275fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  DitherQ7[FRAMESAMPLES];
276fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  data[FRAMESAMPLES];
277fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  invARSpec2_Q16[FRAMESAMPLES_QUARTER];
278fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint16_t invARSpecQ8[FRAMESAMPLES_QUARTER];
279fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  ARCoefQ12[AR_ORDER + 1];
280fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  RCQ15[AR_ORDER];
281fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  gainQ10;
282fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  gain2_Q10, res;
283fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  in_sqrt;
284fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  newRes;
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, len, i;
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int is_12khz = !kIsSWB12;
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int num_dft_coeff = FRAMESAMPLES;
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Create dither signal. */
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (band == kIsacLowerBand) {
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    GenerateDitherQ7Lb(DitherQ7, streamdata->W_upper, FRAMESAMPLES,
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       AvgPitchGain_Q12);
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    GenerateDitherQ7LbUB(DitherQ7, streamdata->W_upper, FRAMESAMPLES);
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (band == kIsacUpperBand12) {
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      is_12khz = kIsSWB12;
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      num_dft_coeff = FRAMESAMPLES_HALF;
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Decode model parameters. */
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0)
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0)
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Compute inverse AR power spectrum. */
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Convert to magnitude spectrum,
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * by doing square-roots (modified from SPLIB). */
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    in_sqrt = invARSpec2_Q16[k];
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    i = 10;
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Negative values make no sense for a real sqrt-function. */
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (in_sqrt < 0)
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      in_sqrt = -in_sqrt;
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    newRes = (in_sqrt / res + res) >> 1;
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    do {
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      res = newRes;
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      newRes = (in_sqrt / res + res) >> 1;
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } while (newRes != res && i-- > 0);
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
329fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    invARSpecQ8[k] = (int16_t)newRes;
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8, DitherQ7,
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     num_dft_coeff, is_12khz);
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Arithmetic decoding of spectrum. */
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (len < 1) {
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (band) {
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kIsacLowerBand: {
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Scale down spectral samples with low SNR. */
342fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      int32_t p1;
343fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      int32_t p2;
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (AvgPitchGain_Q12 <= 614) {
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        p1 = 30 << 10;
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        p2 = 32768 + (33 << 16);
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      } else {
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        p1 = 36 << 10;
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        p2 = 32768 + (40 << 16);
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (k = 0; k < FRAMESAMPLES; k += 4) {
352fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org        gainQ10 = WebRtcSpl_DivW32W16ResW16(p1, (int16_t)(
353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            (invARSpec2_Q16[k >> 2] + p2) >> 16));
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        *fr++ = (double)((data[ k ] * gainQ10 + 512) >> 10) / 128.0;
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        *fi++ = (double)((data[k + 1] * gainQ10 + 512) >> 10) / 128.0;
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        *fr++ = (double)((data[k + 2] * gainQ10 + 512) >> 10) / 128.0;
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        *fi++ = (double)((data[k + 3] * gainQ10 + 512) >> 10) / 128.0;
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kIsacUpperBand12: {
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (k = 0, i = 0; k < FRAMESAMPLES_HALF; k += 4) {
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        fr[i] = (double)data[ k ] / 128.0;
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        fi[i] = (double)data[k + 1] / 128.0;
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        i++;
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        fr[i] = (double)data[k + 2] / 128.0;
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        fi[i] = (double)data[k + 3] / 128.0;
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        i++;
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* The second half of real and imaginary coefficients is zero. This is
371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       * due to using the old FFT module which requires two signals as input
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       * while in 0-12 kHz mode we only have 8-12 kHz band, and the second
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       * signal is set to zero. */
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      memset(&fr[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER *
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org             sizeof(double));
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      memset(&fi[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER *
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org             sizeof(double));
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kIsacUpperBand16: {
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (i = 0, k = 0; k < FRAMESAMPLES; k += 4, i++) {
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        fr[i] = (double)data[ k ] / 128.0;
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        fi[i] = (double)data[k + 1] / 128.0;
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        fr[(FRAMESAMPLES_HALF) - 1 - i] = (double)data[k + 2] / 128.0;
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        fi[(FRAMESAMPLES_HALF) - 1 - i] = (double)data[k + 3] / 128.0;
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return len;
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
394fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_EncodeSpec(const int16_t* fr, const int16_t* fi,
395fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int16_t AvgPitchGain_Q12, enum ISACBand band,
396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          Bitstr* streamdata) {
397fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t ditherQ7[FRAMESAMPLES];
398fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t dataQ7[FRAMESAMPLES];
399fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t PSpec[FRAMESAMPLES_QUARTER];
400fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t invARSpec2_Q16[FRAMESAMPLES_QUARTER];
401fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint16_t invARSpecQ8[FRAMESAMPLES_QUARTER];
402fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t CorrQ7[AR_ORDER + 1];
403fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t CorrQ7_norm[AR_ORDER + 1];
404fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t RCQ15[AR_ORDER];
405fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t ARCoefQ12[AR_ORDER + 1];
406fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t gain2_Q10;
407fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t val;
408fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t nrg, res;
409fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint32_t sum;
410fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t in_sqrt;
411fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t newRes;
412fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t err;
413fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint32_t nrg_u32;
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int shift_var;
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, n, j, i;
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int is_12khz = !kIsSWB12;
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int num_dft_coeff = FRAMESAMPLES;
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Create dither signal. */
420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (band == kIsacLowerBand) {
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    GenerateDitherQ7Lb(ditherQ7, streamdata->W_upper, FRAMESAMPLES,
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       AvgPitchGain_Q12);
423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    GenerateDitherQ7LbUB(ditherQ7, streamdata->W_upper, FRAMESAMPLES);
425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (band == kIsacUpperBand12) {
426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      is_12khz = kIsSWB12;
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      num_dft_coeff = FRAMESAMPLES_HALF;
428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* add dither and quantize, and compute power spectrum */
432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (band) {
433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kIsacLowerBand: {
434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (k = 0; k < FRAMESAMPLES; k += 4) {
435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((*fr++ + ditherQ7[k]   + 64) & 0xFF80) - ditherQ7[k];
436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k] = val;
437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum = val * val;
438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((*fi++ + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 1] = val;
441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += val * val;
442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((*fr++ + ditherQ7[k + 2] + 64) & 0xFF80) - ditherQ7[k + 2];
444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 2] = val;
445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += val * val;
446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((*fi++ + ditherQ7[k + 3] + 64) & 0xFF80) - ditherQ7[k + 3];
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 3] = val;
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += val * val;
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        PSpec[k >> 2] = sum >> 2;
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kIsacUpperBand12: {
456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (k = 0, j = 0; k < FRAMESAMPLES_HALF; k += 4) {
457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((*fr++ + ditherQ7[k]   + 64) & 0xFF80) - ditherQ7[k];
458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k] = val;
459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum = val * val;
460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((*fi++ + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 1] = val;
463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += val * val;
464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        PSpec[j++] = sum >> 1;
466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((*fr++ + ditherQ7[k + 2] + 64) & 0xFF80) - ditherQ7[k + 2];
468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 2] = val;
469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum = val * val;
470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((*fi++ + ditherQ7[k + 3] + 64) & 0xFF80) - ditherQ7[k + 3];
472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 3] = val;
473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += val * val;
474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        PSpec[j++] = sum >> 1;
476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kIsacUpperBand16: {
480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (j = 0, k = 0; k < FRAMESAMPLES; k += 4, j++) {
481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((fr[j] + ditherQ7[k]   + 64) & 0xFF80) - ditherQ7[k];
482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k] = val;
483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum = val * val;
484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((fi[j] + ditherQ7[k + 1] + 64) & 0xFF80) - ditherQ7[k + 1];
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 1] = val;
487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += val * val;
488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((fr[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k + 2] + 64) &
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            0xFF80) - ditherQ7[k + 2];
491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 2] = val;
492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += val * val;
493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        val = ((fi[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k + 3] + 64) &
495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            0xFF80) - ditherQ7[k + 3];
496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        dataQ7[k + 3] = val;
497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += val * val;
498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        PSpec[k >> 2] = sum >> 2;
500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* compute correlation from power spectrum */
506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FindCorrelation(PSpec, CorrQ7);
507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find AR coefficients */
509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Aumber of bit shifts to 14-bit normalize CorrQ7[0]
510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * (leaving room for sign) */
511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  shift_var = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (shift_var > 0) {
514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < AR_ORDER + 1; k++) {
515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      CorrQ7_norm[k] = CorrQ7[k] << shift_var;
516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < AR_ORDER + 1; k++) {
519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      CorrQ7_norm[k] = CorrQ7[k] >> (-shift_var);
520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find RC coefficients. */
524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Quantize & code RC Coefficient. */
527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeRc(RCQ15, streamdata);
528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* RC -> AR coefficients */
530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Compute ARCoef' * Corr * ARCoef in Q19. */
533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  nrg = 0;
534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j <= AR_ORDER; j++) {
535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n <= j; n++) {
536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      nrg += (ARCoefQ12[j] * ((CorrQ7_norm[j - n] * ARCoefQ12[n] + 256) >> 9) +
537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          4) >> 3;
538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = j + 1; n <= AR_ORDER; n++) {
540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      nrg += (ARCoefQ12[j] * ((CorrQ7_norm[n - j] * ARCoefQ12[n] + 256) >> 9) +
541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          4) >> 3;
542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
545fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  nrg_u32 = (uint32_t)nrg;
546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (shift_var > 0) {
547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    nrg_u32 = nrg_u32 >> shift_var;
548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    nrg_u32 = nrg_u32 << (-shift_var);
550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (nrg_u32 > 0x7FFFFFFF) {
552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    nrg = 0x7FFFFFFF;
553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }  else {
554fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    nrg = (int32_t)nrg_u32;
555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Also shifts 31 bits to the left! */
557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg);
558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Quantize & code gain2_Q10. */
560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) {
561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Compute inverse AR power spectrum. */
565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Convert to magnitude spectrum, by doing square-roots
567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * (modified from SPLIB). */
568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    in_sqrt = invARSpec2_Q16[k];
571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    i = 10;
572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Negative values make no sense for a real sqrt-function. */
573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (in_sqrt < 0) {
574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      in_sqrt = -in_sqrt;
575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    newRes = (in_sqrt / res + res) >> 1;
577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    do {
578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      res = newRes;
579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      newRes = (in_sqrt / res + res) >> 1;
580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } while (newRes != res && i-- > 0);
581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
582fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    invARSpecQ8[k] = (int16_t)newRes;
583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* arithmetic coding of spectrum */
585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8,
586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     num_dft_coeff, is_12khz);
587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (err);
589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* step-up */
595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_Rc2Poly(double* RC, int N, double* a) {
596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int m, k;
597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmp[MAX_AR_MODEL_ORDER];
598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  a[0] = 1.0;
600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  tmp[0] = 1.0;
601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (m = 1; m <= N; m++) {
602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* copy */
603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&tmp[1], &a[1], (m - 1) * sizeof(double));
604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    a[m] = RC[m - 1];
605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 1; k < m; k++) {
606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      a[k] += RC[m - 1] * tmp[m - k];
607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return;
610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* step-down */
613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_Poly2Rc(double* a, int N, double* RC) {
614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int m, k;
615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmp[MAX_AR_MODEL_ORDER];
616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmp_inv;
617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  RC[N - 1] = a[N];
619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (m = N - 1; m > 0; m--) {
620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmp_inv = 1.0 / (1.0 - RC[m] * RC[m]);
621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 1; k <= m; k++) {
622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp[k] = (a[k] - RC[m] * a[m - k + 1]) * tmp_inv;
623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&a[1], &tmp[1], (m - 1) * sizeof(double));
626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RC[m - 1] = tmp[m];
627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return;
629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define MAX_ORDER 100
633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Matlab's LAR definition */
635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_Rc2Lar(const double* refc, double* lar, int order) {
636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < order; k++) {
638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lar[k] = log((1 + refc[k]) / (1 - refc[k]));
639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_Lar2Rc(const double* lar, double* refc,  int order) {
644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmp;
646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < order; k++) {
648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmp = exp(lar[k]);
649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    refc[k] = (tmp - 1) / (tmp + 1);
650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_Poly2Lar(double* lowband, int orderLo, double* hiband,
654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         int orderHi, int Nsub, double* lars) {
655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double rc[MAX_ORDER], *inpl, *inph, *outp;
657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  inpl = lowband;
659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  inph = hiband;
660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  outp = lars;
661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < Nsub; k++) {
662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* gains */
663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outp[0] = inpl[0];
664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outp[1] = inph[0];
665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outp += 2;
666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Low band */
668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    inpl[0] = 1.0;
669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Poly2Rc(inpl, orderLo, rc);
670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Rc2Lar(rc, outp, orderLo);
671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outp += orderLo;
672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* High band */
674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    inph[0] = 1.0;
675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Poly2Rc(inph, orderHi, rc);
676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Rc2Lar(rc, outp, orderHi);
677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outp += orderHi;
678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    inpl += orderLo + 1;
680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    inph += orderHi + 1;
681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
685fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_Poly2LarUB(double* lpcVecs, int16_t bandwidth) {
686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double      poly[MAX_ORDER];
687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double      rc[MAX_ORDER];
688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double*     ptrIO;
689fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t vecCntr;
690fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t vecSize;
691fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t numVec;
692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  vecSize = UB_LPC_ORDER;
694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (bandwidth) {
695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac12kHz: {
696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      numVec  = UB_LPC_VEC_PER_FRAME;
697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac16kHz: {
700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      numVec  = UB16_LPC_VEC_PER_FRAME;
701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -1;
705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ptrIO = lpcVecs;
708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poly[0] = 1.0;
709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (vecCntr = 0; vecCntr < numVec; vecCntr++) {
710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&poly[1], ptrIO, sizeof(double) * vecSize);
711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Poly2Rc(poly, vecSize, rc);
712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Rc2Lar(rc, ptrIO, vecSize);
713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ptrIO += vecSize;
714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_Lar2Poly(double* lars, double* lowband, int orderLo,
720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         double* hiband, int orderHi, int Nsub) {
721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, orderTot;
722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double rc[MAX_ORDER], *outpl, *outph, *inp;
723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  orderTot = (orderLo + orderHi + 2);
725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  outpl = lowband;
726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  outph = hiband;
727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* First two elements of 'inp' store gains*/
728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  inp = lars;
729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < Nsub; k++) {
730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Low band */
731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Lar2Rc(&inp[2], rc, orderLo);
732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Rc2Poly(rc, orderLo, outpl);
733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* High band */
735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Lar2Rc(&inp[orderLo + 2], rc, orderHi);
736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Rc2Poly(rc, orderHi, outph);
737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* gains */
739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outpl[0] = inp[0];
740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outph[0] = inp[1];
741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outpl += orderLo + 1;
743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outph += orderHi + 1;
744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    inp += orderTot;
745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  assumes 2 LAR vectors interpolates to 'numPolyVec' A-polynomials
750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Note: 'numPolyVecs' includes the first and the last point of the interval
751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_Lar2PolyInterpolUB(double* larVecs, double* percepFilterParams,
753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   int numPolyVecs) {
754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int polyCntr, coeffCntr;
755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double larInterpol[UB_LPC_ORDER];
756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double rc[UB_LPC_ORDER];
757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double delta[UB_LPC_ORDER];
758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* calculate the step-size for linear interpolation coefficients */
760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) {
761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delta[coeffCntr] = (larVecs[UB_LPC_ORDER + coeffCntr] -
762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        larVecs[coeffCntr]) / (numPolyVecs - 1);
763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (polyCntr = 0; polyCntr < numPolyVecs; polyCntr++) {
766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++) {
767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      larInterpol[coeffCntr] = larVecs[coeffCntr] +
768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          delta[coeffCntr] * polyCntr;
769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Lar2Rc(larInterpol, rc, UB_LPC_ORDER);
771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* convert to A-polynomial, the following function returns A[0] = 1;
773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * which is written where gains had to be written. Then we write the
774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * gain (outside this function). This way we say a memcpy. */
775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Rc2Poly(rc, UB_LPC_ORDER, percepFilterParams);
776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    percepFilterParams += (UB_LPC_ORDER + 1);
777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_DecodeLpc(Bitstr* streamdata, double* LPCCoef_lo,
781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         double* LPCCoef_hi) {
782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lars[KLT_ORDER_GAIN + KLT_ORDER_SHAPE];
783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecodeLpcCoef(streamdata, lars);
786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_LPC;
788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_Lar2Poly(lars, LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI,
790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      SUBFRAMES);
791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
794fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_DecodeInterpolLpcUb(Bitstr* streamdata,
795fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                       double* percepFilterParams,
796fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                       int16_t bandwidth) {
797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lpcCoeff[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int interpolCntr;
800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int subframeCntr;
801fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t numSegments;
802fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t numVecPerSegment;
803fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t numGains;
804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double percepFilterGains[SUBFRAMES << 1];
806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double* ptrOutParam = percepFilterParams;
807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecodeLpcCoefUB(streamdata, lpcCoeff, percepFilterGains,
809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   bandwidth);
810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_LPC;
812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (bandwidth) {
815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac12kHz: {
816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      numGains = SUBFRAMES;
817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      numSegments = UB_LPC_VEC_PER_FRAME - 1;
818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      numVecPerSegment = kLpcVecPerSegmentUb12;
819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac16kHz: {
822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      numGains = SUBFRAMES << 1;
823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      numSegments = UB16_LPC_VEC_PER_FRAME - 1;
824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      numVecPerSegment = kLpcVecPerSegmentUb16;
825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -1;
829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (interpolCntr = 0; interpolCntr < numSegments; interpolCntr++) {
832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_Lar2PolyInterpolUB(&lpcCoeff[interpolCntr * UB_LPC_ORDER],
833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  ptrOutParam, numVecPerSegment + 1);
834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ptrOutParam += (numVecPerSegment * (UB_LPC_ORDER + 1));
835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ptrOutParam = percepFilterParams;
838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (bandwidth == isac16kHz) {
840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ptrOutParam += (1 + UB_LPC_ORDER);
841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (subframeCntr = 0; subframeCntr < numGains; subframeCntr++) {
844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *ptrOutParam = percepFilterGains[subframeCntr];
845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ptrOutParam += (1 + UB_LPC_ORDER);
846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize LPC Coef */
852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_DecodeLpcCoef(Bitstr* streamdata, double* LPCCoef) {
853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int j, k, n, pos, pos2, posg, poss, offsg, offss, offs2;
854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index_g[KLT_ORDER_GAIN], index_s[KLT_ORDER_SHAPE];
855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpcoeffs_g[KLT_ORDER_GAIN], tmpcoeffs_s[KLT_ORDER_SHAPE];
856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpcoeffs2_g[KLT_ORDER_GAIN], tmpcoeffs2_s[KLT_ORDER_SHAPE];
857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double sum;
858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int model = 1;
860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of model number */
862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* We are keeping this for backward compatibility of bit-streams. */
863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(&model, streamdata,
864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kQKltModelCdfPtr,
865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kQKltModelInitIndex, 1);
866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Only accepted value of model is 0. It is kept in bit-stream for backward
870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * compatibility. */
871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (model != 0) {
872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_DISALLOWED_LPC_MODEL;
873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of quantization indices */
876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(
877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_s, streamdata, WebRtcIsac_kQKltCdfPtrShape,
878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_kQKltInitIndexShape, KLT_ORDER_SHAPE);
879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(
883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_g, streamdata, WebRtcIsac_kQKltCdfPtrGain,
884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_kQKltInitIndexGain, KLT_ORDER_GAIN);
885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization levels for coefficients */
890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < KLT_ORDER_SHAPE; k++) {
891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_s[k] =
892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WebRtcIsac_kQKltLevelsShape[WebRtcIsac_kQKltOffsetShape[k] +
893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    index_s[k]];
894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < KLT_ORDER_GAIN; k++) {
896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[WebRtcIsac_kQKltOffsetGain[k] +
897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                index_g[k]];
898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Inverse KLT  */
901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Left transform, transpose matrix!  */
903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offss = 0;
905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;
907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offs2 = 0;
909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_GAIN_ORDER; k++) {
910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = offsg;
912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = offs2;
913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < LPC_GAIN_ORDER; n++) {
914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2++];
915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_g[posg++] = sum;
917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      offs2 += LPC_GAIN_ORDER;
918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offs2 = 0;
920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = offss;
923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = offs2;
924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < LPC_SHAPE_ORDER; n++) {
925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2++];
926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_s[poss++] = sum;
928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      offs2 += LPC_SHAPE_ORDER;
929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += LPC_GAIN_ORDER;
931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offss += LPC_SHAPE_ORDER;
932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Right transform, transpose matrix */
935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offss = 0;
937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;
939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg = offsg;
941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_GAIN_ORDER; k++) {
942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = k;
944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = j;
945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < SUBFRAMES; n++) {
946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2];
947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += LPC_GAIN_ORDER;
948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos2 += SUBFRAMES;
949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_g[posg++] = sum;
952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    poss = offss;
954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = k;
957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = j;
958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < SUBFRAMES; n++) {
959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2];
960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += LPC_SHAPE_ORDER;
961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos2 += SUBFRAMES;
962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_s[poss++] = sum;
964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += LPC_GAIN_ORDER;
966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offss += LPC_SHAPE_ORDER;
967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* scaling, mean addition, and gain restoration */
970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;
972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos = 0;
973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* log gains */
975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LPCCoef[pos] = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LPCCoef[pos] += WebRtcIsac_kLpcMeansGain[posg];
977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LPCCoef[pos] = exp(LPCCoef[pos]);
978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LPCCoef[pos] = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LPCCoef[pos] += WebRtcIsac_kLpcMeansGain[posg];
982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LPCCoef[pos] = exp(LPCCoef[pos]);
983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Low-band LAR coefficients. */
987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < LPC_LOBAND_ORDER; n++, pos++, poss++) {
988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_LOBAND_SCALE;
989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* High-band LAR coefficients. */
993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < LPC_HIBAND_ORDER; n++, pos++, poss++) {
994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_HIBAND_SCALE;
995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Encode LPC in LAR domain. */
1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_EncodeLar(double* LPCCoef, Bitstr* streamdata,
1003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          ISAC_SaveEncData_t* encData) {
1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int j, k, n, pos, pos2, poss, offss, offs2;
1005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index_s[KLT_ORDER_SHAPE];
1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index_ovr_s[KLT_ORDER_SHAPE];
1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpcoeffs_s[KLT_ORDER_SHAPE];
1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpcoeffs2_s[KLT_ORDER_SHAPE];
1009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double sum;
1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const int kModel = 0;
1011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Mean removal and scaling. */
1013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;
1014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos = 0;
1015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* First two element are gains, move over them. */
1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 2;
1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Low-band LAR coefficients. */
1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < LPC_LOBAND_ORDER; n++, poss++, pos++) {
1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_s[poss] = LPCCoef[pos] - WebRtcIsac_kLpcMeansShape[poss];
1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_s[poss] *= LPC_LOBAND_SCALE;
1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* High-band LAR coefficients. */
1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < LPC_HIBAND_ORDER; n++, poss++, pos++) {
1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_s[poss] = LPCCoef[pos] - WebRtcIsac_kLpcMeansShape[poss];
1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_s[poss] *= LPC_HIBAND_SCALE;
1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* KLT  */
1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Left transform. */
1035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offss = 0;
1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    poss = offss;
1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
1039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = offss;
1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = k;
1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < LPC_SHAPE_ORDER; n++) {
1043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2];
1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos2 += LPC_SHAPE_ORDER;
1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_s[poss++] = sum;
1047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offss += LPC_SHAPE_ORDER;
1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Right transform. */
1052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offss = 0;
1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offs2 = 0;
1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    poss = offss;
1056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
1057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = k;
1059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = offs2;
1060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < SUBFRAMES; n++) {
1061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2++];
1062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += LPC_SHAPE_ORDER;
1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_s[poss++] = sum;
1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offs2 += SUBFRAMES;
1067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offss += LPC_SHAPE_ORDER;
1068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Quantize coefficients. */
1071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < KLT_ORDER_SHAPE; k++) {
1072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_s[k] = (WebRtcIsac_lrint(tmpcoeffs_s[k] / KLT_STEPSIZE)) +
1073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WebRtcIsac_kQKltQuantMinShape[k];
1074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index_s[k] < 0) {
1075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_s[k] = 0;
1076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (index_s[k] > WebRtcIsac_kQKltMaxIndShape[k]) {
1077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_s[k] = WebRtcIsac_kQKltMaxIndShape[k];
1078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_ovr_s[k] = WebRtcIsac_kQKltOffsetShape[k] + index_s[k];
1080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Only one model remains in this version of the code, kModel = 0. We
1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * are keeping for bit-streams to be backward compatible. */
1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of model number */
1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, &kModel, WebRtcIsac_kQKltModelCdfPtr, 1);
1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bit streams */
1089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Entropy coding of quantization indices - shape only. */
1090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, index_s, WebRtcIsac_kQKltCdfPtrShape,
1091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          KLT_ORDER_SHAPE);
1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bit streams. */
1094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < KLT_ORDER_SHAPE; k++) {
1095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    encData->LPCindex_s[KLT_ORDER_SHAPE * encData->startIdx + k] = index_s[k];
1096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find quantization levels for shape coefficients. */
1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < KLT_ORDER_SHAPE; k++) {
1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_s[k] = WebRtcIsac_kQKltLevelsShape[index_ovr_s[k]];
1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Inverse KLT.  */
1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Left transform, transpose matrix.! */
1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offss = 0;
1105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;
1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offs2 = 0;
1108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
1109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = offss;
1111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = offs2;
1112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < LPC_SHAPE_ORDER; n++) {
1113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs_s[pos++] * WebRtcIsac_kKltT1Shape[pos2++];
1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_s[poss++] = sum;
1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      offs2 += LPC_SHAPE_ORDER;
1117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offss += LPC_SHAPE_ORDER;
1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Right transform, Transpose matrix */
1122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offss = 0;
1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;
1124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    poss = offss;
1126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_SHAPE_ORDER; k++) {
1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = k;
1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = j;
1130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < SUBFRAMES; n++) {
1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs2_s[pos] * WebRtcIsac_kKltT2Shape[pos2];
1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += LPC_SHAPE_ORDER;
1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos2 += SUBFRAMES;
1134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_s[poss++] = sum;
1136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offss += LPC_SHAPE_ORDER;
1138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Scaling, mean addition, and gain restoration. */
1141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;
1142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  pos = 0;
1143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
1144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Ignore gains. */
1145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos += 2;
1146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Low band LAR coefficients. */
1148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < LPC_LOBAND_ORDER; n++, pos++, poss++) {
1149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_LOBAND_SCALE;
1150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
1151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* High band LAR coefficients. */
1154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < LPC_HIBAND_ORDER; n++, pos++, poss++) {
1155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoef[pos] = tmpcoeffs_s[poss] / LPC_HIBAND_SCALE;
1156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoef[pos] += WebRtcIsac_kLpcMeansShape[poss];
1157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_EncodeLpcLb(double* LPCCoef_lo, double* LPCCoef_hi,
1163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            Bitstr* streamdata, ISAC_SaveEncData_t* encData) {
1164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lars[KLT_ORDER_GAIN + KLT_ORDER_SHAPE];
1165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_Poly2Lar(LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI, SUBFRAMES,
1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      lars);
1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeLar(lars, streamdata, encData);
1170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_Lar2Poly(lars, LPCCoef_lo, ORDERLO, LPCCoef_hi, ORDERHI,
1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      SUBFRAMES);
1172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bit streams (and transcoding). */
1173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < (ORDERLO + 1)*SUBFRAMES; k++) {
1174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    encData->LPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * encData->startIdx + k] =
1175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        LPCCoef_lo[k];
1176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < (ORDERHI + 1)*SUBFRAMES; k++) {
1178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    encData->LPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * encData->startIdx + k] =
1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        LPCCoef_hi[k];
1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1184fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_EncodeLpcUB(double* lpcVecs, Bitstr* streamdata,
1185fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                               double* interpolLPCCoeff,
1186fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                               int16_t bandwidth,
1187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     ISACUBSaveEncDataStruct* encData) {
1188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double    U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
1189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int     idx[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
1190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int interpolCntr;
1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_Poly2LarUB(lpcVecs, bandwidth);
1193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_RemoveLarMean(lpcVecs, bandwidth);
1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_DecorrelateIntraVec(lpcVecs, U, bandwidth);
1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_DecorrelateInterVec(U, lpcVecs, bandwidth);
1196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_QuantizeUncorrLar(lpcVecs, idx, bandwidth);
1197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
1199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
1200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
1201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (bandwidth) {
1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac12kHz: {
1204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Store the indices to be used for multiple encoding. */
1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER *
1206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org             UB_LPC_VEC_PER_FRAME * sizeof(int));
1207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb12,
1208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME);
1209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (interpolCntr = 0; interpolCntr < UB_INTERPOL_SEGMENTS;
1210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          interpolCntr++) {
1211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff,
1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      kLpcVecPerSegmentUb12 + 1);
1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        lpcVecs += UB_LPC_ORDER;
1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        interpolLPCCoeff += (kLpcVecPerSegmentUb12 * (UB_LPC_ORDER + 1));
1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac16kHz: {
1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Store the indices to be used for multiple encoding. */
1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER *
1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org             UB16_LPC_VEC_PER_FRAME * sizeof(int));
1222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb16,
1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME);
1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (interpolCntr = 0; interpolCntr < UB16_INTERPOL_SEGMENTS;
1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          interpolCntr++) {
1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        WebRtcIsac_Lar2PolyInterpolUB(lpcVecs, interpolLPCCoeff,
1227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      kLpcVecPerSegmentUb16 + 1);
1228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        lpcVecs += UB_LPC_ORDER;
1229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        interpolLPCCoeff += (kLpcVecPerSegmentUb16 * (UB_LPC_ORDER + 1));
1230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -1;
1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_EncodeLpcGainLb(double* LPCCoef_lo, double* LPCCoef_hi,
1240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                Bitstr* streamdata,
1241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                ISAC_SaveEncData_t* encData) {
1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int j, k, n, pos, pos2, posg, offsg, offs2;
1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index_g[KLT_ORDER_GAIN];
1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index_ovr_g[KLT_ORDER_GAIN];
1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpcoeffs_g[KLT_ORDER_GAIN];
1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpcoeffs2_g[KLT_ORDER_GAIN];
1247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double sum;
1248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* log gains, mean removal and scaling */
1249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
1250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
1251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] = log(LPCCoef_lo[(LPC_LOBAND_ORDER + 1) * k]);
1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
1253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
1254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
1255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] = log(LPCCoef_hi[(LPC_HIBAND_ORDER + 1) * k]);
1256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
1257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
1258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
1259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* KLT  */
1262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Left transform. */
1264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
1265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg = offsg;
1267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_GAIN_ORDER; k++) {
1268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = offsg;
1270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = k;
1271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < LPC_GAIN_ORDER; n++) {
1272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2];
1273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos2 += LPC_GAIN_ORDER;
1274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_g[posg++] = sum;
1276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += LPC_GAIN_ORDER;
1278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Right transform. */
1281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
1282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offs2 = 0;
1283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg = offsg;
1285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_GAIN_ORDER; k++) {
1286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = k;
1288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = offs2;
1289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < SUBFRAMES; n++) {
1290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2++];
1291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += LPC_GAIN_ORDER;
1292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_g[posg++] = sum;
1294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offs2 += SUBFRAMES;
1296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += LPC_GAIN_ORDER;
1297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Quantize coefficients. */
1300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < KLT_ORDER_GAIN; k++) {
1301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Get index. */
1302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos2 = WebRtcIsac_lrint(tmpcoeffs_g[k] / KLT_STEPSIZE);
1303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_g[k] = (pos2) + WebRtcIsac_kQKltQuantMinGain[k];
1304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index_g[k] < 0) {
1305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_g[k] = 0;
1306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (index_g[k] > WebRtcIsac_kQKltMaxIndGain[k]) {
1307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
1308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[k] + index_g[k];
1310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Find quantization levels for coefficients. */
1312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[index_ovr_g[k]];
1313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save data for creation of multiple bit streams. */
1315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    encData->LPCindex_g[KLT_ORDER_GAIN * encData->startIdx + k] = index_g[k];
1316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Entropy coding of quantization indices - gain. */
1319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, index_g, WebRtcIsac_kQKltCdfPtrGain,
1320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          KLT_ORDER_GAIN);
1321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find quantization levels for coefficients. */
1323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Left transform. */
1324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
1325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
1326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offs2 = 0;
1328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_GAIN_ORDER; k++) {
1329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = offsg;
1331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = offs2;
1332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < LPC_GAIN_ORDER; n++)
1333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2++];
1334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_g[posg++] = sum;
1335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      offs2 += LPC_GAIN_ORDER;
1336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += LPC_GAIN_ORDER;
1338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Right transform, transpose matrix. */
1341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
1342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
1343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg = offsg;
1345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_GAIN_ORDER; k++) {
1346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = k;
1348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = j;
1349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < SUBFRAMES; n++) {
1350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2];
1351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += LPC_GAIN_ORDER;
1352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos2 += SUBFRAMES;
1353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_g[posg++] = sum;
1355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += LPC_GAIN_ORDER;
1357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Scaling, mean addition, and gain restoration. */
1361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
1362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
1363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
1364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += WebRtcIsac_kLpcMeansGain[posg];
1365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LPCCoef_lo[k * (LPC_LOBAND_ORDER + 1)] = exp(sum);
1366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
1368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = tmpcoeffs_g[posg] / LPC_GAIN_SCALE;
1369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += WebRtcIsac_kLpcMeansGain[posg];
1370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LPCCoef_hi[k * (LPC_HIBAND_ORDER + 1)] = exp(sum);
1371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;
1372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
1373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_EncodeLpcGainUb(double* lpGains, Bitstr* streamdata,
1378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                int* lpcGainIndex) {
1379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double U[UB_LPC_GAIN_DIM];
1380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int idx[UB_LPC_GAIN_DIM];
1381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_ToLogDomainRemoveMean(lpGains);
1382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_DecorrelateLPGain(lpGains, U);
1383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_QuantizeLpcGain(U, idx);
1384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store the index for re-encoding for FEC. */
1385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(lpcGainIndex, idx, UB_LPC_GAIN_DIM * sizeof(int));
1386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_CorrelateLpcGain(U, lpGains);
1387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_AddMeanToLinearDomain(lpGains);
1388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcGainCdfMat,
1389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          UB_LPC_GAIN_DIM);
1390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_StoreLpcGainUb(double* lpGains, Bitstr* streamdata) {
1394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double U[UB_LPC_GAIN_DIM];
1395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int idx[UB_LPC_GAIN_DIM];
1396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_ToLogDomainRemoveMean(lpGains);
1397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_DecorrelateLPGain(lpGains, U);
1398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_QuantizeLpcGain(U, idx);
1399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcGainCdfMat,
1400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          UB_LPC_GAIN_DIM);
1401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1405fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_DecodeLpcGainUb(double* lpGains, Bitstr* streamdata) {
1406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double U[UB_LPC_GAIN_DIM];
1407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int idx[UB_LPC_GAIN_DIM];
1408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
1409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(idx, streamdata,
1410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kLpcGainCdfMat,
1411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kLpcGainEntropySearch,
1412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       UB_LPC_GAIN_DIM);
1413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
1414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
1415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_DequantizeLpcGain(idx, U);
1417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_CorrelateLpcGain(U, lpGains);
1418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_AddMeanToLinearDomain(lpGains);
1419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize RC */
1425fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_DecodeRc(Bitstr* streamdata, int16_t* RCQ15) {
1426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, err;
1427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index[AR_ORDER];
1428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of quantization indices */
1430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(index, streamdata,
1431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kQArRcCdfPtr,
1432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kQArRcInitIndex, AR_ORDER);
1433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0)
1434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
1435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization levels for reflection coefficients */
1437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < AR_ORDER; k++) {
1438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
1439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* quantize & code RC */
1445fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsac_EncodeRc(int16_t* RCQ15, Bitstr* streamdata) {
1446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
1447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index[AR_ORDER];
1448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* quantize reflection coefficients (add noise feedback?) */
1450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < AR_ORDER; k++) {
1451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index[k] = WebRtcIsac_kQArRcInitIndex[k];
1452febbabbdb781402c24d22b29980396445b10d725turaj@webrtc.org    // The safe-guards in following while conditions are to suppress gcc 4.8.3
1453febbabbdb781402c24d22b29980396445b10d725turaj@webrtc.org    // warnings, Issue 2888. Otherwise, first and last elements of
1454febbabbdb781402c24d22b29980396445b10d725turaj@webrtc.org    // |WebRtcIsac_kQArBoundaryLevels| are such that the following search
1455febbabbdb781402c24d22b29980396445b10d725turaj@webrtc.org    // *never* cause an out-of-boundary read.
1456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k]]) {
1457febbabbdb781402c24d22b29980396445b10d725turaj@webrtc.org      while (index[k] + 1 < NUM_AR_RC_QUANT_BAUNDARY &&
1458febbabbdb781402c24d22b29980396445b10d725turaj@webrtc.org        RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k] + 1]) {
1459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        index[k]++;
1460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
1462febbabbdb781402c24d22b29980396445b10d725turaj@webrtc.org      while (index[k] > 0 &&
1463febbabbdb781402c24d22b29980396445b10d725turaj@webrtc.org        RCQ15[k] < WebRtcIsac_kQArBoundaryLevels[--index[k]]) ;
1464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
1466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization indices */
1469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, index, WebRtcIsac_kQArRcCdfPtr, AR_ORDER);
1470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize squared Gain */
1474fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_DecodeGain2(Bitstr* streamdata, int32_t* gainQ10) {
1475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index, err;
1476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of quantization index */
1478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(&index, streamdata,
1479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kQGainCdf_ptr,
1480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kQGainInitIndex, 1);
1481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
1482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
1483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization level */
1485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *gainQ10 = WebRtcIsac_kQGain2Levels[index];
1486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* quantize & code squared Gain */
1491fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_EncodeGain2(int32_t* gainQ10, Bitstr* streamdata) {
1492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index;
1493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization index */
1495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  index = WebRtcIsac_kQGainInitIndex[0];
1496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index]) {
1497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    while (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index + 1]) {
1498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index++;
1499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    while (*gainQ10 < WebRtcIsac_kQGain2BoundaryLevels[--index]) ;
1502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* De-quantize */
1504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *gainQ10 = WebRtcIsac_kQGain2Levels[index];
1505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization index */
1507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, &index, WebRtcIsac_kQGainCdf_ptr, 1);
1508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* code and decode Pitch Gains and Lags functions */
1513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize Pitch Gains */
1515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_DecodePitchGain(Bitstr* streamdata,
1516fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                               int16_t* PitchGains_Q12) {
1517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index_comb, err;
1518fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
1519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Entropy decoding of quantization indices */
1521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
1522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistBisectMulti(&index_comb, streamdata,
1523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      WebRtcIsac_kQPitchGainCdf_ptr,
1524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                      WebRtcIsac_kQCdfTableSizeGain, 1);
1525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Error check, Q_mean_Gain.. tables are of size 144 */
1526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((err < 0) || (index_comb < 0) || (index_comb >= 144)) {
1527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
1528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* De-quantize back to pitch gains by table look-up. */
1530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
1531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
1532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
1533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
1534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Quantize & code Pitch Gains. */
1539fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsac_EncodePitchGain(int16_t* PitchGains_Q12,
1540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                Bitstr* streamdata,
1541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                ISAC_SaveEncData_t* encData) {
1542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, j;
1543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double C;
1544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double S[PITCH_SUBFRAMES];
1545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index[3];
1546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index_comb;
1547fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
1548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double PitchGains[PITCH_SUBFRAMES] = {0, 0, 0, 0};
1549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Take the asin. */
1551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
1553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    S[k] = asin(PitchGains[k]);
1554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find quantization index; only for the first three
1557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * transform coefficients. */
1558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < 3; k++) {
1559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /*  transform */
1560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    C = 0.0;
1561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (j = 0; j < PITCH_SUBFRAMES; j++) {
1562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      C += WebRtcIsac_kTransform[k][j] * S[j];
1563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Quantize */
1565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index[k] = WebRtcIsac_lrint(C / PITCH_GAIN_STEPSIZE);
1566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Check that the index is not outside the boundaries of the table. */
1568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index[k] < WebRtcIsac_kIndexLowerLimitGain[k]) {
1569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index[k] = WebRtcIsac_kIndexLowerLimitGain[k];
1570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (index[k] > WebRtcIsac_kIndexUpperLimitGain[k]) {
1571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index[k] = WebRtcIsac_kIndexUpperLimitGain[k];
1572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index[k] -= WebRtcIsac_kIndexLowerLimitGain[k];
1574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Calculate unique overall index. */
1577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  index_comb = WebRtcIsac_kIndexMultsGain[0] * index[0] +
1578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_kIndexMultsGain[1] * index[1] + index[2];
1579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* unquantize back to pitch gains by table look-up */
1581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
1582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
1583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
1584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
1585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization pitch gains */
1587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
1588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, &index_comb,
1589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          WebRtcIsac_kQPitchGainCdf_ptr, 1);
1590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  encData->pitchGain_index[encData->startIdx] = index_comb;
1591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Pitch LAG */
1596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Decode & de-quantize Pitch Lags. */
1597fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_DecodePitchLag(Bitstr* streamdata, int16_t* PitchGain_Q12,
1598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              double* PitchLags) {
1599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, err;
1600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double StepSize;
1601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double C;
1602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index[PITCH_SUBFRAMES];
1603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double mean_gain;
1604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const double* mean_val2, *mean_val3, *mean_val4;
1605fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t* lower_limit;
1606fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t* init_index;
1607fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t* cdf_size;
1608fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t** cdf;
1609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double PitchGain[4] = {0, 0, 0, 0};
1610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* compute mean pitch gain */
1612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mean_gain = 0.0;
1613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < 4; k++) {
1614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchGain[k] = ((float)PitchGain_Q12[k]) / 4096;
1615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_gain += PitchGain[k];
1616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mean_gain /= 4.0;
1618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* voicing classification. */
1620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mean_gain < 0.2) {
1621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
1622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
1623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf_size = WebRtcIsac_kQPitchLagCdfSizeLo;
1624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2 = WebRtcIsac_kQMeanLag2Lo;
1625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val3 = WebRtcIsac_kQMeanLag3Lo;
1626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4 = WebRtcIsac_kQMeanLag4Lo;
1627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
1628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    init_index = WebRtcIsac_kQInitIndexLagLo;
1629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if (mean_gain < 0.4) {
1630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
1631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
1632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf_size = WebRtcIsac_kQPitchLagCdfSizeMid;
1633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2 = WebRtcIsac_kQMeanLag2Mid;
1634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val3 = WebRtcIsac_kQMeanLag3Mid;
1635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4 = WebRtcIsac_kQMeanLag4Mid;
1636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
1637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    init_index = WebRtcIsac_kQInitIndexLagMid;
1638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
1640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
1641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf_size = WebRtcIsac_kQPitchLagCdfSizeHi;
1642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2 = WebRtcIsac_kQMeanLag2Hi;
1643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val3 = WebRtcIsac_kQMeanLag3Hi;
1644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4 = WebRtcIsac_kQMeanLag4Hi;
1645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
1646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    init_index = WebRtcIsac_kQInitIndexLagHi;
1647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Entropy decoding of quantization indices. */
1650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
1651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((err < 0) || (index[0] < 0)) {
1652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
1653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(index + 1, streamdata, cdf + 1,
1655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       init_index, 3);
1656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
1657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
1658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Unquantize back to transform coefficients and do the inverse transform:
1661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * S = T'*C. */
1662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  C = (index[0] + lower_limit[0]) * StepSize;
1663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags[k] = WebRtcIsac_kTransformTranspose[k][0] * C;
1665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  C = mean_val2[index[1]];
1667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][1] * C;
1669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  C = mean_val3[index[2]];
1671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][2] * C;
1673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  C = mean_val4[index[3]];
1675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][3] * C;
1677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Quantize & code pitch lags. */
1684fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsac_EncodePitchLag(double* PitchLags, int16_t* PitchGain_Q12,
1685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               Bitstr* streamdata,
1686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               ISAC_SaveEncData_t* encData) {
1687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, j;
1688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double StepSize;
1689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double C;
1690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index[PITCH_SUBFRAMES];
1691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double mean_gain;
1692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const double* mean_val2, *mean_val3, *mean_val4;
1693fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t* lower_limit, *upper_limit;
1694fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t** cdf;
1695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double PitchGain[4] = {0, 0, 0, 0};
1696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* compute mean pitch gain */
1698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mean_gain = 0.0;
1699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < 4; k++) {
1700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchGain[k] = ((float)PitchGain_Q12[k]) / 4096;
1701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_gain += PitchGain[k];
1702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mean_gain /= 4.0;
1704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bit streams */
1706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  encData->meanGain[encData->startIdx] = mean_gain;
1707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Voicing classification. */
1709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mean_gain < 0.2) {
1710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
1711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
1712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2 = WebRtcIsac_kQMeanLag2Lo;
1713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val3 = WebRtcIsac_kQMeanLag3Lo;
1714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4 = WebRtcIsac_kQMeanLag4Lo;
1715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
1716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    upper_limit = WebRtcIsac_kQIndexUpperLimitLagLo;
1717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if (mean_gain < 0.4) {
1718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
1719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
1720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2 = WebRtcIsac_kQMeanLag2Mid;
1721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val3 = WebRtcIsac_kQMeanLag3Mid;
1722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4 = WebRtcIsac_kQMeanLag4Mid;
1723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
1724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    upper_limit = WebRtcIsac_kQIndexUpperLimitLagMid;
1725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
1727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
1728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2 = WebRtcIsac_kQMeanLag2Hi;
1729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val3 = WebRtcIsac_kQMeanLag3Hi;
1730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4 = WebRtcIsac_kQMeanLag4Hi;
1731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
1732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    upper_limit = WebRtcIsac_kQindexUpperLimitLagHi;
1733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization index */
1736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < 4; k++) {
1737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /*  transform */
1738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    C = 0.0;
1739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (j = 0; j < PITCH_SUBFRAMES; j++) {
1740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      C += WebRtcIsac_kTransform[k][j] * PitchLags[j];
1741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* quantize */
1743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index[k] = WebRtcIsac_lrint(C / StepSize);
1744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* check that the index is not outside the boundaries of the table */
1746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index[k] < lower_limit[k]) {
1747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index[k] = lower_limit[k];
1748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (index[k] > upper_limit[k]) index[k] = upper_limit[k]; {
1749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index[k] -= lower_limit[k];
1750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save data for creation of multiple bit streams */
1752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    encData->pitchIndex[PITCH_SUBFRAMES * encData->startIdx + k] = index[k];
1753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Un-quantize back to transform coefficients and do the inverse transform:
1756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * S = T'*C */
1757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  C = (index[0] + lower_limit[0]) * StepSize;
1758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags[k] = WebRtcIsac_kTransformTranspose[k][0] * C;
1760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  C = mean_val2[index[1]];
1762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][1] * C;
1764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  C = mean_val3[index[2]];
1766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][2] * C;
1768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  C = mean_val4[index[3]];
1770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
1771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags[k] += WebRtcIsac_kTransformTranspose[k][3] * C;
1772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization pitch lags */
1774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
1775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Routines for in-band signaling of bandwidth estimation */
1780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Histograms based on uniform distribution of indices */
1781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Move global variables later! */
1782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* cdf array for frame length indicator */
1785fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t WebRtcIsac_kFrameLengthCdf[4] = {
1786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0, 21845, 43690, 65535 };
1787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* pointer to cdf array for frame length indicator */
1789fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t* WebRtcIsac_kFrameLengthCdf_ptr[1] = {
1790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_kFrameLengthCdf };
1791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* initial cdf index for decoder of frame length indicator */
1793fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t WebRtcIsac_kFrameLengthInitIndex[1] = { 1 };
1794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1796fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_DecodeFrameLen(Bitstr* streamdata, int16_t* framesamples) {
1797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int frame_mode, err;
1798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = 0;
1799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of frame length [1:30ms,2:60ms] */
1800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(&frame_mode, streamdata,
1801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kFrameLengthCdf_ptr,
1802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       WebRtcIsac_kFrameLengthInitIndex, 1);
1803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0)
1804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH;
1805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (frame_mode) {
1807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 1:
1808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      *framesamples = 480; /* 30ms */
1809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 2:
1811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      *framesamples = 960; /* 60ms */
1812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
1814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      err = -ISAC_DISALLOWED_FRAME_MODE_DECODER;
1815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return err;
1817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1819fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_EncodeFrameLen(int16_t framesamples, Bitstr* streamdata) {
1820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int frame_mode, status;
1821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = 0;
1823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_mode = 0;
1824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of frame length [1:480 samples,2:960 samples] */
1825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (framesamples) {
1826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 480:
1827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      frame_mode = 1;
1828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 960:
1830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      frame_mode = 2;
1831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
1833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      status = - ISAC_DISALLOWED_FRAME_MODE_ENCODER;
1834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0)
1837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, &frame_mode,
1840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          WebRtcIsac_kFrameLengthCdf_ptr, 1);
1841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return status;
1842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* cdf array for estimated bandwidth */
1845fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const uint16_t kBwCdf[25] = {
1846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0, 2731, 5461, 8192, 10923, 13653, 16384, 19114, 21845, 24576, 27306, 30037,
1847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    32768, 35498, 38229, 40959, 43690, 46421, 49151, 51882, 54613, 57343, 60074,
1848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    62804, 65535 };
1849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* pointer to cdf array for estimated bandwidth */
1851fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const uint16_t* kBwCdfPtr[1] = { kBwCdf };
1852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* initial cdf index for decoder of estimated bandwidth*/
1854fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const uint16_t kBwInitIndex[1] = { 7 };
1855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1857fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsac_DecodeSendBW(Bitstr* streamdata, int16_t* BWno) {
1858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int BWno32, err;
1859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of sender's BW estimation [0..23] */
1861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr,
1862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       kBwInitIndex, 1);
1863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
1864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
1865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1866fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  *BWno = (int16_t)BWno32;
1867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return err;
1868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_EncodeReceiveBw(int* BWno, Bitstr* streamdata) {
1871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy encoding of receiver's BW estimation [0..23] */
1872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
1873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* estimate code length of LPC Coef */
1877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_TranscodeLPCCoef(double* LPCCoef_lo, double* LPCCoef_hi,
1878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 int* index_g) {
1879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int j, k, n, pos, pos2, posg, offsg, offs2;
1880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int index_ovr_g[KLT_ORDER_GAIN];
1881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpcoeffs_g[KLT_ORDER_GAIN];
1882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpcoeffs2_g[KLT_ORDER_GAIN];
1883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double sum;
1884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* log gains, mean removal and scaling */
1886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
1887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
1888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] = log(LPCCoef_lo[(LPC_LOBAND_ORDER + 1) * k]);
1889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
1890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
1891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
1892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] = log(LPCCoef_hi[(LPC_HIBAND_ORDER + 1) * k]);
1893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] -= WebRtcIsac_kLpcMeansGain[posg];
1894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[posg] *= LPC_GAIN_SCALE;
1895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
1896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* KLT  */
1899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Left transform. */
1901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
1902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg = offsg;
1904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_GAIN_ORDER; k++) {
1905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = offsg;
1907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = k;
1908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < LPC_GAIN_ORDER; n++) {
1909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs_g[pos++] * WebRtcIsac_kKltT1Gain[pos2];
1910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos2 += LPC_GAIN_ORDER;
1911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_g[posg++] = sum;
1913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += LPC_GAIN_ORDER;
1915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Right transform. */
1918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
1919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offs2 = 0;
1920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
1921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg = offsg;
1922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < LPC_GAIN_ORDER; k++) {
1923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum = 0;
1924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos = k;
1925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      pos2 = offs2;
1926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < SUBFRAMES; n++) {
1927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sum += tmpcoeffs2_g[pos] * WebRtcIsac_kKltT2Gain[pos2++];
1928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos += LPC_GAIN_ORDER;
1929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_g[posg++] = sum;
1931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offs2 += SUBFRAMES;
1933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += LPC_GAIN_ORDER;
1934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* quantize coefficients */
1938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < KLT_ORDER_GAIN; k++) {
1939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Get index. */
1940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos2 = WebRtcIsac_lrint(tmpcoeffs_g[k] / KLT_STEPSIZE);
1941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_g[k] = (pos2) + WebRtcIsac_kQKltQuantMinGain[k];
1942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index_g[k] < 0) {
1943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_g[k] = 0;
1944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (index_g[k] > WebRtcIsac_kQKltMaxIndGain[k]) {
1945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
1946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[k] + index_g[k];
1948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* find quantization levels for coefficients */
1950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_g[k] = WebRtcIsac_kQKltLevelsGain[index_ovr_g[k]];
1951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Decode & de-quantize LPC Coefficients. */
1956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_DecodeLpcCoefUB(Bitstr* streamdata, double* lpcVecs,
1957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               double* percepFilterGains,
1958fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                               int16_t bandwidth) {
1959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int  index_s[KLT_ORDER_SHAPE];
1960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
1962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
1963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Entropy decoding of quantization indices. */
1965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (bandwidth) {
1966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac12kHz: {
1967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      err = WebRtcIsac_DecHistOneStepMulti(
1968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb12,
1969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          WebRtcIsac_kLpcShapeEntropySearchUb12, UB_LPC_ORDER *
1970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          UB_LPC_VEC_PER_FRAME);
1971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac16kHz: {
1974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      err = WebRtcIsac_DecHistOneStepMulti(
1975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          index_s, streamdata, WebRtcIsac_kLpcShapeCdfMatUb16,
1976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          WebRtcIsac_kLpcShapeEntropySearchUb16, UB_LPC_ORDER *
1977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          UB16_LPC_VEC_PER_FRAME);
1978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
1981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -1;
1982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
1985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
1986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_DequantizeLpcParam(index_s, lpcVecs, bandwidth);
1989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
1990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
1991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
1992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_DecodeLpcGainUb(percepFilterGains, streamdata);
1993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (bandwidth == isac16kHz) {
1995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Decode another set of Gains. */
1996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_DecodeLpcGainUb(&percepFilterGains[SUBFRAMES], streamdata);
1997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2001fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_EncodeBandwidth(enum ISACBandwidth bandwidth,
2002fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                   Bitstr* streamData) {
2003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int bandwidthMode;
2004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (bandwidth) {
2005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac12kHz: {
2006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bandwidthMode = 0;
2007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
2008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case isac16kHz: {
2010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bandwidthMode = 1;
2011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
2012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
2014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -ISAC_DISALLOWED_ENCODER_BANDWIDTH;
2015b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamData, &bandwidthMode, kOneBitEqualProbCdf_ptr,
2017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          1);
2018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
2019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2021fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_DecodeBandwidth(Bitstr* streamData,
2022fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                   enum ISACBandwidth* bandwidth) {
2023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int bandwidthMode;
2024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcIsac_DecHistOneStepMulti(&bandwidthMode, streamData,
2025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     kOneBitEqualProbCdf_ptr,
2026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     kOneBitEqualProbInitIndex, 1) < 0) {
2027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
2028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (bandwidthMode) {
2030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 0: {
2031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      *bandwidth = isac12kHz;
2032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
2033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 1: {
2035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      *bandwidth = isac16kHz;
2036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
2037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
2039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER;
2040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
2042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2044fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_EncodeJitterInfo(int32_t jitterIndex,
2045fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                    Bitstr* streamData) {
2046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* This is to avoid LINUX warning until we change 'int' to 'Word32'. */
2047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int intVar;
2048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((jitterIndex < 0) || (jitterIndex > 1)) {
2050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
2051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  intVar = (int)(jitterIndex);
2053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Use the same CDF table as for bandwidth
2054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * both take two values with equal probability.*/
2055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(streamData, &intVar, kOneBitEqualProbCdf_ptr, 1);
2056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
2057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2059fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_DecodeJitterInfo(Bitstr* streamData,
2060fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                    int32_t* jitterInfo) {
2061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int intVar;
2062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Use the same CDF table as for bandwidth
2063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * both take two values with equal probability. */
2064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcIsac_DecHistOneStepMulti(&intVar, streamData,
2065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     kOneBitEqualProbCdf_ptr,
2066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     kOneBitEqualProbInitIndex, 1) < 0) {
2067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
2068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2069fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  *jitterInfo = (int16_t)(intVar);
2070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
2071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2072