1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2011 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 file contains all functions used to arithmetically
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * encode the iSAC bistream.
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stddef.h>
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "arith_routins.h"
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "spectrum_ar_model_tables.h"
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pitch_gain_tables.h"
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pitch_lag_tables.h"
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "entropy_coding.h"
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_tables.h"
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "settings.h"
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "signal_processing_library.h"
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
306b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org/*
316b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org * Eenumerations for arguments to functions WebRtcIsacfix_MatrixProduct1()
326b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org * and WebRtcIsacfix_MatrixProduct2().
336b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org*/
346b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
356b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgenum matrix_index_factor {
366b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTIndexFactor1 = 1,
376b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTIndexFactor2 = 2,
386b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTIndexFactor3 = SUBFRAMES,
396b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTIndexFactor4 = LPC_SHAPE_ORDER
406b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org};
416b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
426b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgenum matrix_index_step {
436b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTIndexStep1 = 1,
446b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTIndexStep2 = SUBFRAMES,
456b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTIndexStep3 = LPC_SHAPE_ORDER
466b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org};
476b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
486b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgenum matrixprod_loop_count {
496b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTLoopCount1 = SUBFRAMES,
506b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTLoopCount2 = 2,
516b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTLoopCount3 = LPC_SHAPE_ORDER
526b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org};
536b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
546b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgenum matrix1_shift_value {
556b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTMatrix1_shift0 = 0,
566b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTMatrix1_shift1 = 1,
576b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTMatrix1_shift5 = 5
586b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org};
596b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
606b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgenum matrixprod_init_case {
616b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTInitCase0 = 0,
626b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  kTInitCase1 = 1
636b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org};
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  This function implements the fix-point correspondant function to lrint.
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
68fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  FLP: (int32_t)floor(flt+.499999999999)
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FIP: (fixVal+roundVal)>>qDomain
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  where roundVal = 2^(qDomain-1) = 1<<(qDomain-1)
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org*/
74fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic __inline int32_t CalcLrIntQ(int32_t fixVal, int16_t qDomain) {
75fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t intgr;
76fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t roundVal;
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
78fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  roundVal = WEBRTC_SPL_LSHIFT_W32((int32_t)1, qDomain-1);
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  intgr = WEBRTC_SPL_RSHIFT_W32(fixVal+roundVal, qDomain);
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return intgr;
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
85fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  __inline uint32_t stepwise(int32_t dinQ10) {
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
87fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t ind, diQ10, dtQ10;
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  diQ10 = dinQ10;
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (diQ10 < DPMIN_Q10)
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  diQ10 = DPMIN_Q10;
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (diQ10 >= DPMAX_Q10)
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  diQ10 = DPMAX_Q10 - 1;
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  dtQ10 = diQ10 - DPMIN_Q10;*/ /* Q10 + Q10 = Q10 */
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* ind = (dtQ10 * 5) >> 10;  */ /* 2^10 / 5 = 0.2 in Q10  */
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Q10 -> Q0 */
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* return rpointsFIX_Q10[ind];
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   }
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org*/
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* logN(x) = logN(2)*log2(x) = 0.6931*log2(x). Output in Q8. */
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* The input argument X to logN(X) is 2^17 times higher than the
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   input floating point argument Y to log(Y), since the X value
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   is a Q17 value. This can be compensated for after the call, by
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   subraction a value Z for each Q-step. One Q-step means that
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   X gets 2 thimes higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   177.445678 should be subtracted (since logN() returns a Q8 value).
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   For a X value in Q17, the value 177.445678*17 = 3017 should be
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   subtracted */
113fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic int16_t CalcLogN(int32_t arg) {
114fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t zeros, log2, frac, logN;
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  zeros=WebRtcSpl_NormU32(arg);
117fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  frac=(int16_t)WEBRTC_SPL_RSHIFT_U32(WEBRTC_SPL_LSHIFT_W32(arg, zeros)&0x7FFFFFFF, 23);
118fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  log2=(int16_t)(WEBRTC_SPL_LSHIFT_W32(31-zeros, 8)+frac); // log2(x) in Q8
119fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  logN=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(log2,22713,15); //Q8*Q15 log(2) = 0.693147 = 22713 in Q15
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  logN=logN+11; //Scalar compensation which minimizes the (log(x)-logN(x))^2 error over all x.
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return logN;
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  expN(x) = 2^(a*x), where a = log2(e) ~= 1.442695
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
129fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  Input:  Q8  (int16_t)
130fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  Output: Q17 (int32_t)
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  a = log2(e) = log2(exp(1)) ~= 1.442695  ==>  a = 23637 in Q14 (1.442688)
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  To this value, 700 is added or subtracted in order to get an average error
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  nearer zero, instead of always same-sign.
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org*/
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
137fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic int32_t CalcExpN(int16_t x) {
138fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t ax, axINT, axFRAC;
139fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t exp16;
140fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t exp;
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (x>=0) {
143fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    //  ax=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637-700, 14); //Q8
144fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    ax=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637, 14); //Q8
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    axINT = WEBRTC_SPL_RSHIFT_W16(ax, 8); //Q0
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    axFRAC = ax&0x00FF;
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    exp16 = WEBRTC_SPL_LSHIFT_W32(1, axINT); //Q0
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    axFRAC = axFRAC+256; //Q8
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    exp = WEBRTC_SPL_MUL_16_16(exp16, axFRAC); // Q0*Q8 = Q8
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    exp = WEBRTC_SPL_LSHIFT_W32(exp, 9); //Q17
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
152fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    //  ax=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637+700, 14); //Q8
153fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    ax=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT(x, 23637, 14); //Q8
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ax = -ax;
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    axINT = 1 + WEBRTC_SPL_RSHIFT_W16(ax, 8); //Q0
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    axFRAC = 0x00FF - (ax&0x00FF);
157fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    exp16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(32768, axINT); //Q15
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    axFRAC = axFRAC+256; //Q8
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    exp = WEBRTC_SPL_MUL_16_16(exp16, axFRAC); // Q15*Q8 = Q23
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    exp = WEBRTC_SPL_RSHIFT_W32(exp, 6); //Q17
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return exp;
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* compute correlation from power spectrum */
168fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void CalcCorrelation(int32_t *PSpecQ12, int32_t *CorrQ7)
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
170fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t summ[FRAMESAMPLES/8];
171fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t diff[FRAMESAMPLES/8];
172fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sum;
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, n;
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES/8; k++) {
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    summ[k] = WEBRTC_SPL_RSHIFT_W32(PSpecQ12[k] + PSpecQ12[FRAMESAMPLES/4-1 - k] + 16, 5);
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    diff[k] = WEBRTC_SPL_RSHIFT_W32(PSpecQ12[k] - PSpecQ12[FRAMESAMPLES/4-1 - k] + 16, 5);
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = 2;
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES/8; n++)
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += summ[n];
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CorrQ7[0] = sum;
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < AR_ORDER; k += 2) {
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = 0;
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES/8; n++)
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WebRtcIsacfix_kCos[k][n], diff[n]) + 256, 9);
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CorrQ7[k+1] = sum;
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=1; k<AR_ORDER; k+=2) {
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = 0;
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES/8; n++)
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WebRtcIsacfix_kCos[k][n], summ[n]) + 256, 9);
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CorrQ7[k+1] = sum;
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* compute inverse AR power spectrum */
202fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void CalcInvArSpec(const int16_t *ARCoefQ12,
203fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          const int32_t gainQ10,
204fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int32_t *CurveQ16)
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
206fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t CorrQ11[AR_ORDER+1];
207fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sum, tmpGain;
208fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t diffQ16[FRAMESAMPLES/8];
209fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t *CS_ptrQ9;
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, n;
211fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t round, shftVal = 0, sh;
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = 0;
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < AR_ORDER+1; n++)
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]);    /* Q24 */
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(sum, 6), 65) + 32768, 16);    /* result in Q8 */
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CorrQ11[0] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, gainQ10) + 256, 9);
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if(gainQ10>400000){
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpGain = WEBRTC_SPL_RSHIFT_W32(gainQ10, 3);
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    round = 32;
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 6;
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpGain = gainQ10;
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    round = 256;
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 9;
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 1; k < AR_ORDER+1; k++) {
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = 16384;
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = k; n < AR_ORDER+1; n++)
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]);  /* Q24 */
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = WEBRTC_SPL_RSHIFT_W32(sum, 15);
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CorrQ11[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, tmpGain) + round, shftVal);
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = WEBRTC_SPL_LSHIFT_W32(CorrQ11[0], 7);
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES/8; n++)
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CurveQ16[n] = sum;
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 1; k < AR_ORDER; k += 2) {
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES/8; n++)
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      CurveQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WebRtcIsacfix_kCos[k][n], CorrQ11[k+1]) + 2, 2);
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CS_ptrQ9 = WebRtcIsacfix_kCos[0];
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sh=WebRtcSpl_NormW32(CorrQ11[1]);
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (CorrQ11[1]==0) /* Use next correlation */
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sh=WebRtcSpl_NormW32(CorrQ11[2]);
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (sh<9)
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 9 - sh;
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 0;
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES/8; n++)
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    diffQ16[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[1], shftVal)) + 2, 2);
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 2; k < AR_ORDER; k += 2) {
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CS_ptrQ9 = WebRtcIsacfix_kCos[k];
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES/8; n++)
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      diffQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[k+1], shftVal)) + 2, 2);
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<FRAMESAMPLES/8; k++) {
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CurveQ16[FRAMESAMPLES/4-1 - k] = CurveQ16[k] - WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CurveQ16[k] += WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
272fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void CalcRootInvArSpec(const int16_t *ARCoefQ12,
273fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                              const int32_t gainQ10,
274fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                              uint16_t *CurveQ8)
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
276fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t CorrQ11[AR_ORDER+1];
277fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sum, tmpGain;
278fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t summQ16[FRAMESAMPLES/8];
279fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t diffQ16[FRAMESAMPLES/8];
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
281fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t *CS_ptrQ9;
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, n, i;
283fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t round, shftVal = 0, sh;
284fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t res, in_sqrt, newRes;
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = 0;
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < AR_ORDER+1; n++)
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]);    /* Q24 */
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(sum, 6), 65) + 32768, 16);    /* result in Q8 */
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CorrQ11[0] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, gainQ10) + 256, 9);
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if(gainQ10>400000){
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpGain = WEBRTC_SPL_RSHIFT_W32(gainQ10, 3);
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    round = 32;
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 6;
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpGain = gainQ10;
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    round = 256;
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 9;
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 1; k < AR_ORDER+1; k++) {
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = 16384;
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = k; n < AR_ORDER+1; n++)
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]);  /* Q24 */
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = WEBRTC_SPL_RSHIFT_W32(sum, 15);
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CorrQ11[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, tmpGain) + round, shftVal);
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sum = WEBRTC_SPL_LSHIFT_W32(CorrQ11[0], 7);
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES/8; n++)
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    summQ16[n] = sum;
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 1; k < (AR_ORDER); k += 2) {
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES/8; n++)
3169cfe80329340de096ed8e7e2d8b109611d85b3d0bjornv@webrtc.org      summQ16[n] += ((CorrQ11[k + 1] * WebRtcIsacfix_kCos[k][n]) + 2) >> 2;
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CS_ptrQ9 = WebRtcIsacfix_kCos[0];
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  sh=WebRtcSpl_NormW32(CorrQ11[1]);
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (CorrQ11[1]==0) /* Use next correlation */
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sh=WebRtcSpl_NormW32(CorrQ11[2]);
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (sh<9)
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 9 - sh;
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shftVal = 0;
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES/8; n++)
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    diffQ16[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[1], shftVal)) + 2, 2);
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 2; k < AR_ORDER; k += 2) {
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CS_ptrQ9 = WebRtcIsacfix_kCos[k];
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES/8; n++)
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      diffQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[k+1], shftVal)) + 2, 2);
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  in_sqrt = summQ16[0] + WEBRTC_SPL_LSHIFT_W32(diffQ16[0], shftVal);
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB)  */
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  res = WEBRTC_SPL_LSHIFT_W32(1, WEBRTC_SPL_RSHIFT_W16(WebRtcSpl_GetSizeInBits(in_sqrt), 1));
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES/8; k++)
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    in_sqrt = summQ16[k] + WEBRTC_SPL_LSHIFT_W32(diffQ16[k], shftVal);
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    i = 10;
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* make in_sqrt positive to prohibit sqrt of negative values */
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(in_sqrt<0)
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      in_sqrt=-in_sqrt;
352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3535b3e14c36bf3cf2a0cda2e25895f61b6e3df922dbjornv@webrtc.org    newRes = (in_sqrt / res + res) >> 1;
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    do
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      res = newRes;
3575b3e14c36bf3cf2a0cda2e25895f61b6e3df922dbjornv@webrtc.org      newRes = (in_sqrt / res + res) >> 1;
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } while (newRes != res && i-- > 0);
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
360fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    CurveQ8[k] = (int16_t)newRes;
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = FRAMESAMPLES/8; k < FRAMESAMPLES/4; k++) {
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    in_sqrt = summQ16[FRAMESAMPLES/4-1 - k] - WEBRTC_SPL_LSHIFT_W32(diffQ16[FRAMESAMPLES/4-1 - k], shftVal);
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    i = 10;
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* make in_sqrt positive to prohibit sqrt of negative values */
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(in_sqrt<0)
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      in_sqrt=-in_sqrt;
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3715b3e14c36bf3cf2a0cda2e25895f61b6e3df922dbjornv@webrtc.org    newRes = (in_sqrt / res + res) >> 1;
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    do
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      res = newRes;
3755b3e14c36bf3cf2a0cda2e25895f61b6e3df922dbjornv@webrtc.org      newRes = (in_sqrt / res + res) >> 1;
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } while (newRes != res && i-- > 0);
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
378fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    CurveQ8[k] = (int16_t)newRes;
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* generate array of dither samples in Q7 */
386fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void GenerateDitherQ7(int16_t *bufQ7,
387fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                             uint32_t seed,
388fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                             int16_t length,
389fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                             int16_t AvgPitchGain_Q12)
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int   k;
392fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t dither1_Q7, dither2_Q7, dither_gain_Q14, shft;
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (AvgPitchGain_Q12 < 614)  /* this threshold should be equal to that in decode_spec() */
395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < length-2; k += 3)
397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
398fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      /* new random unsigned int32_t */
399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* fixed-point dither sample between -64 and 64 (Q7) */
402fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      dither1_Q7 = (int16_t)WEBRTC_SPL_RSHIFT_W32((int32_t)seed + 16777216, 25); // * 128/4294967295
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
404fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      /* new random unsigned int32_t */
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* fixed-point dither sample between -64 and 64 */
408fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      dither2_Q7 = (int16_t)WEBRTC_SPL_RSHIFT_W32(seed + 16777216, 25);
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
410fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      shft = (int16_t)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 15);
411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (shft < 5)
412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      {
413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k]   = dither1_Q7;
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k+1] = dither2_Q7;
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k+2] = 0;
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      else if (shft < 10)
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      {
419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k]   = dither1_Q7;
420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k+1] = 0;
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k+2] = dither2_Q7;
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      else
424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      {
425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k]   = 0;
426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k+1] = dither1_Q7;
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        bufQ7[k+2] = dither2_Q7;
428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else
432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
433fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    dither_gain_Q14 = (int16_t)(22528 - WEBRTC_SPL_MUL(10, AvgPitchGain_Q12));
434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* dither on half of the coefficients */
436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < length-1; k += 2)
437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
438fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      /* new random unsigned int32_t */
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* fixed-point dither sample between -64 and 64 */
442fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      dither1_Q7 = (int16_t)WEBRTC_SPL_RSHIFT_W32((int32_t)seed + 16777216, 25);
443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* dither sample is placed in either even or odd index */
445fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      shft = (int16_t)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 1);     /* either 0 or 1 */
446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
447fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      bufQ7[k + shft] = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(dither_gain_Q14, dither1_Q7) + 8192, 14);
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bufQ7[k + 1 - shft] = 0;
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * function to decode the complex spectrum from the bitstream
458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * returns the total number of bytes in the stream
459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
460fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsacfix_DecodeSpec(Bitstr_dec *streamdata,
461fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                 int16_t *frQ7,
462fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                 int16_t *fiQ7,
463fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                 int16_t AvgPitchGain_Q12)
464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
465fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  data[FRAMESAMPLES];
466fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  invARSpec2_Q16[FRAMESAMPLES/4];
467fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  ARCoefQ12[AR_ORDER+1];
468fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  RCQ15[AR_ORDER];
469fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  gainQ10;
470fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  gain2_Q10;
471fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  len;
472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int          k;
473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* create dither signal */
475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  GenerateDitherQ7(data, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* Dither is output in vector 'Data' */
476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* decode model parameters */
478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcIsacfix_DecodeRcCoef(streamdata, RCQ15) < 0)
479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcIsacfix_DecodeGain2(streamdata, &gain2_Q10) < 0)
485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* compute inverse AR power spectrum */
488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CalcInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* arithmetic decoding of spectrum */
491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* 'data' input and output. Input = Dither */
492fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  len = WebRtcIsacfix_DecLogisticMulti2(data, streamdata, invARSpec2_Q16, (int16_t)FRAMESAMPLES);
493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (len<1)
495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* subtract dither and scale down spectral samples with low SNR */
498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (AvgPitchGain_Q12 <= 614)
499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < FRAMESAMPLES; k += 4)
501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
502fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      gainQ10 = WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_LSHIFT_W32((int32_t)30, 10),
503fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                              (int16_t)WEBRTC_SPL_RSHIFT_U32(invARSpec2_Q16[k>>2] + (uint32_t)2195456, 16));
504fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *frQ7++ = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[ k ], gainQ10) + 512, 10);
505fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *fiQ7++ = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+1], gainQ10) + 512, 10);
506fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *frQ7++ = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+2], gainQ10) + 512, 10);
507fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *fiQ7++ = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+3], gainQ10) + 512, 10);
508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else
511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < FRAMESAMPLES; k += 4)
513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
514fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      gainQ10 = WebRtcSpl_DivW32W16ResW16(WEBRTC_SPL_LSHIFT_W32((int32_t)36, 10),
515fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                              (int16_t)WEBRTC_SPL_RSHIFT_U32(invARSpec2_Q16[k>>2] + (uint32_t)2654208, 16));
516fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *frQ7++ = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[ k ], gainQ10) + 512, 10);
517fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *fiQ7++ = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+1], gainQ10) + 512, 10);
518fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *frQ7++ = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+2], gainQ10) + 512, 10);
519fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *fiQ7++ = (int16_t)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(data[k+3], gainQ10) + 512, 10);
520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return len;
524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
527fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EncodeSpec(const int16_t *fr,
528fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                             const int16_t *fi,
529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             Bitstr_enc *streamdata,
530fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                             int16_t AvgPitchGain_Q12)
531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
532fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  dataQ7[FRAMESAMPLES];
533fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  PSpec[FRAMESAMPLES/4];
534fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint16_t invARSpecQ8[FRAMESAMPLES/4];
535fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  CorrQ7[AR_ORDER+1];
536fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  CorrQ7_norm[AR_ORDER+1];
537fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  RCQ15[AR_ORDER];
538fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  ARCoefQ12[AR_ORDER+1];
539fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  gain2_Q10;
540fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  val;
541fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t  nrg;
542fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint32_t sum;
543fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  lft_shft;
544fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  status;
545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int          k, n, j;
546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* create dither_float signal */
549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  GenerateDitherQ7(dataQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12);
550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* add dither and quantize, and compute power spectrum */
552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Vector dataQ7 contains Dither in Q7 */
553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES; k += 4)
554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    val = ((*fr++ + dataQ7[k]   + 64) & 0xFF80) - dataQ7[k]; /* Data = Dither */
556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    dataQ7[k] = val;            /* New value in Data */
557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum = WEBRTC_SPL_UMUL(val, val);
558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    val = ((*fi++ + dataQ7[k+1] + 64) & 0xFF80) - dataQ7[k+1]; /* Data = Dither */
560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    dataQ7[k+1] = val;            /* New value in Data */
561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += WEBRTC_SPL_UMUL(val, val);
562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    val = ((*fr++ + dataQ7[k+2] + 64) & 0xFF80) - dataQ7[k+2]; /* Data = Dither */
564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    dataQ7[k+2] = val;            /* New value in Data */
565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += WEBRTC_SPL_UMUL(val, val);
566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    val = ((*fi++ + dataQ7[k+3] + 64) & 0xFF80) - dataQ7[k+3]; /* Data = Dither */
568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    dataQ7[k+3] = val;            /* New value in Data */
569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sum += WEBRTC_SPL_UMUL(val, val);
570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PSpec[k>>2] = WEBRTC_SPL_RSHIFT_U32(sum, 2);
572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* compute correlation from power spectrum */
575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CalcCorrelation(PSpec, CorrQ7);
576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find AR coefficients */
579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* number of bit shifts to 14-bit normalize CorrQ7[0] (leaving room for sign) */
580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  lft_shft = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (lft_shft > 0) {
583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k=0; k<AR_ORDER+1; k++)
584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      CorrQ7_norm[k] = WEBRTC_SPL_LSHIFT_W32(CorrQ7[k], lft_shft);
585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k=0; k<AR_ORDER+1; k++)
587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      CorrQ7_norm[k] = WEBRTC_SPL_RSHIFT_W32(CorrQ7[k], -lft_shft);
588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find RC coefficients */
591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* quantize & code RC Coef */
594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncodeRcCoef(RCQ15, streamdata);
595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* RC -> AR coefficients */
600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* compute ARCoef' * Corr * ARCoef in Q19 */
603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  nrg = 0;
604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j = 0; j <= AR_ORDER; j++) {
605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n <= j; n++)
606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      nrg += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(ARCoefQ12[j], WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CorrQ7_norm[j-n], ARCoefQ12[n]) + 256, 9)) + 4, 3);
607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = j+1; n <= AR_ORDER; n++)
608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      nrg += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(ARCoefQ12[j], WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CorrQ7_norm[n-j], ARCoefQ12[n]) + 256, 9)) + 4, 3);
609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (lft_shft > 0)
612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    nrg = WEBRTC_SPL_RSHIFT_W32(nrg, lft_shft);
613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else
614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    nrg = WEBRTC_SPL_LSHIFT_W32(nrg, -lft_shft);
615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if(nrg>131072)
617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES >> 2, nrg);  /* also shifts 31 bits to the left! */
618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else
619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    gain2_Q10 = WEBRTC_SPL_RSHIFT_W32(FRAMESAMPLES, 2);
620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* quantize & code gain2_Q10 */
622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcIsacfix_EncodeGain2(&gain2_Q10, streamdata))
623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* compute inverse AR magnitude spectrum */
626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CalcRootInvArSpec(ARCoefQ12, gain2_Q10, invARSpecQ8);
627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* arithmetic coding of spectrum */
630fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  status = WebRtcIsacfix_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, (int16_t)FRAMESAMPLES);
631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ( status )
632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return( status );
633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Matlab's LAR definition */
639fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void Rc2LarFix(const int16_t *rcQ15, int32_t *larQ17, int16_t order) {
640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /*
642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    This is a piece-wise implemenetation of a rc2lar-function (all values in the comment
644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    are Q15 values and  are based on [0 24956/32768 30000/32768 32500/32768], i.e.
645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    [0.76159667968750   0.91552734375000   0.99182128906250]
646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    x0  x1           a                 k              x0(again)         b
648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ==================================================================================
649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0.00 0.76:   0                  2.625997508581   0                  0
650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0.76 0.91:   2.000012018559     7.284502668663   0.761596679688    -3.547841027073
651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0.91 0.99:   3.121320351712    31.115835041229   0.915527343750   -25.366077452148
652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    0.99 1.00:   5.495270168700   686.663805654056   0.991821289063  -675.552510708011
653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    The implementation is y(x)= a + (x-x0)*k, but this can be simplified to
655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    y(x) = a-x0*k + x*k = b + x*k, where b = a-x0*k
657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    akx=[0                 2.625997508581   0
659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    2.000012018559     7.284502668663   0.761596679688
660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    3.121320351712    31.115835041229   0.915527343750
661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    5.495270168700   686.663805654056   0.991821289063];
662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    b = akx(:,1) - akx(:,3).*akx(:,2)
664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    [ 0.0
666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    -3.547841027073
667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    -25.366077452148
668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    -675.552510708011]
669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  */
671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
673fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t rc;
674fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t larAbsQ17;
675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < order; k++) {
677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rc = WEBRTC_SPL_ABS_W16(rcQ15[k]); //Q15
679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Calculate larAbsQ17 in Q17 from rc in Q15 */
681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (rc<24956) {  //0.7615966 in Q15
683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // (Q15*Q13)>>11 = Q17
684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      larAbsQ17 = WEBRTC_SPL_MUL_16_16_RSFT(rc, 21512, 11);
685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (rc<30000) { //0.91552734375 in Q15
686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // Q17 + (Q15*Q12)>>10 = Q17
687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      larAbsQ17 = -465024 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 29837, 10);
688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (rc<32500) { //0.99182128906250 in Q15
689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // Q17 + (Q15*Q10)>>8 = Q17
690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      larAbsQ17 = -3324784 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 31863, 8);
691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else  {
692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // Q17 + (Q15*Q5)>>3 = Q17
693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      larAbsQ17 = -88546020 + WEBRTC_SPL_MUL_16_16_RSFT(rc, 21973, 3);
694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (rcQ15[k]>0) {
697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      larQ17[k] = larAbsQ17;
698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      larQ17[k] = -larAbsQ17;
700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
705fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void Lar2RcFix(const int32_t *larQ17, int16_t *rcQ15,  int16_t order) {
706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /*
708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    This is a piece-wise implemenetation of a lar2rc-function
709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    See comment in Rc2LarFix() about details.
710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  */
711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
713fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t larAbsQ11;
714fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t rc;
715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < order; k++) {
717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
718fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    larAbsQ11 = (int16_t) WEBRTC_SPL_ABS_W32(WEBRTC_SPL_RSHIFT_W32(larQ17[k]+32,6)); //Q11
719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (larAbsQ11<4097) { //2.000012018559 in Q11
721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // Q11*Q16>>12 = Q15
722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rc = WEBRTC_SPL_MUL_16_16_RSFT(larAbsQ11, 24957, 12);
723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (larAbsQ11<6393) { //3.121320351712 in Q11
724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // (Q11*Q17 + Q13)>>13 = Q15
725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rc = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(larAbsQ11, 17993) + 130738688), 13);
726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (larAbsQ11<11255) { //5.495270168700 in Q11
727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // (Q11*Q19 + Q30)>>15 = Q15
728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rc = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(larAbsQ11, 16850) + 875329820), 15);
729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else  {
730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // (Q11*Q24>>16 + Q19)>>4 = Q15
731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rc = WEBRTC_SPL_RSHIFT_W32(((WEBRTC_SPL_MUL_16_16_RSFT(larAbsQ11, 24433, 16)) + 515804), 4);
732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (larQ17[k]<=0) {
735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rc = -rc;
736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
738fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    rcQ15[k] = (int16_t) rc;  // Q15
739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
742fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void Poly2LarFix(int16_t *lowbandQ15,
743fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t orderLo,
744fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t *hibandQ15,
745fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t orderHi,
746fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t Nsub,
747fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int32_t *larsQ17) {
748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, n;
750fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t *outpQ17;
751fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t orderTot;
752fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t larQ17[MAX_ORDER];   // Size 7+6 is enough
753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  orderTot = (orderLo + orderHi);
755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  outpQ17 = larsQ17;
756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < Nsub; k++) {
757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Rc2LarFix(lowbandQ15, larQ17, orderLo);
759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < orderLo; n++)
761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      outpQ17[n] = larQ17[n]; //Q17
762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Rc2LarFix(hibandQ15, larQ17, orderHi);
764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < orderHi; n++)
766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      outpQ17[n + orderLo] = larQ17[n]; //Q17;
767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outpQ17 += orderTot;
769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lowbandQ15 += orderLo;
770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    hibandQ15 += orderHi;
771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
775fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void Lar2polyFix(int32_t *larsQ17,
776fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t *lowbandQ15,
777fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t orderLo,
778fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t *hibandQ15,
779fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t orderHi,
780fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t Nsub) {
781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, n;
783fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t orderTot;
784fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t *outplQ15, *outphQ15;
785fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t *inpQ17;
786fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t rcQ15[7+6];
787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  orderTot = (orderLo + orderHi);
789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  outplQ15 = lowbandQ15;
790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  outphQ15 = hibandQ15;
791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  inpQ17 = larsQ17;
792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < Nsub; k++) {
793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* gains not handled here as in the FLP version */
795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Low band */
797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Lar2RcFix(&inpQ17[0], rcQ15, orderLo);
798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < orderLo; n++)
799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      outplQ15[n] = rcQ15[n]; // Refl. coeffs
800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* High band */
802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Lar2RcFix(&inpQ17[orderLo], rcQ15, orderHi);
803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < orderHi; n++)
804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      outphQ15[n] = rcQ15[n]; // Refl. coeffs
805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    inpQ17 += orderTot;
807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outplQ15 += orderLo;
808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    outphQ15 += orderHi;
809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
8126b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org/*
8136b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgFunction WebRtcIsacfix_MatrixProduct1C() does one form of matrix multiplication.
8146b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgIt first shifts input data of one matrix, determines the right indexes for the
8156b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgtwo matrixes, multiply them, and write the results into an output buffer.
8166b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
8176b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgNote that two factors (or, multipliers) determine the initialization values of
8186b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgthe variable |matrix1_index| in the code. The relationship is
8196b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org|matrix1_index| = |matrix1_index_factor1| * |matrix1_index_factor2|, where
8206b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org|matrix1_index_factor1| is given by the argument while |matrix1_index_factor2|
8216b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgis determined by the value of argument |matrix1_index_init_case|;
8226b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org|matrix1_index_factor2| is the value of the outmost loop counter j (when
8236b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org|matrix1_index_init_case| is 0), or the value of the middle loop counter k (when
8246b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org|matrix1_index_init_case| is non-zero).
8256b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
8266b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org|matrix0_index| is determined the same way.
8276b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
8286b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgArguments:
8296b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix0[]:                 matrix0 data in Q15 domain.
8306b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix1[]:                 matrix1 data.
8316b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix_product[]:          output data (matrix product).
8326b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix1_index_factor1:     The first of two factors determining the
8336b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                             initialization value of matrix1_index.
8346b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix0_index_factor1:     The first of two factors determining the
8356b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                             initialization value of matrix0_index.
8366b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix1_index_init_case:   Case number for selecting the second of two
8376b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                             factors determining the initialization value
8386b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                             of matrix1_index and matrix0_index.
8396b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix1_index_step:        Incremental step for matrix1_index.
8406b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix0_index_step:        Incremental step for matrix0_index.
8416b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  inner_loop_count:          Maximum count of the inner loop.
8426b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  mid_loop_count:            Maximum count of the intermediate loop.
8436b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  shift:                     Left shift value for matrix1.
8446b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org*/
8456b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgvoid WebRtcIsacfix_MatrixProduct1C(const int16_t matrix0[],
8466b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int32_t matrix1[],
8476b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   int32_t matrix_product[],
8486b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int matrix1_index_factor1,
8496b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int matrix0_index_factor1,
8506b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int matrix1_index_init_case,
8516b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int matrix1_index_step,
8526b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int matrix0_index_step,
8536b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int inner_loop_count,
8546b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int mid_loop_count,
8556b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int shift) {
8566b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  int j = 0, k = 0, n = 0;
8576b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  int matrix0_index = 0, matrix1_index = 0, matrix_prod_index = 0;
8586b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  int* matrix0_index_factor2 = &k;
8596b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  int* matrix1_index_factor2 = &j;
8606b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  if (matrix1_index_init_case != 0) {
8616b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    matrix0_index_factor2 = &j;
8626b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    matrix1_index_factor2 = &k;
8636b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  }
8646b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
8656b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
8666b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    matrix_prod_index = mid_loop_count * j;
8676b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    for (k = 0; k < mid_loop_count; k++) {
8686b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      int32_t sum32 = 0;
8696b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      matrix0_index = matrix0_index_factor1 * (*matrix0_index_factor2);
8706b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      matrix1_index = matrix1_index_factor1 * (*matrix1_index_factor2);
8716b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      for (n = 0; n < inner_loop_count; n++) {
8726b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org        sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
8736b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                              matrix1[matrix1_index] << shift));
8746b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org        matrix0_index += matrix0_index_step;
8756b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org        matrix1_index += matrix1_index_step;
8766b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      }
8776b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      matrix_product[matrix_prod_index] = sum32;
8786b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      matrix_prod_index++;
8796b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    }
8806b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  }
8816b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org}
8826b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
8836b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org/*
8846b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgFunction WebRtcIsacfix_MatrixProduct2C() returns the product of two matrixes,
8856b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgone of which has two columns. It first has to determine the correct index of
8866b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgthe first matrix before doing the actual element multiplication.
8876b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
8886b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgArguments:
8896b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix0[]:                 A matrix in Q15 domain.
8906b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix1[]:                 A matrix in Q21 domain.
8916b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix_product[]:          Output data in Q17 domain.
8926b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix0_index_factor:      A factor determining the initialization value
8936b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                             of matrix0_index.
8946b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  matrix0_index_step:        Incremental step for matrix0_index.
8956b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org*/
8966b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.orgvoid WebRtcIsacfix_MatrixProduct2C(const int16_t matrix0[],
8976b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int32_t matrix1[],
8986b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   int32_t matrix_product[],
8996b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int matrix0_index_factor,
9006b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   const int matrix0_index_step) {
9016b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  int j = 0, n = 0;
9026b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
9036b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
9046b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    int32_t sum32 = 0, sum32_2 = 0;
9056b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    matrix1_index = 0;
9066b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    matrix0_index = matrix0_index_factor * j;
9076b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    for (n = SUBFRAMES; n > 0; n--) {
9086b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
9096b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                            matrix1[matrix1_index]));
9106b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      sum32_2 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
9116b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                            matrix1[matrix1_index + 1]));
9126b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      matrix1_index += 2;
9136b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      matrix0_index += matrix0_index_step;
9146b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    }
9156b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    matrix_product[matrix_prod_index] = sum32 >> 3;
9166b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    matrix_product[matrix_prod_index + 1] = sum32_2 >> 3;
9176b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    matrix_prod_index += 2;
9186b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  }
9196b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org}
9206b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
921fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_DecodeLpc(int32_t *gain_lo_hiQ17,
922fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t *LPCCoef_loQ15,
923fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t *LPCCoef_hiQ15,
924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            Bitstr_dec *streamdata,
925fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t *outmodel) {
926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
927fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_GAIN+KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecodeLpcCoef(streamdata, larsQ17, gain_lo_hiQ17, outmodel);
931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_LPC;
933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize LPC Coef */
940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec *streamdata,
941fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                int32_t *LPCCoefQ17,
942fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                int32_t *gain_lo_hiQ17,
943fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                int16_t *outmodel)
944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int j, k, n;
946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
947fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t pos, pos2, posg, poss;
948fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t gainpos;
949fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t model;
950fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index_QQ[KLT_ORDER_SHAPE];
951fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
952fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
953fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tmpcoeffs_sQ10[KLT_ORDER_SHAPE];
954fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
955fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs2_sQ18[KLT_ORDER_SHAPE];
956fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sumQQ;
957fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t sumQQ16;
958fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmp32;
959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of model number */
963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistOneStepMulti(&model, streamdata, WebRtcIsacfix_kModelCdfPtr, WebRtcIsacfix_kModelInitIndex, 1);
964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of quantization indices */
968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfShapePtr[model], WebRtcIsacfix_kInitIndexShape[model], KLT_ORDER_SHAPE);
969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization levels for coefficients */
972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<KLT_ORDER_SHAPE; k++) {
973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_sQ10[WebRtcIsacfix_kSelIndShape[k]] = WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[model]+WebRtcIsacfix_kOffsetShape[model][k] + index_QQ[k]];
974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfGainPtr[model], WebRtcIsacfix_kInitIndexGain[model], KLT_ORDER_GAIN);
977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization levels for coefficients */
980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<KLT_ORDER_GAIN; k++) {
981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[model]+ WebRtcIsacfix_kOffsetGain[model][k] + index_QQ[k]];
982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* inverse KLT  */
986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* left transform */  // Transpose matrix!
9886b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1GainQ15[model], tmpcoeffs_gQ17,
9896b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                               tmpcoeffs2_gQ21, kTIndexFactor2, kTIndexFactor2,
9906b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                               kTInitCase0, kTIndexStep1, kTIndexStep1,
9916b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                               kTLoopCount2, kTLoopCount2, kTMatrix1_shift5);
9926b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;
994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j=0; j<SUBFRAMES; j++) {
995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k=0; k<LPC_SHAPE_ORDER; k++) {
996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sumQQ = 0;
9976b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      pos = LPC_SHAPE_ORDER * j;
9986b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      pos2 = LPC_SHAPE_ORDER * k;
999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n=0; n<LPC_SHAPE_ORDER; n++) {
1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        sumQQ += WEBRTC_SPL_MUL_16_16_RSFT(tmpcoeffs_sQ10[pos], WebRtcIsacfix_kT1ShapeQ15[model][pos2], 7); // (Q10*Q15)>>7 = Q18
1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos++;
1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        pos2++;
1003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_sQ18[poss] = sumQQ; //Q18
1005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      poss++;
1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* right transform */ // Transpose matrix
10106b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
10116b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor1, kTIndexStep2);
10126b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[model],
10136b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      tmpcoeffs2_sQ18, tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor1,
10146b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      kTInitCase1, kTIndexStep3, kTIndexStep2, kTLoopCount1, kTLoopCount3,
10156b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      kTMatrix1_shift0);
1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* scaling, mean addition, and gain restoration */
1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  gainpos = 0;
1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;poss = 0;pos=0;
1020b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<SUBFRAMES; k++) {
1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* log gains */
1023fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    sumQQ16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmpcoeffs_gQ17[posg], 2+9); //Divide by 4 and get Q17 to Q8, i.e. shift 2+9
1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    gainpos++;
1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1030fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    sumQQ16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmpcoeffs_gQ17[posg], 2+9); //Divide by 4 and get Q17 to Q8, i.e. shift 2+9
1031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    gainpos++;
1035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++;
1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* lo band LAR coeffs */
1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n=0; n<ORDERLO; n++, pos++, poss++) {
1039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
1040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoefQ17[pos] = tmp32;
1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* hi band LAR coeffs */
1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n=0; n<ORDERHI; n++, pos++, poss++) {
1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]), 3); // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
1047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
1048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoefQ17[pos] = tmp32;
1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *outmodel=model;
1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1056b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1057b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* estimate codel length of LPC Coef */
1059fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic int EstCodeLpcCoef(int32_t *LPCCoefQ17,
1060fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int32_t *gain_lo_hiQ17,
1061fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int16_t *model,
1062fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int32_t *sizeQ11,
1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          Bitstr_enc *streamdata,
1064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          ISAC_SaveEncData_t* encData,
1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          transcode_obj *transcodingParam) {
1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int j, k, n;
1067fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t posQQ, pos2QQ, gainpos;
1068fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t  pos, poss, posg, offsg;
1069fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index_gQQ[KLT_ORDER_GAIN], index_sQQ[KLT_ORDER_SHAPE];
1070fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index_ovr_gQQ[KLT_ORDER_GAIN], index_ovr_sQQ[KLT_ORDER_SHAPE];
1071fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t BitsQQ;
1072fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org
1073fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
1074fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
1075fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
1076fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
1077fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs2_sQ17[KLT_ORDER_SHAPE];
1078fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sumQQ;
1079fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmp32;
1080fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t sumQQ16;
1081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
1082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* write LAR coefficients to statistics file */
1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bitstreams (and transcoding) */
1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (encData != NULL) {
1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k=0; k<KLT_ORDER_GAIN; k++) {
1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
1088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* log gains, mean removal and scaling */
1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;poss = 0;pos=0; gainpos=0;
1093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<SUBFRAMES; k++) {
1095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* log gains */
1096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* The input argument X to logN(X) is 2^17 times higher than the
1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       input floating point argument Y to log(Y), since the X value
1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       is a Q17 value. This can be compensated for after the call, by
1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       subraction a value Z for each Q-step. One Q-step means that
1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       177.445678 should be subtracted (since logN() returns a Q8 value).
1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       For a X value in Q17, the value 177.445678*17 = 3017 should be
1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       subtracted */
1105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++; gainpos++;
1108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++; gainpos++;
1112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* lo band LAR coeffs */
1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n=0; n<ORDERLO; n++, poss++, pos++) {
1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(17203, tmp32<<3); // tmp32 = 2.1*tmp32
1117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_sQ17[poss] = tmp32; //Q17
1118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* hi band LAR coeffs */
1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n=0; n<ORDERHI; n++, poss++, pos++) {
1122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(14746, tmp32<<1); // tmp32 = 0.45*tmp32
1124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs_sQ17[poss] = tmp32; //Q17
1125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* KLT  */
1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* left transform */
1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
11346b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  posg = 0;
1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j=0; j<SUBFRAMES; j++) {
11366b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    // Q21 = Q6 * Q15
11376b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    sumQQ = WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[offsg],
11386b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org        WebRtcIsacfix_kT1GainQ15[0][0]);
11396b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[offsg + 1],
11406b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org        WebRtcIsacfix_kT1GainQ15[0][2]);
11416b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    tmpcoeffs2_gQ21[posg] = sumQQ;
11426b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    posg++;
11436b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
11446b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    // Q21 = Q6 * Q15
11456b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    sumQQ = WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[offsg],
11466b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org        WebRtcIsacfix_kT1GainQ15[0][1]);
11476b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[offsg + 1],
11486b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org        WebRtcIsacfix_kT1GainQ15[0][3]);
11496b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    tmpcoeffs2_gQ21[posg] = sumQQ;
11506b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    posg++;
11516b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += 2;
1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11556b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1ShapeQ15[0], tmpcoeffs_sQ17,
11566b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      tmpcoeffs2_sQ17, kTIndexFactor4, kTIndexFactor1, kTInitCase0,
11576b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      kTIndexStep1, kTIndexStep3, kTLoopCount3, kTLoopCount3, kTMatrix1_shift1);
11586b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* right transform */
11606b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
11616b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
11626b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
11636b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[0], tmpcoeffs2_sQ17,
11646b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor3, kTInitCase1, kTIndexStep3,
11656b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      kTIndexStep1, kTLoopCount1, kTLoopCount3, kTMatrix1_shift1);
1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* quantize coefficients */
1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  BitsQQ = 0;
1170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posQQ = WebRtcIsacfix_kSelIndGain[k];
1173fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
1174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
1176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index_gQQ[k] < 0) {
1177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_gQQ[k] = 0;
1178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
1181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_ovr_gQQ[k] = WebRtcIsacfix_kOffsetGain[0][k]+index_gQQ[k];
1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posQQ = WebRtcIsacfix_kOfLevelsGain[0] + index_ovr_gQQ[k];
1184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save data for creation of multiple bitstreams */
1186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (encData != NULL) {
1187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
1188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* determine number of bits */
1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sumQQ = WebRtcIsacfix_kCodeLenGainQ11[posQQ]; //Q11
1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    BitsQQ += sumQQ;
1193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<KLT_ORDER_SHAPE; k++) //ATTN: ok?
1196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1197fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    index_sQQ[k] = (int16_t)(CalcLrIntQ(tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]], 17) + WebRtcIsacfix_kQuantMinShape[k]); //ATTN: ok?
1198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index_sQQ[k] < 0)
1200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_sQQ[k] = 0;
1201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (index_sQQ[k] > WebRtcIsacfix_kMaxIndShape[k])
1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_sQQ[k] = WebRtcIsacfix_kMaxIndShape[k];
1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_ovr_sQQ[k] = WebRtcIsacfix_kOffsetShape[0][k]+index_sQQ[k];
1204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posQQ = WebRtcIsacfix_kOfLevelsShape[0] + index_ovr_sQQ[k];
1206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sumQQ = WebRtcIsacfix_kCodeLenShapeQ11[posQQ]; //Q11
1207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    BitsQQ += sumQQ;
1208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *model = 0;
1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *sizeQ11=BitsQQ;
1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of model number */
1216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, model, WebRtcIsacfix_kModelCdfPtr, 1);
1217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
1218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization indices - shape only */
1222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, index_sQQ, WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE);
1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bitstreams */
1228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (encData != NULL) {
1229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k=0; k<KLT_ORDER_SHAPE; k++)
1230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      encData->LPCindex_s[KLT_ORDER_SHAPE*encData->startIdx + k] = index_sQQ[k];
1232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* save the state of the bitstream object 'streamdata' for the possible bit-rate reduction */
1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam->full         = streamdata->full;
1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam->stream_index = streamdata->stream_index;
1237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam->streamval    = streamdata->streamval;
1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam->W_upper      = streamdata->W_upper;
1239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam->beforeLastWord     = streamdata->stream[streamdata->stream_index-1];
1240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam->lastWord     = streamdata->stream[streamdata->stream_index];
1241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of index */
1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization levels for shape coefficients */
1249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<KLT_ORDER_SHAPE; k++) {
1250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]] = WEBRTC_SPL_MUL(128, WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[0]+index_ovr_sQQ[k]]);
1251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* inverse KLT  */
1254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* left transform */  // Transpose matrix!
12566b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1ShapeQ15[0], tmpcoeffs_sQ17,
12576b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      tmpcoeffs2_sQ17, kTIndexFactor4, kTIndexFactor4, kTInitCase0,
12586b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      kTIndexStep1, kTIndexStep1, kTLoopCount3, kTLoopCount3, kTMatrix1_shift1);
1259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* right transform */ // Transpose matrix
12616b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[0], tmpcoeffs2_sQ17,
12626b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor1, kTInitCase1, kTIndexStep3,
12636b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      kTIndexStep2, kTLoopCount1, kTLoopCount3, kTMatrix1_shift1);
1264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* scaling, mean addition, and gain restoration */
1266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  poss = 0;pos=0;
1267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<SUBFRAMES; k++) {
1268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* lo band LAR coeffs */
1270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n=0; n<ORDERLO; n++, pos++, poss++) {
1271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
1272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
1273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoefQ17[pos] = tmp32;
1274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* hi band LAR coeffs */
1277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n=0; n<ORDERHI; n++, pos++, poss++) {
1278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]), 3); // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
1279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
1280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      LPCCoefQ17[pos] = tmp32;
1281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  //to update tmpcoeffs_gQ17 to the proper state
1286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<KLT_ORDER_GAIN; k++) {
1287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[0]+index_ovr_gQQ[k]];
1288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization levels for coefficients */
1293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* left transform */
1295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  offsg = 0;
1296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
1297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j=0; j<SUBFRAMES; j++) {
12986b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    // (Q15 * Q17) >> (16 - 1) = Q17; Q17 << 4 = Q21.
12996b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    sumQQ = (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][0],
13006b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                         tmpcoeffs_gQ17[offsg]) << 1);
13016b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][1],
13026b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                          tmpcoeffs_gQ17[offsg + 1]) << 1);
13036b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    tmpcoeffs2_gQ21[posg] = WEBRTC_SPL_LSHIFT_W32(sumQQ, 4);
13046b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    posg++;
13056b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
13066b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    sumQQ = (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][2],
13076b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                         tmpcoeffs_gQ17[offsg]) << 1);
13086b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][3],
13096b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                          tmpcoeffs_gQ17[offsg + 1]) << 1);
13106b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    tmpcoeffs2_gQ21[posg] = WEBRTC_SPL_LSHIFT_W32(sumQQ, 4);
13116b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org    posg++;
1312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    offsg += 2;
1313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* right transform */ // Transpose matrix
13166b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
13176b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor1, kTIndexStep2);
1318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* scaling, mean addition, and gain restoration */
1320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  posg = 0;
1321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  gainpos = 0;
1322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<2*SUBFRAMES; k++) {
1323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1324fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    sumQQ16 = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmpcoeffs_gQ17[posg], 2+9); //Divide by 4 and get Q17 to Q8, i.e. shift 2+9
1325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[0][posg];
1326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
1327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
1328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    gainpos++;
1330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pos++;posg++;
1331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1336fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EstCodeLpcGain(int32_t *gain_lo_hiQ17,
1337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 Bitstr_enc *streamdata,
1338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISAC_SaveEncData_t* encData) {
13396b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  int j, k;
1340fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t posQQ, pos2QQ, gainpos;
1341fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t posg;
1342fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index_gQQ[KLT_ORDER_GAIN];
1343fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org
1344fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
1345fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
1346fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
1347fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sumQQ;
1348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
1349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* write LAR coefficients to statistics file */
1351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bitstreams (and transcoding) */
1352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (encData != NULL) {
1353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k=0; k<KLT_ORDER_GAIN; k++) {
1354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
1355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* log gains, mean removal and scaling */
13596b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  posg = 0; gainpos = 0;
1360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<SUBFRAMES; k++) {
1362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* log gains */
1363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* The input argument X to logN(X) is 2^17 times higher than the
1365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       input floating point argument Y to log(Y), since the X value
1366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       is a Q17 value. This can be compensated for after the call, by
1367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       subraction a value Z for each Q-step. One Q-step means that
1368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
1369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       177.445678 should be subtracted (since logN() returns a Q8 value).
1370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       For a X value in Q17, the value 177.445678*17 = 3017 should be
1371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       subtracted */
1372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++; gainpos++;
1375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++; gainpos++;
1379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* KLT  */
1383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* left transform */
13856b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  posg = 0;
1386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (j=0; j<SUBFRAMES; j++) {
13876b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      // Q21 = Q6 * Q15
13886b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      sumQQ = WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[j * 2],
13896b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   WebRtcIsacfix_kT1GainQ15[0][0]);
13906b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[j * 2 + 1],
13916b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                    WebRtcIsacfix_kT1GainQ15[0][2]);
1392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpcoeffs2_gQ21[posg] = sumQQ;
1393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      posg++;
1394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13956b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      sumQQ = WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[j * 2],
13966b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                   WebRtcIsacfix_kT1GainQ15[0][1]);
13976b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[j * 2 + 1],
13986b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                                    WebRtcIsacfix_kT1GainQ15[0][3]);
13996b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org      tmpcoeffs2_gQ21[posg] = sumQQ;
1400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      posg++;
1401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
14036b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  /* right transform */
14046b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
14056b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
14066b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org
1407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* quantize coefficients */
1408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
1410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posQQ = WebRtcIsacfix_kSelIndGain[k];
1412fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
1413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
1415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index_gQQ[k] < 0) {
1416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_gQQ[k] = 0;
1417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
1419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
1420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save data for creation of multiple bitstreams */
1423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (encData != NULL) {
1424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
1425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of index */
1429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
1430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
1431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1438fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EncodeLpc(int32_t *gain_lo_hiQ17,
1439fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t *LPCCoef_loQ15,
1440fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t *LPCCoef_hiQ15,
1441fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int16_t *model,
1442fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                            int32_t *sizeQ11,
1443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            Bitstr_enc *streamdata,
1444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            ISAC_SaveEncData_t* encData,
1445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            transcode_obj *transcodeParam)
1446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
1448fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
1449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // = (6+12)*6 == 108
1450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Poly2LarFix(LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES, larsQ17);
1452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
14536b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  status = EstCodeLpcCoef(larsQ17, gain_lo_hiQ17, model, sizeQ11,
14546b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                          streamdata, encData, transcodeParam);
1455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
1456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return (status);
1457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
1460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize RC */
1466fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_DecodeRcCoef(Bitstr_dec *streamdata, int16_t *RCQ15)
1467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, err;
1469fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index[AR_ORDER];
1470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of quantization indices */
1472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistOneStepMulti(index, streamdata, WebRtcIsacfix_kRcCdfPtr, WebRtcIsacfix_kRcInitInd, AR_ORDER);
1473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
1474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
1475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization levels for reflection coefficients */
1477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<AR_ORDER; k++)
1478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
1480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* quantize & code RC */
1488fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EncodeRcCoef(int16_t *RCQ15, Bitstr_enc *streamdata)
1489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
1491fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index[AR_ORDER];
1492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status;
1493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* quantize reflection coefficients (add noise feedback?) */
1495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<AR_ORDER; k++)
1496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index[k] = WebRtcIsacfix_kRcInitInd[k];
1498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k]])
1500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      while (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k] + 1])
1502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        index[k]++;
1503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else
1505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    {
1506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      while (RCQ15[k] < WebRtcIsacfix_kRcBound[--index[k]]) ;
1507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
1510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization indices */
1514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, index, WebRtcIsacfix_kRcCdfPtr, AR_ORDER);
1515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
1517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return status;
1518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize squared Gain */
1522fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_DecodeGain2(Bitstr_dec *streamdata, int32_t *gainQ10)
1523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
1525fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index;
1526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of quantization index */
1528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistOneStepMulti(
1529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      &index,
1530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      streamdata,
1531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsacfix_kGainPtr,
1532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsacfix_kGainInitInd,
1533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      1);
1534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* error check */
1535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0) {
1536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
1537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization level */
1540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
1541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* quantize & code squared Gain */
1548fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EncodeGain2(int32_t *gainQ10, Bitstr_enc *streamdata)
1549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1550fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index;
1551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
1552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization index */
1554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  index = WebRtcIsacfix_kGainInitInd[0];
1555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (*gainQ10 > WebRtcIsacfix_kGain2Bound[index])
1556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    while (*gainQ10 > WebRtcIsacfix_kGain2Bound[index + 1])
1558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index++;
1559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  else
1561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    while (*gainQ10 < WebRtcIsacfix_kGain2Bound[--index]) ;
1563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* dequantize */
1566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
1567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization index */
1569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, &index, WebRtcIsacfix_kGainPtr, 1);
1570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
1572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return status;
1573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* code and decode Pitch Gains and Lags functions */
1577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize Pitch Gains */
1579fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_DecodePitchGain(Bitstr_dec *streamdata, int16_t *PitchGains_Q12)
1580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
1582fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index_comb;
1583fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t *pitch_gain_cdf_ptr[1];
1584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of quantization indices */
1586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
1587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistBisectMulti(&index_comb, streamdata, pitch_gain_cdf_ptr, WebRtcIsacfix_kCdfTableSizeGain, 1);
1588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* error check, Q_mean_Gain.. tables are of size 144 */
1589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((err < 0) || (index_comb < 0) || (index_comb >= 144))
1590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
1591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* unquantize back to pitch gains by table look-up */
1593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
1594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
1595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
1596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
1597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* quantize & code Pitch Gains */
1603fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EncodePitchGain(int16_t *PitchGains_Q12, Bitstr_enc *streamdata, ISAC_SaveEncData_t* encData)
1604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k,j;
1606fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t SQ15[PITCH_SUBFRAMES];
1607fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index[3];
1608fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index_comb;
1609fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t *pitch_gain_cdf_ptr[1];
1610fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t CQ17;
1611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
1612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* get the approximate arcsine (almost linear)*/
1615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<PITCH_SUBFRAMES; k++)
1616fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    SQ15[k] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(PitchGains_Q12[k],33,2); //Q15
1617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization index; only for the first three transform coefficients */
1620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<3; k++)
1621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /*  transform */
1623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CQ17=0;
1624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (j=0; j<PITCH_SUBFRAMES; j++) {
1625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      CQ17 += WEBRTC_SPL_MUL_16_16_RSFT(WebRtcIsacfix_kTransform[k][j], SQ15[j],10); // Q17
1626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1628fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    index[k] = (int16_t)((CQ17 + 8192)>>14); // Rounding and scaling with stepsize (=1/0.125=8)
1629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* check that the index is not outside the boundaries of the table */
1631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index[k] < WebRtcIsacfix_kLowerlimiGain[k]) index[k] = WebRtcIsacfix_kLowerlimiGain[k];
1632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (index[k] > WebRtcIsacfix_kUpperlimitGain[k]) index[k] = WebRtcIsacfix_kUpperlimitGain[k];
1633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index[k] -= WebRtcIsacfix_kLowerlimiGain[k];
1634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* calculate unique overall index */
1637fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  index_comb = (int16_t)(WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[0], index[0]) +
1638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[1], index[1]) + index[2]);
1639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* unquantize back to pitch gains by table look-up */
1641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // (Y)
1642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
1643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
1644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
1645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
1646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization pitch gains */
1649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
1650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, &index_comb, pitch_gain_cdf_ptr, 1);
1651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
1652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bitstreams */
1656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (encData != NULL) {
1657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    encData->pitchGain_index[encData->startIdx] = index_comb;
1658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Pitch LAG */
1666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* decode & dequantize Pitch Lags */
1669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsacfix_DecodePitchLag(Bitstr_dec *streamdata,
1670fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                 int16_t *PitchGain_Q12,
1671fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                 int16_t *PitchLags_Q7)
1672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, err;
1674fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index[PITCH_SUBFRAMES];
1675fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t *mean_val2Q10, *mean_val4Q10;
1676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1677fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t *lower_limit;
1678fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t *init_index;
1679fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t *cdf_size;
1680fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t **cdf;
1681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1682fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t meangainQ12;
1683fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t CQ11, CQ10,tmp32a,tmp32b;
1684fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t shft,tmp16a,tmp16c;
1685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  meangainQ12=0;
1687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < 4; k++)
1688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    meangainQ12 += PitchGain_Q12[k];
1689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  meangainQ12 = WEBRTC_SPL_RSHIFT_W32(meangainQ12, 2);  // Get average
1691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* voicing classificiation */
1693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (meangainQ12 <= 819) {                 // mean_gain < 0.2
1694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shft = -1;        // StepSize=2.0;
1695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsacfix_kPitchLagPtrLo;
1696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf_size = WebRtcIsacfix_kPitchLagSizeLo;
1697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
1698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
1699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsacfix_kLowerLimitLo;
1700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    init_index = WebRtcIsacfix_kInitIndLo;
1701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if (meangainQ12 <= 1638) {            // mean_gain < 0.4
1702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shft = 0;        // StepSize=1.0;
1703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsacfix_kPitchLagPtrMid;
1704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf_size = WebRtcIsacfix_kPitchLagSizeMid;
1705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
1706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
1707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsacfix_kLowerLimitMid;
1708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    init_index = WebRtcIsacfix_kInitIndMid;
1709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shft = 1;        // StepSize=0.5;
1711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsacfix_kPitchLagPtrHi;
1712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf_size = WebRtcIsacfix_kPitchLagSizeHi;
1713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
1714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
1715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsacfix_kLowerLimitHi;
1716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    init_index = WebRtcIsacfix_kInitIndHi;
1717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of quantization indices */
1720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
1721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((err<0) || (index[0]<0))  // error check
1722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
1723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistOneStepMulti(index+1, streamdata, cdf+1, init_index, 3);
1725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
1726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
1727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
1730fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  CQ11 = ((int32_t)index[0] + lower_limit[0]);  // Q0
1731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
1732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<PITCH_SUBFRAMES; k++) {
1733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmp32a =  WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11);
1734fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp16a = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32a, 5);
1735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags_Q7[k] = tmp16a;
1736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CQ10 = mean_val2Q10[index[1]];
1739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<PITCH_SUBFRAMES; k++) {
1740fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp32b =  (int32_t) WEBRTC_SPL_MUL_16_16_RSFT((int16_t) WebRtcIsacfix_kTransform[1][k], (int16_t) CQ10,10);
1741fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp16c = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5);
1742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags_Q7[k] += tmp16c;
1743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CQ10 = mean_val4Q10[index[3]];
1746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<PITCH_SUBFRAMES; k++) {
1747fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp32b =  (int32_t) WEBRTC_SPL_MUL_16_16_RSFT((int16_t) WebRtcIsacfix_kTransform[3][k], (int16_t) CQ10,10);
1748fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp16c = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5);
1749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLags_Q7[k] += tmp16c;
1750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
1753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* quantize & code Pitch Lags */
1758fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EncodePitchLag(int16_t *PitchLagsQ7,int16_t *PitchGain_Q12,
1759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 Bitstr_enc *streamdata, ISAC_SaveEncData_t* encData)
1760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k, j;
1762fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t index[PITCH_SUBFRAMES];
1763fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t meangainQ12, CQ17;
1764fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t CQ11, CQ10,tmp32a;
1765fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org
1766fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t *mean_val2Q10,*mean_val4Q10;
1767fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t *lower_limit, *upper_limit;
1768fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t **cdf;
1769fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t shft, tmp16a, tmp16b, tmp16c;
1770fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmp32b;
1771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
1772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* compute mean pitch gain */
1774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  meangainQ12=0;
1775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < 4; k++)
1776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    meangainQ12 += PitchGain_Q12[k];
1777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  meangainQ12 = WEBRTC_SPL_RSHIFT_W32(meangainQ12, 2);
1779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for creation of multiple bitstreams */
1781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (encData != NULL) {
1782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    encData->meanGain[encData->startIdx] = meangainQ12;
1783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* voicing classificiation */
1786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (meangainQ12 <= 819) {                 // mean_gain < 0.2
1787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shft = -1;        // StepSize=2.0;
1788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsacfix_kPitchLagPtrLo;
1789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
1790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
1791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsacfix_kLowerLimitLo;
1792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    upper_limit = WebRtcIsacfix_kUpperLimitLo;
1793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if (meangainQ12 <= 1638) {            // mean_gain < 0.4
1794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shft = 0;        // StepSize=1.0;
1795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsacfix_kPitchLagPtrMid;
1796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
1797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
1798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsacfix_kLowerLimitMid;
1799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    upper_limit = WebRtcIsacfix_kUpperLimitMid;
1800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shft = 1;        // StepSize=0.5;
1802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cdf = WebRtcIsacfix_kPitchLagPtrHi;
1803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
1804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
1805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    lower_limit = WebRtcIsacfix_kLowerLimitHi;
1806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    upper_limit = WebRtcIsacfix_kUpperLimitHi;
1807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* find quantization index */
1810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<4; k++)
1811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
1812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /*  transform */
1813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CQ17=0;
1814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (j=0; j<PITCH_SUBFRAMES; j++)
1815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      CQ17 += WEBRTC_SPL_MUL_16_16_RSFT(WebRtcIsacfix_kTransform[k][j], PitchLagsQ7[j],2); // Q17
1816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CQ17 = WEBRTC_SPL_SHIFT_W32(CQ17,shft); // Scale with StepSize
1818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* quantize */
1820fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp16b = (int16_t) WEBRTC_SPL_RSHIFT_W32(CQ17 + 65536, 17 );
1821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index[k] =  tmp16b;
1822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* check that the index is not outside the boundaries of the table */
1824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index[k] < lower_limit[k]) index[k] = lower_limit[k];
1825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (index[k] > upper_limit[k]) index[k] = upper_limit[k];
1826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index[k] -= lower_limit[k];
1827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save data for creation of multiple bitstreams */
1829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if(encData != NULL) {
1830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      encData->pitchIndex[PITCH_SUBFRAMES*encData->startIdx + k] = index[k];
1831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
1835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CQ11 = (index[0] + lower_limit[0]);  // Q0
1836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
1837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<PITCH_SUBFRAMES; k++) {
1839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmp32a =  WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11); // Q12
1840fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp16a = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32a, 5);// Q7
1841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLagsQ7[k] = tmp16a;
1842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CQ10 = mean_val2Q10[index[1]];
1845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<PITCH_SUBFRAMES; k++) {
1846fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp32b =  (int32_t) WEBRTC_SPL_MUL_16_16_RSFT((int16_t) WebRtcIsacfix_kTransform[1][k], (int16_t) CQ10,10);
1847fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp16c = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q7
1848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLagsQ7[k] += tmp16c;
1849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CQ10 = mean_val4Q10[index[3]];
1852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<PITCH_SUBFRAMES; k++) {
1853fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp32b =  (int32_t) WEBRTC_SPL_MUL_16_16_RSFT((int16_t) WebRtcIsacfix_kTransform[3][k], (int16_t) CQ10,10);
1854fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    tmp16c = (int16_t) WEBRTC_SPL_RSHIFT_W32(tmp32b, 5); // Q7
1855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchLagsQ7[k] += tmp16c;
1856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of quantization pitch lags */
1859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
1860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
1862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return status;
1863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Routines for inband signaling of bandwitdh estimation */
1868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Histograms based on uniform distribution of indices */
1869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* Move global variables later! */
1870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* cdf array for frame length indicator */
1873fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t kFrameLenCdf[4] = {
1874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  0, 21845, 43690, 65535};
1875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* pointer to cdf array for frame length indicator */
1877fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t *kFrameLenCdfPtr[1] = {kFrameLenCdf};
1878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* initial cdf index for decoder of frame length indicator */
1880fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t kFrameLenInitIndex[1] = {1};
1881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsacfix_DecodeFrameLen(Bitstr_dec *streamdata,
1884fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                 int16_t *framesamples)
1885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
1888fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t frame_mode;
1889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = 0;
1891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of frame length [1:30ms,2:60ms] */
1892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistOneStepMulti(&frame_mode, streamdata, kFrameLenCdfPtr, kFrameLenInitIndex, 1);
1893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
1894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH;
1895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch(frame_mode) {
1897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 1:
1898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      *framesamples = 480; /* 30ms */
1899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 2:
1901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      *framesamples = 960; /* 60ms */
1902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
1904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      err = -ISAC_DISALLOWED_FRAME_MODE_DECODER;
1905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return err;
1908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1911fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EncodeFrameLen(int16_t framesamples, Bitstr_enc *streamdata) {
1912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status;
1914fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t frame_mode;
1915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = 0;
1917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_mode = 0;
1918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy coding of frame length [1:480 samples,2:960 samples] */
1919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch(framesamples) {
1920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 480:
1921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      frame_mode = 1;
1922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case 960:
1924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      frame_mode = 2;
1925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
1926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
1927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      status = - ISAC_DISALLOWED_FRAME_MODE_ENCODER;
1928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0)
1931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, &frame_mode, kFrameLenCdfPtr, 1);
1934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return status;
1936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* cdf array for estimated bandwidth */
1939fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t kBwCdf[25] = {
1940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  0, 2731, 5461, 8192, 10923, 13653, 16384, 19114, 21845, 24576, 27306, 30037,
1941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  32768, 35498, 38229, 40959, 43690, 46421, 49151, 51882, 54613, 57343, 60074,
1942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  62804, 65535};
1943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* pointer to cdf array for estimated bandwidth */
1945fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t *kBwCdfPtr[1] = {kBwCdf};
1946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* initial cdf index for decoder of estimated bandwidth*/
1948fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgconst uint16_t kBwInitIndex[1] = {7};
1949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1951fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec *streamdata, int16_t *BWno) {
1952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
1954fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t BWno32;
1955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy decoding of sender's BW estimation [0..23] */
1957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsacfix_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr, kBwInitIndex, 1);
1958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err<0)  // error check
1959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
1960fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  *BWno = (int16_t)BWno32;
1961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return err;
1962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1966fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_EncodeReceiveBandwidth(int16_t *BWno, Bitstr_enc *streamdata)
1967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{
1968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
1969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* entropy encoding of receiver's BW estimation [0..23] */
1970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsacfix_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
1971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return status;
1973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* estimate codel length of LPC Coef */
1976fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsacfix_TranscodeLpcCoef(int32_t *gain_lo_hiQ17,
1977fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                                    int16_t *index_gQQ) {
19786b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  int j, k;
1979fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t posQQ, pos2QQ;
1980fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t posg, offsg, gainpos;
1981fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
1982fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
1983fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
1984fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int32_t sumQQ;
1985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* log gains, mean removal and scaling */
19886b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  posg = 0; gainpos=0;
1989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<SUBFRAMES; k++) {
1991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* log gains */
1992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* The input argument X to logN(X) is 2^17 times higher than the
1994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       input floating point argument Y to log(Y), since the X value
1995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       is a Q17 value. This can be compensated for after the call, by
1996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       subraction a value Z for each Q-step. One Q-step means that
1997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
1998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       177.445678 should be subtracted (since logN() returns a Q8 value).
1999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       For a X value in Q17, the value 177.445678*17 = 3017 should be
2000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       subtracted */
2001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
2002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
2003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++; gainpos++;
2004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
2006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
2007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posg++; gainpos++;
2008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* KLT  */
2013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2014b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* left transform */
2015715275c813e0169cd103f3ef15a69b8134dfa3f7kma@webrtc.org  for (j = 0, offsg = 0; j < SUBFRAMES; j++, offsg += 2) {
2016d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org    // Q21 = Q6 * Q15
2017d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org    sumQQ = WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[offsg],
2018d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org                                 WebRtcIsacfix_kT1GainQ15[0][0]);
2019d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org    sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[offsg + 1],
2020d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org                                  WebRtcIsacfix_kT1GainQ15[0][2]);
2021d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org    tmpcoeffs2_gQ21[offsg] = sumQQ;
2022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2023d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org    // Q21 = Q6 * Q15
2024d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org    sumQQ = WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[offsg],
2025d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org                                 WebRtcIsacfix_kT1GainQ15[0][1]);
2026d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org    sumQQ += WEBRTC_SPL_MUL_16_16(tmpcoeffs_gQ6[offsg + 1],
2027d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org                                  WebRtcIsacfix_kT1GainQ15[0][3]);
2028d451969b3aa5714f092ce4b86c5b380e8218c89dkma@webrtc.org    tmpcoeffs2_gQ21[offsg + 1] = sumQQ;
2029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* right transform */
20326b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
20336b12f9704ef671d4ec2ab14c531c967373c8b137kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
2034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* quantize coefficients */
2036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
2037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
2038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    posQQ = WebRtcIsacfix_kSelIndGain[k];
2039fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
2040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
2042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (index_gQQ[k] < 0) {
2043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_gQQ[k] = 0;
2044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
2046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
2047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
2048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
2049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
2050