1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
2470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  Use of this source code is governed by a BSD-style license
5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  that can be found in the LICENSE file in the root of the source
6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  tree. An additional intellectual property rights grant can be found
7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  in the file PATENTS.  All contributing project authors may
8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *  be found in the AUTHORS file in the root of the source tree.
9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
11470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * entropy_coding.c
13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * This file contains all functions used to arithmetically
15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * encode the iSAC bistream.
16470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *
17470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
18470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
19470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include <stddef.h>
20470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "arith_routins.h"
22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "spectrum_ar_model_tables.h"
23470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "pitch_gain_tables.h"
24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "pitch_lag_tables.h"
25470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "entropy_coding.h"
26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "lpc_tables.h"
27470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "settings.h"
28470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "signal_processing_library.h"
29470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org/*
3123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org * Eenumerations for arguments to functions WebRtcIsacfix_MatrixProduct1()
3223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org * and WebRtcIsacfix_MatrixProduct2().
3323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org*/
3423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
3523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgenum matrix_index_factor {
3623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTIndexFactor1 = 1,
3723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTIndexFactor2 = 2,
3823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTIndexFactor3 = SUBFRAMES,
3923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTIndexFactor4 = LPC_SHAPE_ORDER
4023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org};
4123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
4223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgenum matrix_index_step {
4323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTIndexStep1 = 1,
4423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTIndexStep2 = SUBFRAMES,
4523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTIndexStep3 = LPC_SHAPE_ORDER
4623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org};
4723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
4823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgenum matrixprod_loop_count {
4923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTLoopCount1 = SUBFRAMES,
5023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTLoopCount2 = 2,
5123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTLoopCount3 = LPC_SHAPE_ORDER
5223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org};
5323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
5423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgenum matrix1_shift_value {
5523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTMatrix1_shift0 = 0,
5623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTMatrix1_shift1 = 1,
5723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTMatrix1_shift5 = 5
5823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org};
5923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
6023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgenum matrixprod_init_case {
6123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTInitCase0 = 0,
6223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  kTInitCase1 = 1
6323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org};
64470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
65470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
66470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  This function implements the fix-point correspondant function to lrint.
67470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
680946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  FLP: (int32_t)floor(flt+.499999999999)
69470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  FIP: (fixVal+roundVal)>>qDomain
70470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
71470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  where roundVal = 2^(qDomain-1) = 1<<(qDomain-1)
72470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
73470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/
740946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic __inline int32_t CalcLrIntQ(int32_t fixVal, int16_t qDomain) {
75a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org  return (fixVal + (1 << (qDomain - 1))) >> qDomain;
76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
77470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
790946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  __inline uint32_t stepwise(int32_t dinQ10) {
80470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
810946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t ind, diQ10, dtQ10;
82470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
83470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  diQ10 = dinQ10;
84470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (diQ10 < DPMIN_Q10)
85470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  diQ10 = DPMIN_Q10;
86470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (diQ10 >= DPMAX_Q10)
87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  diQ10 = DPMAX_Q10 - 1;
88470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
89470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  dtQ10 = diQ10 - DPMIN_Q10;*/ /* Q10 + Q10 = Q10 */
90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* ind = (dtQ10 * 5) >> 10;  */ /* 2^10 / 5 = 0.2 in Q10  */
91470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* Q10 -> Q0 */
92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
93470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* return rpointsFIX_Q10[ind];
94470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
95470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   }
96470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/
97470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
98470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* logN(x) = logN(2)*log2(x) = 0.6931*log2(x). Output in Q8. */
99470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* The input argument X to logN(X) is 2^17 times higher than the
100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   input floating point argument Y to log(Y), since the X value
101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   is a Q17 value. This can be compensated for after the call, by
102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   subraction a value Z for each Q-step. One Q-step means that
103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   X gets 2 thimes higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   177.445678 should be subtracted (since logN() returns a Q8 value).
105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   For a X value in Q17, the value 177.445678*17 = 3017 should be
106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com   subtracted */
1070946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic int16_t CalcLogN(int32_t arg) {
1080946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t zeros, log2, frac, logN;
109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  zeros=WebRtcSpl_NormU32(arg);
111d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker  frac = (int16_t)((uint32_t)((arg << zeros) & 0x7FFFFFFF) >> 23);
112d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker  log2 = (int16_t)(((31 - zeros) << 8) + frac);  // log2(x) in Q8
113f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker  logN = (int16_t)(log2 * 22713 >> 15);  // log(2) = 0.693147 = 22713 in Q15
114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  logN=logN+11; //Scalar compensation which minimizes the (log(x)-logN(x))^2 error over all x.
115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return logN;
117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  expN(x) = 2^(a*x), where a = log2(e) ~= 1.442695
122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1230946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  Input:  Q8  (int16_t)
1240946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  Output: Q17 (int32_t)
125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  a = log2(e) = log2(exp(1)) ~= 1.442695  ==>  a = 23637 in Q14 (1.442688)
127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  To this value, 700 is added or subtracted in order to get an average error
128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  nearer zero, instead of always same-sign.
129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/
130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1310946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic int32_t CalcExpN(int16_t x) {
132f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker  int16_t axINT, axFRAC;
1330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t exp16;
1340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t exp;
135f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker  int16_t ax = (int16_t)(x * 23637 >> 14);  // Q8
136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (x>=0) {
138f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org    axINT = ax >> 8;  //Q0
139470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    axFRAC = ax&0x00FF;
140d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    exp16 = 1 << axINT;  // Q0
141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    axFRAC = axFRAC+256; //Q8
142bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org    exp = exp16 * axFRAC;  // Q0*Q8 = Q8
143d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    exp <<= 9;  // Q17
144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    ax = -ax;
146f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org    axINT = 1 + (ax >> 8);  //Q0
147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    axFRAC = 0x00FF - (ax&0x00FF);
148a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    exp16 = (int16_t)(32768 >> axINT);  // Q15
149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    axFRAC = axFRAC+256; //Q8
150bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org    exp = exp16 * axFRAC;  // Q15*Q8 = Q23
151a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    exp >>= 6;  // Q17
152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return exp;
155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* compute correlation from power spectrum */
1590946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic void CalcCorrelation(int32_t *PSpecQ12, int32_t *CorrQ7)
160470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1610946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t summ[FRAMESAMPLES/8];
1620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t diff[FRAMESAMPLES/8];
1630946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t sum;
164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k, n;
165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < FRAMESAMPLES/8; k++) {
167a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES / 4 - 1 - k] + 16) >> 5;
168a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES / 4 - 1 - k] + 16) >> 5;
169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  sum = 2;
172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (n = 0; n < FRAMESAMPLES/8; n++)
173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum += summ[n];
174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CorrQ7[0] = sum;
175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < AR_ORDER; k += 2) {
177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum = 0;
178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < FRAMESAMPLES/8; n++)
179a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      sum += (WebRtcIsacfix_kCos[k][n] * diff[n] + 256) >> 9;
180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CorrQ7[k+1] = sum;
181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=1; k<AR_ORDER; k+=2) {
184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum = 0;
185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < FRAMESAMPLES/8; n++)
186a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      sum += (WebRtcIsacfix_kCos[k][n] * summ[n] + 256) >> 9;
187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CorrQ7[k+1] = sum;
188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
192470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* compute inverse AR power spectrum */
1930946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic void CalcInvArSpec(const int16_t *ARCoefQ12,
1940946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                          const int32_t gainQ10,
1950946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                          int32_t *CurveQ16)
196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1970946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t CorrQ11[AR_ORDER+1];
1980946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t sum, tmpGain;
1990946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t diffQ16[FRAMESAMPLES/8];
2000946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const int16_t *CS_ptrQ9;
201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k, n;
2020946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t round, shftVal = 0, sh;
203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  sum = 0;
205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (n = 0; n < AR_ORDER+1; n++)
206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]);    /* Q24 */
207a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org  sum = ((sum >> 6) * 65 + 32768) >> 16;  /* Result in Q8. */
208a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org  CorrQ11[0] = (sum * gainQ10 + 256) >> 9;
209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if(gainQ10>400000){
212a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    tmpGain = gainQ10 >> 3;
213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    round = 32;
214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shftVal = 6;
215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpGain = gainQ10;
217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    round = 256;
218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shftVal = 9;
219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 1; k < AR_ORDER+1; k++) {
222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum = 16384;
223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = k; n < AR_ORDER+1; n++)
224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]);  /* Q24 */
225a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    sum >>= 15;
226a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    CorrQ11[k] = (sum * tmpGain + round) >> shftVal;
227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
228d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker  sum = CorrQ11[0] << 7;
229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (n = 0; n < FRAMESAMPLES/8; n++)
230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CurveQ16[n] = sum;
231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 1; k < AR_ORDER; k += 2) {
233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < FRAMESAMPLES/8; n++)
234a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      CurveQ16[n] += (WebRtcIsacfix_kCos[k][n] * CorrQ11[k + 1] + 2) >> 2;
235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CS_ptrQ9 = WebRtcIsacfix_kCos[0];
238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  sh=WebRtcSpl_NormW32(CorrQ11[1]);
241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (CorrQ11[1]==0) /* Use next correlation */
242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sh=WebRtcSpl_NormW32(CorrQ11[2]);
243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (sh<9)
245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shftVal = 9 - sh;
246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shftVal = 0;
248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (n = 0; n < FRAMESAMPLES/8; n++)
250a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    diffQ16[n] = (CS_ptrQ9[n] * (CorrQ11[1] >> shftVal) + 2) >> 2;
251470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 2; k < AR_ORDER; k += 2) {
252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CS_ptrQ9 = WebRtcIsacfix_kCos[k];
253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < FRAMESAMPLES/8; n++)
254a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      diffQ16[n] += (CS_ptrQ9[n] * (CorrQ11[k + 1] >> shftVal) + 2) >> 2;
255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<FRAMESAMPLES/8; k++) {
258d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    int32_t diff_q16 = diffQ16[k] << shftVal;
259d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    CurveQ16[FRAMESAMPLES / 4 - 1 - k] = CurveQ16[k] - diff_q16;
260d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    CurveQ16[k] += diff_q16;
261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2640946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic void CalcRootInvArSpec(const int16_t *ARCoefQ12,
2650946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                              const int32_t gainQ10,
2660946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                              uint16_t *CurveQ8)
267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
2680946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t CorrQ11[AR_ORDER+1];
2690946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t sum, tmpGain;
2700946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t summQ16[FRAMESAMPLES/8];
2710946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t diffQ16[FRAMESAMPLES/8];
272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2730946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const int16_t *CS_ptrQ9;
274470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k, n, i;
2750946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t round, shftVal = 0, sh;
2760946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t res, in_sqrt, newRes;
277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  sum = 0;
279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (n = 0; n < AR_ORDER+1; n++)
280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]);    /* Q24 */
281a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org  sum = ((sum >> 6) * 65 + 32768) >> 16;  /* Result in Q8. */
282a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org  CorrQ11[0] = (sum * gainQ10 + 256) >> 9;
283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if(gainQ10>400000){
286a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    tmpGain = gainQ10 >> 3;
287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    round = 32;
288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shftVal = 6;
289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpGain = gainQ10;
291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    round = 256;
292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shftVal = 9;
293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 1; k < AR_ORDER+1; k++) {
296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum = 16384;
297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = k; n < AR_ORDER+1; n++)
298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]);  /* Q24 */
299a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    sum >>= 15;
300a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    CorrQ11[k] = (sum * tmpGain + round) >> shftVal;
301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
302d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker  sum = CorrQ11[0] << 7;
303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (n = 0; n < FRAMESAMPLES/8; n++)
304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    summQ16[n] = sum;
305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 1; k < (AR_ORDER); k += 2) {
307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < FRAMESAMPLES/8; n++)
308926707b167e9bfb876c7c903dcefc41c84e5fedbbjornv@webrtc.org      summQ16[n] += ((CorrQ11[k + 1] * WebRtcIsacfix_kCos[k][n]) + 2) >> 2;
309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CS_ptrQ9 = WebRtcIsacfix_kCos[0];
312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  sh=WebRtcSpl_NormW32(CorrQ11[1]);
315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (CorrQ11[1]==0) /* Use next correlation */
316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sh=WebRtcSpl_NormW32(CorrQ11[2]);
317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (sh<9)
319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shftVal = 9 - sh;
320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shftVal = 0;
322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (n = 0; n < FRAMESAMPLES/8; n++)
324a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    diffQ16[n] = (CS_ptrQ9[n] * (CorrQ11[1] >> shftVal) + 2) >> 2;
325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 2; k < AR_ORDER; k += 2) {
326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CS_ptrQ9 = WebRtcIsacfix_kCos[k];
327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < FRAMESAMPLES/8; n++)
328a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      diffQ16[n] += (CS_ptrQ9[n] * (CorrQ11[k + 1] >> shftVal) + 2) >> 2;
329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
331d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker  in_sqrt = summQ16[0] + (diffQ16[0] << shftVal);
332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB)  */
334f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org  res = 1 << (WebRtcSpl_GetSizeInBits(in_sqrt) >> 1);
335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < FRAMESAMPLES/8; k++)
337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
338d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    in_sqrt = summQ16[k] + (diffQ16[k] << shftVal);
339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    i = 10;
340470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
341470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* make in_sqrt positive to prohibit sqrt of negative values */
342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(in_sqrt<0)
343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      in_sqrt=-in_sqrt;
344470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
345df9fef6638b4b5ef7a6c9a3eb2b20e26aefc9746bjornv@webrtc.org    newRes = (in_sqrt / res + res) >> 1;
346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    do
347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      res = newRes;
349df9fef6638b4b5ef7a6c9a3eb2b20e26aefc9746bjornv@webrtc.org      newRes = (in_sqrt / res + res) >> 1;
350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } while (newRes != res && i-- > 0);
351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3520946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    CurveQ8[k] = (int16_t)newRes;
353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = FRAMESAMPLES/8; k < FRAMESAMPLES/4; k++) {
355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
356d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    in_sqrt = summQ16[FRAMESAMPLES / 4 - 1 - k] -
357d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker        (diffQ16[FRAMESAMPLES / 4 - 1 - k] << shftVal);
358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    i = 10;
359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* make in_sqrt positive to prohibit sqrt of negative values */
361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(in_sqrt<0)
362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      in_sqrt=-in_sqrt;
363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
364df9fef6638b4b5ef7a6c9a3eb2b20e26aefc9746bjornv@webrtc.org    newRes = (in_sqrt / res + res) >> 1;
365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    do
366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      res = newRes;
368df9fef6638b4b5ef7a6c9a3eb2b20e26aefc9746bjornv@webrtc.org      newRes = (in_sqrt / res + res) >> 1;
369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } while (newRes != res && i-- > 0);
370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3710946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    CurveQ8[k] = (int16_t)newRes;
372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* generate array of dither samples in Q7 */
3790946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic void GenerateDitherQ7(int16_t *bufQ7,
3800946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                             uint32_t seed,
3810946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                             int16_t length,
3820946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                             int16_t AvgPitchGain_Q12)
383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int   k;
3850946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t dither1_Q7, dither2_Q7, dither_gain_Q14, shft;
386470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (AvgPitchGain_Q12 < 614)  /* this threshold should be equal to that in decode_spec() */
388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k = 0; k < length-2; k += 3)
390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
3910946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org      /* new random unsigned int32_t */
392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* fixed-point dither sample between -64 and 64 (Q7) */
395a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      dither1_Q7 = (int16_t)(((int32_t)seed + 16777216) >> 25);
396470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
3970946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org      /* new random unsigned int32_t */
398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* fixed-point dither sample between -64 and 64 */
401a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      dither2_Q7 = (int16_t)((seed + 16777216) >> 25);
402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
4030946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org      shft = (int16_t)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 15);
404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      if (shft < 5)
405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k]   = dither1_Q7;
407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k+1] = dither2_Q7;
408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k+2] = 0;
409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      else if (shft < 10)
411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k]   = dither1_Q7;
413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k+1] = 0;
414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k+2] = dither2_Q7;
415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      else
417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      {
418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k]   = 0;
419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k+1] = dither1_Q7;
420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        bufQ7[k+2] = dither2_Q7;
421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
4260946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    dither_gain_Q14 = (int16_t)(22528 - WEBRTC_SPL_MUL(10, AvgPitchGain_Q12));
427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* dither on half of the coefficients */
429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k = 0; k < length-1; k += 2)
430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
4310946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org      /* new random unsigned int32_t */
432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      seed = WEBRTC_SPL_UMUL(seed, 196314165) + 907633515;
433470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* fixed-point dither sample between -64 and 64 */
435a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      dither1_Q7 = (int16_t)(((int32_t)seed + 16777216) >> 25);
436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      /* dither sample is placed in either even or odd index */
4380946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org      shft = (int16_t)(WEBRTC_SPL_RSHIFT_U32(seed, 25) & 1);     /* either 0 or 1 */
439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
440a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      bufQ7[k + shft] = (int16_t)((dither_gain_Q14 * dither1_Q7 + 8192) >> 14);
441470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      bufQ7[k + 1 - shft] = 0;
442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
446470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/*
450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * function to decode the complex spectrum from the bitstream
451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * returns the total number of bytes in the stream
452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */
453aba07ef6d92bf1ded7ad1af49b54a8e6652dfcbbPeter Kastingint WebRtcIsacfix_DecodeSpec(Bitstr_dec *streamdata,
454aba07ef6d92bf1ded7ad1af49b54a8e6652dfcbbPeter Kasting                             int16_t *frQ7,
455aba07ef6d92bf1ded7ad1af49b54a8e6652dfcbbPeter Kasting                             int16_t *fiQ7,
456aba07ef6d92bf1ded7ad1af49b54a8e6652dfcbbPeter Kasting                             int16_t AvgPitchGain_Q12)
457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
4580946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  data[FRAMESAMPLES];
4590946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t  invARSpec2_Q16[FRAMESAMPLES/4];
4600946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  ARCoefQ12[AR_ORDER+1];
4610946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  RCQ15[AR_ORDER];
4620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  gainQ10;
4630946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t  gain2_Q10;
464aba07ef6d92bf1ded7ad1af49b54a8e6652dfcbbPeter Kasting  int len;
465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int          k;
466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* create dither signal */
468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  GenerateDitherQ7(data, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12); /* Dither is output in vector 'Data' */
469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* decode model parameters */
471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (WebRtcIsacfix_DecodeRcCoef(streamdata, RCQ15) < 0)
472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (WebRtcIsacfix_DecodeGain2(streamdata, &gain2_Q10) < 0)
478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* compute inverse AR power spectrum */
481470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CalcInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* arithmetic decoding of spectrum */
484470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* 'data' input and output. Input = Dither */
4850946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  len = WebRtcIsacfix_DecLogisticMulti2(data, streamdata, invARSpec2_Q16, (int16_t)FRAMESAMPLES);
486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (len<1)
488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* subtract dither and scale down spectral samples with low SNR */
491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (AvgPitchGain_Q12 <= 614)
492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k = 0; k < FRAMESAMPLES; k += 4)
494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
495d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker      gainQ10 = WebRtcSpl_DivW32W16ResW16(30 << 10,
496d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker          (int16_t)((uint32_t)(invARSpec2_Q16[k >> 2] + 2195456) >> 16));
497a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      *frQ7++ = (int16_t)((data[k] * gainQ10 + 512) >> 10);
498a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      *fiQ7++ = (int16_t)((data[k + 1] * gainQ10 + 512) >> 10);
499a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      *frQ7++ = (int16_t)((data[k + 2] * gainQ10 + 512) >> 10);
500a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      *fiQ7++ = (int16_t)((data[k + 3] * gainQ10 + 512) >> 10);
501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k = 0; k < FRAMESAMPLES; k += 4)
506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
507d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker      gainQ10 = WebRtcSpl_DivW32W16ResW16(36 << 10,
508d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker          (int16_t)((uint32_t)(invARSpec2_Q16[k >> 2] + 2654208) >> 16));
509a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      *frQ7++ = (int16_t)((data[k] * gainQ10 + 512) >> 10);
510a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      *fiQ7++ = (int16_t)((data[k + 1] * gainQ10 + 512) >> 10);
511a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      *frQ7++ = (int16_t)((data[k + 2] * gainQ10 + 512) >> 10);
512a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      *fiQ7++ = (int16_t)((data[k + 3] * gainQ10 + 512) >> 10);
513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
515470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return len;
517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
518470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
5200946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_EncodeSpec(const int16_t *fr,
5210946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                             const int16_t *fi,
522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                             Bitstr_enc *streamdata,
5230946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                             int16_t AvgPitchGain_Q12)
524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
5250946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  dataQ7[FRAMESAMPLES];
5260946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t  PSpec[FRAMESAMPLES/4];
5270946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint16_t invARSpecQ8[FRAMESAMPLES/4];
5280946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t  CorrQ7[AR_ORDER+1];
5290946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t  CorrQ7_norm[AR_ORDER+1];
5300946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  RCQ15[AR_ORDER];
5310946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  ARCoefQ12[AR_ORDER+1];
5320946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t  gain2_Q10;
5330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  val;
5340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t  nrg;
5350946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  uint32_t sum;
5360946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  lft_shft;
5370946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  status;
538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int          k, n, j;
539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
541470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* create dither_float signal */
542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  GenerateDitherQ7(dataQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12);
543470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* add dither and quantize, and compute power spectrum */
545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Vector dataQ7 contains Dither in Q7 */
546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < FRAMESAMPLES; k += 4)
547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    val = ((*fr++ + dataQ7[k]   + 64) & 0xFF80) - dataQ7[k]; /* Data = Dither */
549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    dataQ7[k] = val;            /* New value in Data */
550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum = WEBRTC_SPL_UMUL(val, val);
551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    val = ((*fi++ + dataQ7[k+1] + 64) & 0xFF80) - dataQ7[k+1]; /* Data = Dither */
553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    dataQ7[k+1] = val;            /* New value in Data */
554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum += WEBRTC_SPL_UMUL(val, val);
555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    val = ((*fr++ + dataQ7[k+2] + 64) & 0xFF80) - dataQ7[k+2]; /* Data = Dither */
557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    dataQ7[k+2] = val;            /* New value in Data */
558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum += WEBRTC_SPL_UMUL(val, val);
559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    val = ((*fi++ + dataQ7[k+3] + 64) & 0xFF80) - dataQ7[k+3]; /* Data = Dither */
561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    dataQ7[k+3] = val;            /* New value in Data */
562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sum += WEBRTC_SPL_UMUL(val, val);
563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    PSpec[k>>2] = WEBRTC_SPL_RSHIFT_U32(sum, 2);
565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* compute correlation from power spectrum */
568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CalcCorrelation(PSpec, CorrQ7);
569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find AR coefficients */
572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* number of bit shifts to 14-bit normalize CorrQ7[0] (leaving room for sign) */
573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  lft_shft = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
575470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (lft_shft > 0) {
576470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k=0; k<AR_ORDER+1; k++)
577d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker      CorrQ7_norm[k] = CorrQ7[k] << lft_shft;
578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k=0; k<AR_ORDER+1; k++)
580a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      CorrQ7_norm[k] = CorrQ7[k] >> -lft_shft;
581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find RC coefficients */
584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* quantize & code RC Coef */
587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncodeRcCoef(RCQ15, streamdata);
588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (status < 0) {
589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return status;
590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* RC -> AR coefficients */
593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* compute ARCoef' * Corr * ARCoef in Q19 */
596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  nrg = 0;
597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (j = 0; j <= AR_ORDER; j++) {
598470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n <= j; n++)
599a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      nrg += (ARCoefQ12[j] * ((CorrQ7_norm[j - n] * ARCoefQ12[n] + 256) >> 9) +
600a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org          4) >> 3;
601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = j+1; n <= AR_ORDER; n++)
602a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      nrg += (ARCoefQ12[j] * ((CorrQ7_norm[n - j] * ARCoefQ12[n] + 256) >> 9) +
603a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org          4) >> 3;
604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (lft_shft > 0)
607a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    nrg >>= lft_shft;
608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
609d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    nrg <<= -lft_shft;
610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if(nrg>131072)
612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES >> 2, nrg);  /* also shifts 31 bits to the left! */
613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
614a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    gain2_Q10 = FRAMESAMPLES >> 2;
615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* quantize & code gain2_Q10 */
617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (WebRtcIsacfix_EncodeGain2(&gain2_Q10, streamdata))
618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -1;
619470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* compute inverse AR magnitude spectrum */
621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CalcRootInvArSpec(ARCoefQ12, gain2_Q10, invARSpecQ8);
622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* arithmetic coding of spectrum */
6250946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  status = WebRtcIsacfix_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8, (int16_t)FRAMESAMPLES);
626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if ( status )
627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return( status );
628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* Matlab's LAR definition */
6340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic void Rc2LarFix(const int16_t *rcQ15, int32_t *larQ17, int16_t order) {
635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /*
637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    This is a piece-wise implemenetation of a rc2lar-function (all values in the comment
639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    are Q15 values and  are based on [0 24956/32768 30000/32768 32500/32768], i.e.
640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    [0.76159667968750   0.91552734375000   0.99182128906250]
641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    x0  x1           a                 k              x0(again)         b
643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    ==================================================================================
644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    0.00 0.76:   0                  2.625997508581   0                  0
645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    0.76 0.91:   2.000012018559     7.284502668663   0.761596679688    -3.547841027073
646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    0.91 0.99:   3.121320351712    31.115835041229   0.915527343750   -25.366077452148
647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    0.99 1.00:   5.495270168700   686.663805654056   0.991821289063  -675.552510708011
648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    The implementation is y(x)= a + (x-x0)*k, but this can be simplified to
650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    y(x) = a-x0*k + x*k = b + x*k, where b = a-x0*k
652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    akx=[0                 2.625997508581   0
654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    2.000012018559     7.284502668663   0.761596679688
655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    3.121320351712    31.115835041229   0.915527343750
656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    5.495270168700   686.663805654056   0.991821289063];
657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    b = akx(:,1) - akx(:,3).*akx(:,2)
659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    [ 0.0
661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    -3.547841027073
662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    -25.366077452148
663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    -675.552510708011]
664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
665470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  */
666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k;
6680946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t rc;
6690946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t larAbsQ17;
670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < order; k++) {
672470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
673470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    rc = WEBRTC_SPL_ABS_W16(rcQ15[k]); //Q15
674470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Calculate larAbsQ17 in Q17 from rc in Q15 */
676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rc<24956) {  //0.7615966 in Q15
678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      // (Q15*Q13)>>11 = Q17
679f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker      larAbsQ17 = rc * 21512 >> 11;
680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else if (rc<30000) { //0.91552734375 in Q15
681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      // Q17 + (Q15*Q12)>>10 = Q17
682f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker      larAbsQ17 = -465024 + (rc * 29837 >> 10);
683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else if (rc<32500) { //0.99182128906250 in Q15
684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      // Q17 + (Q15*Q10)>>8 = Q17
685f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker      larAbsQ17 = -3324784 + (rc * 31863 >> 8);
686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else  {
687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      // Q17 + (Q15*Q5)>>3 = Q17
688f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker      larAbsQ17 = -88546020 + (rc * 21973 >> 3);
689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (rcQ15[k]>0) {
692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      larQ17[k] = larAbsQ17;
693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else {
694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      larQ17[k] = -larAbsQ17;
695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
7000946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic void Lar2RcFix(const int32_t *larQ17, int16_t *rcQ15,  int16_t order) {
701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /*
703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    This is a piece-wise implemenetation of a lar2rc-function
704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    See comment in Rc2LarFix() about details.
705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  */
706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k;
7080946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t larAbsQ11;
7090946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t rc;
710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < order; k++) {
712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
713a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    larAbsQ11 = (int16_t)WEBRTC_SPL_ABS_W32((larQ17[k] + 32) >> 6);  // Q11
714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (larAbsQ11<4097) { //2.000012018559 in Q11
716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      // Q11*Q16>>12 = Q15
717f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker      rc = larAbsQ11 * 24957 >> 12;
718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else if (larAbsQ11<6393) { //3.121320351712 in Q11
719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      // (Q11*Q17 + Q13)>>13 = Q15
720a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      rc = (larAbsQ11 * 17993 + 130738688) >> 13;
721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else if (larAbsQ11<11255) { //5.495270168700 in Q11
722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      // (Q11*Q19 + Q30)>>15 = Q15
723a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      rc = (larAbsQ11 * 16850 + 875329820) >> 15;
724470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    } else  {
725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      // (Q11*Q24>>16 + Q19)>>4 = Q15
726a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org      rc = (((larAbsQ11 * 24433) >> 16) + 515804) >> 4;
727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
728470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (larQ17[k]<=0) {
730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      rc = -rc;
731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
7330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    rcQ15[k] = (int16_t) rc;  // Q15
734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
7370946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic void Poly2LarFix(int16_t *lowbandQ15,
7380946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t orderLo,
7390946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t *hibandQ15,
7400946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t orderHi,
7410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t Nsub,
7420946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int32_t *larsQ17) {
743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k, n;
7450946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t *outpQ17;
7460946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t orderTot;
7470946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t larQ17[MAX_ORDER];   // Size 7+6 is enough
748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  orderTot = (orderLo + orderHi);
750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  outpQ17 = larsQ17;
751470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < Nsub; k++) {
752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Rc2LarFix(lowbandQ15, larQ17, orderLo);
754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < orderLo; n++)
756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      outpQ17[n] = larQ17[n]; //Q17
757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Rc2LarFix(hibandQ15, larQ17, orderHi);
759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
760470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < orderHi; n++)
761470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      outpQ17[n + orderLo] = larQ17[n]; //Q17;
762470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    outpQ17 += orderTot;
764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    lowbandQ15 += orderLo;
765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    hibandQ15 += orderHi;
766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
7700946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic void Lar2polyFix(int32_t *larsQ17,
7710946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t *lowbandQ15,
7720946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t orderLo,
7730946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t *hibandQ15,
7740946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t orderHi,
7750946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                        int16_t Nsub) {
776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k, n;
7780946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t orderTot;
7790946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t *outplQ15, *outphQ15;
7800946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t *inpQ17;
7810946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t rcQ15[7+6];
782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  orderTot = (orderLo + orderHi);
784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  outplQ15 = lowbandQ15;
785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  outphQ15 = hibandQ15;
786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  inpQ17 = larsQ17;
787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < Nsub; k++) {
788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* gains not handled here as in the FLP version */
790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Low band */
792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Lar2RcFix(&inpQ17[0], rcQ15, orderLo);
793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < orderLo; n++)
794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      outplQ15[n] = rcQ15[n]; // Refl. coeffs
795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* High band */
797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    Lar2RcFix(&inpQ17[orderLo], rcQ15, orderHi);
798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n = 0; n < orderHi; n++)
799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      outphQ15[n] = rcQ15[n]; // Refl. coeffs
800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    inpQ17 += orderTot;
802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    outplQ15 += orderLo;
803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    outphQ15 += orderHi;
804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
80723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org/*
80823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgFunction WebRtcIsacfix_MatrixProduct1C() does one form of matrix multiplication.
80923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgIt first shifts input data of one matrix, determines the right indexes for the
81023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgtwo matrixes, multiply them, and write the results into an output buffer.
81123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
81223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgNote that two factors (or, multipliers) determine the initialization values of
81323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgthe variable |matrix1_index| in the code. The relationship is
81423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org|matrix1_index| = |matrix1_index_factor1| * |matrix1_index_factor2|, where
81523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org|matrix1_index_factor1| is given by the argument while |matrix1_index_factor2|
81623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgis determined by the value of argument |matrix1_index_init_case|;
81723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org|matrix1_index_factor2| is the value of the outmost loop counter j (when
81823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org|matrix1_index_init_case| is 0), or the value of the middle loop counter k (when
81923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org|matrix1_index_init_case| is non-zero).
82023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
82123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org|matrix0_index| is determined the same way.
82223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
82323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgArguments:
82423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix0[]:                 matrix0 data in Q15 domain.
82523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix1[]:                 matrix1 data.
82623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix_product[]:          output data (matrix product).
82723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix1_index_factor1:     The first of two factors determining the
82823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                             initialization value of matrix1_index.
82923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix0_index_factor1:     The first of two factors determining the
83023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                             initialization value of matrix0_index.
83123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix1_index_init_case:   Case number for selecting the second of two
83223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                             factors determining the initialization value
83323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                             of matrix1_index and matrix0_index.
83423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix1_index_step:        Incremental step for matrix1_index.
83523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix0_index_step:        Incremental step for matrix0_index.
83623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  inner_loop_count:          Maximum count of the inner loop.
83723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  mid_loop_count:            Maximum count of the intermediate loop.
83823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  shift:                     Left shift value for matrix1.
83923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org*/
84023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgvoid WebRtcIsacfix_MatrixProduct1C(const int16_t matrix0[],
84123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int32_t matrix1[],
84223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   int32_t matrix_product[],
84323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int matrix1_index_factor1,
84423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int matrix0_index_factor1,
84523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int matrix1_index_init_case,
84623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int matrix1_index_step,
84723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int matrix0_index_step,
84823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int inner_loop_count,
84923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int mid_loop_count,
85023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int shift) {
85123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  int j = 0, k = 0, n = 0;
85223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  int matrix0_index = 0, matrix1_index = 0, matrix_prod_index = 0;
85323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  int* matrix0_index_factor2 = &k;
85423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  int* matrix1_index_factor2 = &j;
85523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  if (matrix1_index_init_case != 0) {
85623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    matrix0_index_factor2 = &j;
85723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    matrix1_index_factor2 = &k;
85823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  }
85923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
86023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
86123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    matrix_prod_index = mid_loop_count * j;
86223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    for (k = 0; k < mid_loop_count; k++) {
86323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      int32_t sum32 = 0;
86423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      matrix0_index = matrix0_index_factor1 * (*matrix0_index_factor2);
86523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      matrix1_index = matrix1_index_factor1 * (*matrix1_index_factor2);
86623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      for (n = 0; n < inner_loop_count; n++) {
86723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org        sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
86823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                              matrix1[matrix1_index] << shift));
86923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org        matrix0_index += matrix0_index_step;
87023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org        matrix1_index += matrix1_index_step;
87123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      }
87223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      matrix_product[matrix_prod_index] = sum32;
87323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      matrix_prod_index++;
87423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    }
87523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  }
87623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org}
87723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
87823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org/*
87923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgFunction WebRtcIsacfix_MatrixProduct2C() returns the product of two matrixes,
88023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgone of which has two columns. It first has to determine the correct index of
88123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgthe first matrix before doing the actual element multiplication.
88223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
88323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgArguments:
88423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix0[]:                 A matrix in Q15 domain.
88523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix1[]:                 A matrix in Q21 domain.
88623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix_product[]:          Output data in Q17 domain.
88723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix0_index_factor:      A factor determining the initialization value
88823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                             of matrix0_index.
88923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  matrix0_index_step:        Incremental step for matrix0_index.
89023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org*/
89123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.orgvoid WebRtcIsacfix_MatrixProduct2C(const int16_t matrix0[],
89223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int32_t matrix1[],
89323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   int32_t matrix_product[],
89423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int matrix0_index_factor,
89523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                   const int matrix0_index_step) {
89623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  int j = 0, n = 0;
89723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  int matrix1_index = 0, matrix0_index = 0, matrix_prod_index = 0;
89823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  for (j = 0; j < SUBFRAMES; j++) {
89923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    int32_t sum32 = 0, sum32_2 = 0;
90023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    matrix1_index = 0;
90123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    matrix0_index = matrix0_index_factor * j;
90223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    for (n = SUBFRAMES; n > 0; n--) {
90323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      sum32 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
90423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                            matrix1[matrix1_index]));
90523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      sum32_2 += (WEBRTC_SPL_MUL_16_32_RSFT16(matrix0[matrix0_index],
90623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                            matrix1[matrix1_index + 1]));
90723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      matrix1_index += 2;
90823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      matrix0_index += matrix0_index_step;
90923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    }
91023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    matrix_product[matrix_prod_index] = sum32 >> 3;
91123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    matrix_product[matrix_prod_index + 1] = sum32_2 >> 3;
91223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    matrix_prod_index += 2;
91323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  }
91423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org}
91523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
9160946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_DecodeLpc(int32_t *gain_lo_hiQ17,
9170946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                            int16_t *LPCCoef_loQ15,
9180946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                            int16_t *LPCCoef_hiQ15,
919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            Bitstr_dec *streamdata,
9200946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                            int16_t *outmodel) {
921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
9220946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_GAIN+KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int err;
924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecodeLpcCoef(streamdata, larsQ17, gain_lo_hiQ17, outmodel);
926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0)  // error check
927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_LPC;
928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* decode & dequantize LPC Coef */
935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint WebRtcIsacfix_DecodeLpcCoef(Bitstr_dec *streamdata,
9360946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                int32_t *LPCCoefQ17,
9370946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                int32_t *gain_lo_hiQ17,
9380946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                int16_t *outmodel)
939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int j, k, n;
941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int err;
9420946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t pos, pos2, posg, poss;
9430946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t gainpos;
9440946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t model;
9450946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index_QQ[KLT_ORDER_SHAPE];
9460946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
9470946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
9480946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t tmpcoeffs_sQ10[KLT_ORDER_SHAPE];
9490946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
9500946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs2_sQ18[KLT_ORDER_SHAPE];
9510946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t sumQQ;
9520946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t sumQQ16;
9530946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmp32;
954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
955470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy decoding of model number */
958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistOneStepMulti(&model, streamdata, WebRtcIsacfix_kModelCdfPtr, WebRtcIsacfix_kModelInitIndex, 1);
959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0)  // error check
960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return err;
961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy decoding of quantization indices */
963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfShapePtr[model], WebRtcIsacfix_kInitIndexShape[model], KLT_ORDER_SHAPE);
964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0)  // error check
965470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return err;
966470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization levels for coefficients */
967470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<KLT_ORDER_SHAPE; k++) {
968470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_sQ10[WebRtcIsacfix_kSelIndShape[k]] = WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[model]+WebRtcIsacfix_kOffsetShape[model][k] + index_QQ[k]];
969470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
970470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
971470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistOneStepMulti(index_QQ, streamdata, WebRtcIsacfix_kCdfGainPtr[model], WebRtcIsacfix_kInitIndexGain[model], KLT_ORDER_GAIN);
972470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0)  // error check
973470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return err;
974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization levels for coefficients */
975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<KLT_ORDER_GAIN; k++) {
976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[model]+ WebRtcIsacfix_kOffsetGain[model][k] + index_QQ[k]];
977470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* inverse KLT  */
981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* left transform */  // Transpose matrix!
98323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1GainQ15[model], tmpcoeffs_gQ17,
98423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                               tmpcoeffs2_gQ21, kTIndexFactor2, kTIndexFactor2,
98523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                               kTInitCase0, kTIndexStep1, kTIndexStep1,
98623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                               kTLoopCount2, kTLoopCount2, kTMatrix1_shift5);
98723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  poss = 0;
989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (j=0; j<SUBFRAMES; j++) {
990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k=0; k<LPC_SHAPE_ORDER; k++) {
991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      sumQQ = 0;
99223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      pos = LPC_SHAPE_ORDER * j;
99323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      pos2 = LPC_SHAPE_ORDER * k;
994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      for (n=0; n<LPC_SHAPE_ORDER; n++) {
995f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker        sumQQ += tmpcoeffs_sQ10[pos] *
996f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker            WebRtcIsacfix_kT1ShapeQ15[model][pos2] >> 7;  // (Q10*Q15)>>7 = Q18
997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        pos++;
998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        pos2++;
999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      }
1000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmpcoeffs2_sQ18[poss] = sumQQ; //Q18
1001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      poss++;
1002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1004470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1005470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* right transform */ // Transpose matrix
100623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
100723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor1, kTIndexStep2);
100823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[model],
100923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      tmpcoeffs2_sQ18, tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor1,
101023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      kTInitCase1, kTIndexStep3, kTIndexStep2, kTLoopCount1, kTLoopCount3,
101123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      kTMatrix1_shift0);
1012470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1013470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* scaling, mean addition, and gain restoration */
1014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  gainpos = 0;
1015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  posg = 0;poss = 0;pos=0;
1016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<SUBFRAMES; k++) {
1017470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1018470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* log gains */
1019a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
1020a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
1021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
1022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
1023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
1024470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gainpos++;
1025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posg++;
1026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1027a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
1028a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
1029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[model][posg];
1030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
1031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
1032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gainpos++;
1033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posg++;
1034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1035470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* lo band LAR coeffs */
1036470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n=0; n<ORDERLO; n++, pos++, poss++) {
1037470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
1038470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
1039470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      LPCCoefQ17[pos] = tmp32;
1040470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1041470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1042470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* hi band LAR coeffs */
1043470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n=0; n<ORDERHI; n++, pos++, poss++) {
1044d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker      // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
1045d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]) << 3;
1046470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[model][poss]; // Q17+Q17 = Q17
1047470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      LPCCoefQ17[pos] = tmp32;
1048470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1049470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1050470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1051470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1052470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  *outmodel=model;
1053470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1054470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1055470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1056470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1057470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* estimate codel length of LPC Coef */
10580946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic int EstCodeLpcCoef(int32_t *LPCCoefQ17,
10590946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                          int32_t *gain_lo_hiQ17,
10600946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                          int16_t *model,
10610946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                          int32_t *sizeQ11,
1062470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                          Bitstr_enc *streamdata,
1063eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org                          IsacSaveEncoderData* encData,
1064470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                          transcode_obj *transcodingParam) {
1065470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int j, k, n;
10660946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t posQQ, pos2QQ, gainpos;
10670946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t  pos, poss, posg, offsg;
10680946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index_gQQ[KLT_ORDER_GAIN], index_sQQ[KLT_ORDER_SHAPE];
10690946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index_ovr_gQQ[KLT_ORDER_GAIN], index_ovr_sQQ[KLT_ORDER_SHAPE];
10700946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t BitsQQ;
10710946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org
10720946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
10730946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
10740946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs_sQ17[KLT_ORDER_SHAPE];
10750946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
10760946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs2_sQ17[KLT_ORDER_SHAPE];
10770946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t sumQQ;
10780946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmp32;
10790946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t sumQQ16;
1080470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status = 0;
1081470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1082470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* write LAR coefficients to statistics file */
1083470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Save data for creation of multiple bitstreams (and transcoding) */
1084470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (encData != NULL) {
1085470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k=0; k<KLT_ORDER_GAIN; k++) {
1086470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
1087470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1088470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1089470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1090470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* log gains, mean removal and scaling */
1091470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  posg = 0;poss = 0;pos=0; gainpos=0;
1092470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1093470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<SUBFRAMES; k++) {
1094470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* log gains */
1095470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1096470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* The input argument X to logN(X) is 2^17 times higher than the
1097470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       input floating point argument Y to log(Y), since the X value
1098470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       is a Q17 value. This can be compensated for after the call, by
1099470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       subraction a value Z for each Q-step. One Q-step means that
1100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
1101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       177.445678 should be subtracted (since logN() returns a Q8 value).
1102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       For a X value in Q17, the value 177.445678*17 = 3017 should be
1103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       subtracted */
1104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posg++; gainpos++;
1107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1108470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1109470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posg++; gainpos++;
1111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* lo band LAR coeffs */
1113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n=0; n<ORDERLO; n++, poss++, pos++) {
1114470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
1115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(17203, tmp32<<3); // tmp32 = 2.1*tmp32
1116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmpcoeffs_sQ17[poss] = tmp32; //Q17
1117470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1118470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* hi band LAR coeffs */
1120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n=0; n<ORDERHI; n++, poss++, pos++) {
1121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = LPCCoefQ17[pos] - WebRtcIsacfix_kMeansShapeQ17[0][poss]; //Q17
1122470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(14746, tmp32<<1); // tmp32 = 0.45*tmp32
1123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmpcoeffs_sQ17[poss] = tmp32; //Q17
1124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1125470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1128470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1129470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* KLT  */
1130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* left transform */
1132470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  offsg = 0;
113323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  posg = 0;
1134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (j=0; j<SUBFRAMES; j++) {
113523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    // Q21 = Q6 * Q15
1136bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org    sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][0] +
1137bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org        tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
113823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    tmpcoeffs2_gQ21[posg] = sumQQ;
113923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    posg++;
114023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
114123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    // Q21 = Q6 * Q15
1142bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org    sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][1] +
1143bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org        tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
114423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    tmpcoeffs2_gQ21[posg] = sumQQ;
114523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    posg++;
114623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
1147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    offsg += 2;
1148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
115023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1ShapeQ15[0], tmpcoeffs_sQ17,
115123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      tmpcoeffs2_sQ17, kTIndexFactor4, kTIndexFactor1, kTInitCase0,
115223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      kTIndexStep1, kTIndexStep3, kTLoopCount3, kTLoopCount3, kTMatrix1_shift1);
115323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
1154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* right transform */
115523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
115623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
115723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
115823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[0], tmpcoeffs2_sQ17,
115923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor3, kTInitCase1, kTIndexStep3,
116023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      kTIndexStep1, kTLoopCount1, kTLoopCount3, kTMatrix1_shift1);
1161470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1162470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* quantize coefficients */
1163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  BitsQQ = 0;
1165470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
1166470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
1167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posQQ = WebRtcIsacfix_kSelIndGain[k];
11680946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
1169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
1171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (index_gQQ[k] < 0) {
1172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index_gQQ[k] = 0;
1173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
1175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
1176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index_ovr_gQQ[k] = WebRtcIsacfix_kOffsetGain[0][k]+index_gQQ[k];
1178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posQQ = WebRtcIsacfix_kOfLevelsGain[0] + index_ovr_gQQ[k];
1179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1180470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Save data for creation of multiple bitstreams */
1181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (encData != NULL) {
1182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
1183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1184470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* determine number of bits */
1186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sumQQ = WebRtcIsacfix_kCodeLenGainQ11[posQQ]; //Q11
1187470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    BitsQQ += sumQQ;
1188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<KLT_ORDER_SHAPE; k++) //ATTN: ok?
1191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
11920946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    index_sQQ[k] = (int16_t)(CalcLrIntQ(tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]], 17) + WebRtcIsacfix_kQuantMinShape[k]); //ATTN: ok?
1193470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (index_sQQ[k] < 0)
1195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index_sQQ[k] = 0;
1196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (index_sQQ[k] > WebRtcIsacfix_kMaxIndShape[k])
1197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index_sQQ[k] = WebRtcIsacfix_kMaxIndShape[k];
1198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index_ovr_sQQ[k] = WebRtcIsacfix_kOffsetShape[0][k]+index_sQQ[k];
1199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posQQ = WebRtcIsacfix_kOfLevelsShape[0] + index_ovr_sQQ[k];
1201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sumQQ = WebRtcIsacfix_kCodeLenShapeQ11[posQQ]; //Q11
1202470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    BitsQQ += sumQQ;
1203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  *model = 0;
1208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  *sizeQ11=BitsQQ;
1209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of model number */
1211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, model, WebRtcIsacfix_kModelCdfPtr, 1);
1212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (status < 0) {
1213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return status;
1214470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1216470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of quantization indices - shape only */
1217470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, index_sQQ, WebRtcIsacfix_kCdfShapePtr[0], KLT_ORDER_SHAPE);
1218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (status < 0) {
1219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return status;
1220470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1221470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Save data for creation of multiple bitstreams */
1223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (encData != NULL) {
1224470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k=0; k<KLT_ORDER_SHAPE; k++)
1225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      encData->LPCindex_s[KLT_ORDER_SHAPE*encData->startIdx + k] = index_sQQ[k];
1227470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1228470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* save the state of the bitstream object 'streamdata' for the possible bit-rate reduction */
1230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  transcodingParam->full         = streamdata->full;
1231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  transcodingParam->stream_index = streamdata->stream_index;
1232470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  transcodingParam->streamval    = streamdata->streamval;
1233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  transcodingParam->W_upper      = streamdata->W_upper;
1234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  transcodingParam->beforeLastWord     = streamdata->stream[streamdata->stream_index-1];
1235470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  transcodingParam->lastWord     = streamdata->stream[streamdata->stream_index];
1236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of index */
1238470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
1239470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (status < 0) {
1240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return status;
1241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1242470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1243470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization levels for shape coefficients */
1244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<KLT_ORDER_SHAPE; k++) {
1245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_sQ17[WebRtcIsacfix_kSelIndShape[k]] = WEBRTC_SPL_MUL(128, WebRtcIsacfix_kLevelsShapeQ10[WebRtcIsacfix_kOfLevelsShape[0]+index_ovr_sQQ[k]]);
1246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1248470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* inverse KLT  */
1249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1250470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* left transform */  // Transpose matrix!
125123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT1ShapeQ15[0], tmpcoeffs_sQ17,
125223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      tmpcoeffs2_sQ17, kTIndexFactor4, kTIndexFactor4, kTInitCase0,
125323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      kTIndexStep1, kTIndexStep1, kTLoopCount3, kTLoopCount3, kTMatrix1_shift1);
1254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* right transform */ // Transpose matrix
125623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct1(WebRtcIsacfix_kT2ShapeQ15[0], tmpcoeffs2_sQ17,
125723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      tmpcoeffs_sQ17, kTIndexFactor1, kTIndexFactor1, kTInitCase1, kTIndexStep3,
125823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      kTIndexStep2, kTLoopCount1, kTLoopCount3, kTMatrix1_shift1);
1259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* scaling, mean addition, and gain restoration */
1261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  poss = 0;pos=0;
1262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<SUBFRAMES; k++) {
1263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* lo band LAR coeffs */
1265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n=0; n<ORDERLO; n++, pos++, poss++) {
1266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(31208, tmpcoeffs_sQ17[poss]); // (Q16*Q17)>>16 = Q17, with 1/2.1 = 0.47619047619 ~= 31208 in Q16
1267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
1268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      LPCCoefQ17[pos] = tmp32;
1269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* hi band LAR coeffs */
1272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (n=0; n<ORDERHI; n++, pos++, poss++) {
1273d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker      // ((Q13*Q17)>>16)<<3 = Q17, with 1/0.45 = 2.222222222222 ~= 18204 in Q13
1274d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker      tmp32 = WEBRTC_SPL_MUL_16_32_RSFT16(18204, tmpcoeffs_sQ17[poss]) << 3;
1275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmp32 = tmp32 + WebRtcIsacfix_kMeansShapeQ17[0][poss]; // Q17+Q17 = Q17
1276470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      LPCCoefQ17[pos] = tmp32;
1277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  //to update tmpcoeffs_gQ17 to the proper state
1282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<KLT_ORDER_GAIN; k++) {
1283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ17[WebRtcIsacfix_kSelIndGain[k]] = WebRtcIsacfix_kLevelsGainQ17[WebRtcIsacfix_kOfLevelsGain[0]+index_ovr_gQQ[k]];
1284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization levels for coefficients */
1289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* left transform */
1291470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  offsg = 0;
1292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  posg = 0;
1293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (j=0; j<SUBFRAMES; j++) {
129423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    // (Q15 * Q17) >> (16 - 1) = Q17; Q17 << 4 = Q21.
129523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    sumQQ = (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][0],
129623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                         tmpcoeffs_gQ17[offsg]) << 1);
129723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][1],
129823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                          tmpcoeffs_gQ17[offsg + 1]) << 1);
1299d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    tmpcoeffs2_gQ21[posg] = sumQQ << 4;
130023da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    posg++;
130123da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
130223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    sumQQ = (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][2],
130323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                         tmpcoeffs_gQ17[offsg]) << 1);
130423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    sumQQ += (WEBRTC_SPL_MUL_16_32_RSFT16(WebRtcIsacfix_kT1GainQ15[0][3],
130523da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                                          tmpcoeffs_gQ17[offsg + 1]) << 1);
1306d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker    tmpcoeffs2_gQ21[posg] = sumQQ << 4;
130723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org    posg++;
1308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    offsg += 2;
1309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* right transform */ // Transpose matrix
131223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
131323da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor1, kTIndexStep2);
1314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* scaling, mean addition, and gain restoration */
1316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  posg = 0;
1317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  gainpos = 0;
1318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<2*SUBFRAMES; k++) {
1319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1320a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    // Divide by 4 and get Q17 to Q8, i.e. shift 2+9.
1321a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    sumQQ16 = (int16_t)(tmpcoeffs_gQ17[posg] >> 11);
1322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sumQQ16 += WebRtcIsacfix_kMeansGainQ8[0][posg];
1323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    sumQQ = CalcExpN(sumQQ16); // Q8 in and Q17 out
1324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gain_lo_hiQ17[gainpos] = sumQQ; //Q17
1325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    gainpos++;
1327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    pos++;posg++;
1328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1331470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
13330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_EstCodeLpcGain(int32_t *gain_lo_hiQ17,
1334470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                                 Bitstr_enc *streamdata,
1335eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org                                 IsacSaveEncoderData* encData) {
133623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  int j, k;
13370946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t posQQ, pos2QQ, gainpos;
13380946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t posg;
13390946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index_gQQ[KLT_ORDER_GAIN];
13400946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org
13410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
13420946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
13430946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
13440946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t sumQQ;
1345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status = 0;
1346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1347470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* write LAR coefficients to statistics file */
1348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Save data for creation of multiple bitstreams (and transcoding) */
1349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (encData != NULL) {
1350470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (k=0; k<KLT_ORDER_GAIN; k++) {
1351470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      encData->LPCcoeffs_g[KLT_ORDER_GAIN*encData->startIdx + k] = gain_lo_hiQ17[k];
1352470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1353470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1354470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* log gains, mean removal and scaling */
135623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  posg = 0; gainpos = 0;
1357470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<SUBFRAMES; k++) {
1359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* log gains */
1360470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1361470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* The input argument X to logN(X) is 2^17 times higher than the
1362470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       input floating point argument Y to log(Y), since the X value
1363470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       is a Q17 value. This can be compensated for after the call, by
1364470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       subraction a value Z for each Q-step. One Q-step means that
1365470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
1366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       177.445678 should be subtracted (since logN() returns a Q8 value).
1367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       For a X value in Q17, the value 177.445678*17 = 3017 should be
1368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       subtracted */
1369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1370470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posg++; gainpos++;
1372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1374470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posg++; gainpos++;
1376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1377470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1378470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* KLT  */
1380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* left transform */
138223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  posg = 0;
1383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (j=0; j<SUBFRAMES; j++) {
138423da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      // Q21 = Q6 * Q15
1385bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org      sumQQ = tmpcoeffs_gQ6[j * 2] * WebRtcIsacfix_kT1GainQ15[0][0] +
1386bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org          tmpcoeffs_gQ6[j * 2 + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
1387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      tmpcoeffs2_gQ21[posg] = sumQQ;
1388470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      posg++;
1389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1390bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org      sumQQ = tmpcoeffs_gQ6[j * 2] * WebRtcIsacfix_kT1GainQ15[0][1] +
1391bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org          tmpcoeffs_gQ6[j * 2 + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
139223da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org      tmpcoeffs2_gQ21[posg] = sumQQ;
1393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      posg++;
1394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
139623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  /* right transform */
139723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
139823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
139923da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org
1400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* quantize coefficients */
1401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
1403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
1404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posQQ = WebRtcIsacfix_kSelIndGain[k];
14050946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
1406470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1407470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
1408470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (index_gQQ[k] < 0) {
1409470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index_gQQ[k] = 0;
1410470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
1412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
1413470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1415470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Save data for creation of multiple bitstreams */
1416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (encData != NULL) {
1417470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_gQQ[k];
1418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1419470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1421470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of index */
1422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, index_gQQ, WebRtcIsacfix_kCdfGainPtr[0], KLT_ORDER_GAIN);
1423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (status < 0) {
1424470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return status;
1425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1427470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1429470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
14310946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_EncodeLpc(int32_t *gain_lo_hiQ17,
14320946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                            int16_t *LPCCoef_loQ15,
14330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                            int16_t *LPCCoef_hiQ15,
14340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                            int16_t *model,
14350946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                            int32_t *sizeQ11,
1436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            Bitstr_enc *streamdata,
1437eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org                            IsacSaveEncoderData* encData,
1438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                            transcode_obj *transcodeParam)
1439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status = 0;
14410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t larsQ17[KLT_ORDER_SHAPE]; // KLT_ORDER_SHAPE == (ORDERLO+ORDERHI)*SUBFRAMES
1442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  // = (6+12)*6 == 108
1443470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  Poly2LarFix(LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES, larsQ17);
1445470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
144623da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  status = EstCodeLpcCoef(larsQ17, gain_lo_hiQ17, model, sizeQ11,
144723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                          streamdata, encData, transcodeParam);
1448470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (status < 0) {
1449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return (status);
1450470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  Lar2polyFix(larsQ17, LPCCoef_loQ15, ORDERLO, LPCCoef_hiQ15, ORDERHI, SUBFRAMES);
1453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1454470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1455470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1456470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1457470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1458470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* decode & dequantize RC */
14590946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_DecodeRcCoef(Bitstr_dec *streamdata, int16_t *RCQ15)
1460470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1461470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k, err;
14620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index[AR_ORDER];
1463470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1464470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy decoding of quantization indices */
1465470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistOneStepMulti(index, streamdata, WebRtcIsacfix_kRcCdfPtr, WebRtcIsacfix_kRcInitInd, AR_ORDER);
1466470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0)  // error check
1467470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return err;
1468470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1469470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization levels for reflection coefficients */
1470470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<AR_ORDER; k++)
1471470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
1472470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
1473470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1474470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1475470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1476470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1477470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1478470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1479470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1480470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* quantize & code RC */
14810946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_EncodeRcCoef(int16_t *RCQ15, Bitstr_enc *streamdata)
1482470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1483470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k;
14840946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index[AR_ORDER];
1485470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status;
1486470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1487470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* quantize reflection coefficients (add noise feedback?) */
1488470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<AR_ORDER; k++)
1489470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
1490470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index[k] = WebRtcIsacfix_kRcInitInd[k];
1491470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1492470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k]])
1493470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1494470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      while (RCQ15[k] > WebRtcIsacfix_kRcBound[index[k] + 1])
1495470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com        index[k]++;
1496470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1497470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else
1498470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    {
1499470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      while (RCQ15[k] < WebRtcIsacfix_kRcBound[--index[k]]) ;
1500470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1501470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1502470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    RCQ15[k] = *(WebRtcIsacfix_kRcLevPtr[k] + index[k]);
1503470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1504470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1505470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1506470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of quantization indices */
1507470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, index, WebRtcIsacfix_kRcCdfPtr, AR_ORDER);
1508470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1509470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
1510470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return status;
1511470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1512470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1513470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1514470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* decode & dequantize squared Gain */
15150946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_DecodeGain2(Bitstr_dec *streamdata, int32_t *gainQ10)
1516470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1517470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int err;
15180946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index;
1519470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1520470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy decoding of quantization index */
1521470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistOneStepMulti(
1522470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      &index,
1523470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      streamdata,
1524470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      WebRtcIsacfix_kGainPtr,
1525470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      WebRtcIsacfix_kGainInitInd,
1526470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      1);
1527470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* error check */
1528470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0) {
1529470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return err;
1530470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1532470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization level */
1533470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
1534470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1535470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1536470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1538470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1539470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1540470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* quantize & code squared Gain */
15410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_EncodeGain2(int32_t *gainQ10, Bitstr_enc *streamdata)
1542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
15430946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index;
1544470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status = 0;
1545470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization index */
1547470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  index = WebRtcIsacfix_kGainInitInd[0];
1548470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (*gainQ10 > WebRtcIsacfix_kGain2Bound[index])
1549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
1550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    while (*gainQ10 > WebRtcIsacfix_kGain2Bound[index + 1])
1551470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index++;
1552470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1553470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  else
1554470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
1555470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    while (*gainQ10 < WebRtcIsacfix_kGain2Bound[--index]) ;
1556470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1558470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* dequantize */
1559470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  *gainQ10 = WebRtcIsacfix_kGain2Lev[index];
1560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of quantization index */
1562470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, &index, WebRtcIsacfix_kGainPtr, 1);
1563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
1565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return status;
1566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1567470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1568470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* code and decode Pitch Gains and Lags functions */
1570470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1571470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* decode & dequantize Pitch Gains */
15720946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_DecodePitchGain(Bitstr_dec *streamdata, int16_t *PitchGains_Q12)
1573470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1574470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int err;
15750946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index_comb;
15760946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t *pitch_gain_cdf_ptr[1];
1577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1578470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy decoding of quantization indices */
1579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
1580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistBisectMulti(&index_comb, streamdata, pitch_gain_cdf_ptr, WebRtcIsacfix_kCdfTableSizeGain, 1);
1581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* error check, Q_mean_Gain.. tables are of size 144 */
15821617f65eecbd894b17870929a9ffec4d62078d89tina.legrand@webrtc.org  if ((err < 0) || (index_comb < 0) || (index_comb >= 144))
1583470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
1584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1585470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* unquantize back to pitch gains by table look-up */
1586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
1587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
1588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
1589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
1590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1595470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* quantize & code Pitch Gains */
1596eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.orgint WebRtcIsacfix_EncodePitchGain(int16_t* PitchGains_Q12,
1597eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org                                  Bitstr_enc* streamdata,
1598eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org                                  IsacSaveEncoderData* encData) {
1599470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k,j;
16000946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t SQ15[PITCH_SUBFRAMES];
16010946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index[3];
16020946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index_comb;
16030946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t *pitch_gain_cdf_ptr[1];
16040946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t CQ17;
1605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status = 0;
1606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* get the approximate arcsine (almost linear)*/
1609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<PITCH_SUBFRAMES; k++)
1610f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker    SQ15[k] = (int16_t)(PitchGains_Q12[k] * 33 >> 2);  // Q15
1611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization index; only for the first three transform coefficients */
1614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<3; k++)
1615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
1616470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /*  transform */
1617470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CQ17=0;
1618470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (j=0; j<PITCH_SUBFRAMES; j++) {
1619f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker      CQ17 += WebRtcIsacfix_kTransform[k][j] * SQ15[j] >> 10;  // Q17
1620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1621470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
16220946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    index[k] = (int16_t)((CQ17 + 8192)>>14); // Rounding and scaling with stepsize (=1/0.125=8)
1623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* check that the index is not outside the boundaries of the table */
1625470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (index[k] < WebRtcIsacfix_kLowerlimiGain[k]) index[k] = WebRtcIsacfix_kLowerlimiGain[k];
1626470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (index[k] > WebRtcIsacfix_kUpperlimitGain[k]) index[k] = WebRtcIsacfix_kUpperlimitGain[k];
1627470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index[k] -= WebRtcIsacfix_kLowerlimiGain[k];
1628470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* calculate unique overall index */
16310946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  index_comb = (int16_t)(WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[0], index[0]) +
1632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com                               WEBRTC_SPL_MUL(WebRtcIsacfix_kMultsGain[1], index[1]) + index[2]);
1633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* unquantize back to pitch gains by table look-up */
1635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  // (Y)
1636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  PitchGains_Q12[0] = WebRtcIsacfix_kPitchGain1[index_comb];
1637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  PitchGains_Q12[1] = WebRtcIsacfix_kPitchGain2[index_comb];
1638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  PitchGains_Q12[2] = WebRtcIsacfix_kPitchGain3[index_comb];
1639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  PitchGains_Q12[3] = WebRtcIsacfix_kPitchGain4[index_comb];
1640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of quantization pitch gains */
1643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  *pitch_gain_cdf_ptr = WebRtcIsacfix_kPitchGainCdf;
1644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, &index_comb, pitch_gain_cdf_ptr, 1);
1645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (status < 0) {
1646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return status;
1647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1648470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Save data for creation of multiple bitstreams */
1650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (encData != NULL) {
1651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    encData->pitchGain_index[encData->startIdx] = index_comb;
1652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1659470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* Pitch LAG */
1660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* decode & dequantize Pitch Lags */
1663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint WebRtcIsacfix_DecodePitchLag(Bitstr_dec *streamdata,
16640946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                 int16_t *PitchGain_Q12,
16650946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                 int16_t *PitchLags_Q7)
1666470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1667470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k, err;
16680946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index[PITCH_SUBFRAMES];
16690946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const int16_t *mean_val2Q10, *mean_val4Q10;
1670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
16710946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const int16_t *lower_limit;
16720946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t *init_index;
16730946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t *cdf_size;
16740946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t **cdf;
1675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
16760946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t meangainQ12;
16770946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t CQ11, CQ10,tmp32a,tmp32b;
1678728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting  int16_t shft;
1679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  meangainQ12=0;
1681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < 4; k++)
1682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    meangainQ12 += PitchGain_Q12[k];
1683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1684a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org  meangainQ12 >>= 2;  // Get average.
1685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* voicing classificiation */
1687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (meangainQ12 <= 819) {                 // mean_gain < 0.2
1688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shft = -1;        // StepSize=2.0;
1689470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf = WebRtcIsacfix_kPitchLagPtrLo;
1690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf_size = WebRtcIsacfix_kPitchLagSizeLo;
1691470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
1692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
1693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    lower_limit = WebRtcIsacfix_kLowerLimitLo;
1694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    init_index = WebRtcIsacfix_kInitIndLo;
1695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else if (meangainQ12 <= 1638) {            // mean_gain < 0.4
1696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shft = 0;        // StepSize=1.0;
1697470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf = WebRtcIsacfix_kPitchLagPtrMid;
1698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf_size = WebRtcIsacfix_kPitchLagSizeMid;
1699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
1700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
1701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    lower_limit = WebRtcIsacfix_kLowerLimitMid;
1702470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    init_index = WebRtcIsacfix_kInitIndMid;
1703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
1704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shft = 1;        // StepSize=0.5;
1705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf = WebRtcIsacfix_kPitchLagPtrHi;
1706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf_size = WebRtcIsacfix_kPitchLagSizeHi;
1707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
1708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
1709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    lower_limit = WebRtcIsacfix_kLowerLimitHi;
1710470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    init_index = WebRtcIsacfix_kInitIndHi;
1711470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1712470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1713470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy decoding of quantization indices */
1714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
1715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if ((err<0) || (index[0]<0))  // error check
1716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
1717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistOneStepMulti(index+1, streamdata, cdf+1, init_index, 3);
1719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0)  // error check
1720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
1721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1723470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
17240946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  CQ11 = ((int32_t)index[0] + lower_limit[0]);  // Q0
1725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
1726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<PITCH_SUBFRAMES; k++) {
1727470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmp32a =  WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11);
1728728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting    PitchLags_Q7[k] = (int16_t)(tmp32a >> 5);
1729470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1730470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CQ10 = mean_val2Q10[index[1]];
1732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<PITCH_SUBFRAMES; k++) {
1733f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker    tmp32b = WebRtcIsacfix_kTransform[1][k] * (int16_t)CQ10 >> 10;
1734728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting    PitchLags_Q7[k] += (int16_t)(tmp32b >> 5);
1735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CQ10 = mean_val4Q10[index[3]];
1738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<PITCH_SUBFRAMES; k++) {
1739f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker    tmp32b = WebRtcIsacfix_kTransform[3][k] * (int16_t)CQ10 >> 10;
1740728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting    PitchLags_Q7[k] += (int16_t)(tmp32b >> 5);
1741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return 0;
1744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* quantize & code Pitch Lags */
1749eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.orgint WebRtcIsacfix_EncodePitchLag(int16_t* PitchLagsQ7,
1750eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org                                 int16_t* PitchGain_Q12,
1751eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org                                 Bitstr_enc* streamdata,
1752eb544460e47140d494dddf1217a698a1dcf4dee0pbos@webrtc.org                                 IsacSaveEncoderData* encData) {
1753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int k, j;
17540946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t index[PITCH_SUBFRAMES];
17550946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t meangainQ12, CQ17;
17560946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t CQ11, CQ10,tmp32a;
17570946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org
17580946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const int16_t *mean_val2Q10,*mean_val4Q10;
17590946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const int16_t *lower_limit, *upper_limit;
17600946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  const uint16_t **cdf;
1761728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting  int16_t shft, tmp16b;
17620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmp32b;
1763470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status = 0;
1764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* compute mean pitch gain */
1766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  meangainQ12=0;
1767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k = 0; k < 4; k++)
1768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    meangainQ12 += PitchGain_Q12[k];
1769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1770a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org  meangainQ12 >>= 2;
1771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* Save data for creation of multiple bitstreams */
1773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (encData != NULL) {
1774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    encData->meanGain[encData->startIdx] = meangainQ12;
1775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1776470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1777470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* voicing classificiation */
1778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (meangainQ12 <= 819) {                 // mean_gain < 0.2
1779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shft = -1;        // StepSize=2.0;
1780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf = WebRtcIsacfix_kPitchLagPtrLo;
1781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Lo;
1782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Lo;
1783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    lower_limit = WebRtcIsacfix_kLowerLimitLo;
1784470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    upper_limit = WebRtcIsacfix_kUpperLimitLo;
1785470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else if (meangainQ12 <= 1638) {            // mean_gain < 0.4
1786470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shft = 0;        // StepSize=1.0;
1787470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf = WebRtcIsacfix_kPitchLagPtrMid;
1788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Mid;
1789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Mid;
1790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    lower_limit = WebRtcIsacfix_kLowerLimitMid;
1791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    upper_limit = WebRtcIsacfix_kUpperLimitMid;
1792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  } else {
1793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    shft = 1;        // StepSize=0.5;
1794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    cdf = WebRtcIsacfix_kPitchLagPtrHi;
1795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val2Q10 = WebRtcIsacfix_kMeanLag2Hi;
1796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    mean_val4Q10 = WebRtcIsacfix_kMeanLag4Hi;
1797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    lower_limit = WebRtcIsacfix_kLowerLimitHi;
1798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    upper_limit = WebRtcIsacfix_kUpperLimitHi;
1799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* find quantization index */
1802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<4; k++)
1803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
1804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /*  transform */
1805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CQ17=0;
1806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    for (j=0; j<PITCH_SUBFRAMES; j++)
1807f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker      CQ17 += WebRtcIsacfix_kTransform[k][j] * PitchLagsQ7[j] >> 2;  // Q17
1808470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    CQ17 = WEBRTC_SPL_SHIFT_W32(CQ17,shft); // Scale with StepSize
1810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* quantize */
1812a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org    tmp16b = (int16_t)((CQ17 + 65536) >> 17);
1813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index[k] =  tmp16b;
1814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* check that the index is not outside the boundaries of the table */
1816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (index[k] < lower_limit[k]) index[k] = lower_limit[k];
1817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (index[k] > upper_limit[k]) index[k] = upper_limit[k];
1818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index[k] -= lower_limit[k];
1819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* Save data for creation of multiple bitstreams */
1821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if(encData != NULL) {
1822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      encData->pitchIndex[PITCH_SUBFRAMES*encData->startIdx + k] = index[k];
1823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
1824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
1827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CQ11 = (index[0] + lower_limit[0]);  // Q0
1828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CQ11 = WEBRTC_SPL_SHIFT_W32(CQ11,11-shft); // Scale with StepSize, Q11
1829470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1830470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<PITCH_SUBFRAMES; k++) {
1831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmp32a =  WEBRTC_SPL_MUL_16_32_RSFT11(WebRtcIsacfix_kTransform[0][k], CQ11); // Q12
1832728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting    PitchLagsQ7[k] = (int16_t)(tmp32a >> 5);  // Q7.
1833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CQ10 = mean_val2Q10[index[1]];
1836470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<PITCH_SUBFRAMES; k++) {
1837f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker    tmp32b = WebRtcIsacfix_kTransform[1][k] * (int16_t)CQ10 >> 10;
1838728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting    PitchLagsQ7[k] += (int16_t)(tmp32b >> 5);  // Q7.
1839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  CQ10 = mean_val4Q10[index[3]];
1842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<PITCH_SUBFRAMES; k++) {
1843f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker    tmp32b = WebRtcIsacfix_kTransform[3][k] * (int16_t)CQ10 >> 10;
1844728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting    PitchLagsQ7[k] += (int16_t)(tmp32b >> 5);  // Q7.
1845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of quantization pitch lags */
1848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, index, cdf, PITCH_SUBFRAMES);
1849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1850470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* If error in WebRtcIsacfix_EncHistMulti(), status will be negative, otherwise 0 */
1851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return status;
1852470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1853470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1855470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* Routines for inband signaling of bandwitdh estimation */
1857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* Histograms based on uniform distribution of indices */
1858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* Move global variables later! */
1859470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* cdf array for frame length indicator */
18620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgconst uint16_t kFrameLenCdf[4] = {
1863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  0, 21845, 43690, 65535};
1864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* pointer to cdf array for frame length indicator */
18660946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgconst uint16_t *kFrameLenCdfPtr[1] = {kFrameLenCdf};
1867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* initial cdf index for decoder of frame length indicator */
18690946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgconst uint16_t kFrameLenInitIndex[1] = {1};
1870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1871470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1872470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comint WebRtcIsacfix_DecodeFrameLen(Bitstr_dec *streamdata,
1873dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                                 size_t *framesamples)
1874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1876470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int err;
18770946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t frame_mode;
1878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = 0;
1880470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy decoding of frame length [1:30ms,2:60ms] */
1881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistOneStepMulti(&frame_mode, streamdata, kFrameLenCdfPtr, kFrameLenInitIndex, 1);
1882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0)  // error check
1883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH;
1884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  switch(frame_mode) {
1886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    case 1:
1887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *framesamples = 480; /* 30ms */
1888470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      break;
1889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    case 2:
1890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      *framesamples = 960; /* 60ms */
1891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      break;
1892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    default:
1893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      err = -ISAC_DISALLOWED_FRAME_MODE_DECODER;
1894470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return err;
1897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1899470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
19000946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_EncodeFrameLen(int16_t framesamples, Bitstr_enc *streamdata) {
1901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status;
19030946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t frame_mode;
1904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = 0;
1906470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  frame_mode = 0;
1907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy coding of frame length [1:480 samples,2:960 samples] */
1908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  switch(framesamples) {
1909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    case 480:
1910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      frame_mode = 1;
1911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      break;
1912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    case 960:
1913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      frame_mode = 2;
1914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      break;
1915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    default:
1916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      status = - ISAC_DISALLOWED_FRAME_MODE_ENCODER;
1917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1919470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (status < 0)
1920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return status;
1921470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, &frame_mode, kFrameLenCdfPtr, 1);
1923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return status;
1925470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* cdf array for estimated bandwidth */
19280946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgconst uint16_t kBwCdf[25] = {
1929470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  0, 2731, 5461, 8192, 10923, 13653, 16384, 19114, 21845, 24576, 27306, 30037,
1930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  32768, 35498, 38229, 40959, 43690, 46421, 49151, 51882, 54613, 57343, 60074,
1931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  62804, 65535};
1932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* pointer to cdf array for estimated bandwidth */
19340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgconst uint16_t *kBwCdfPtr[1] = {kBwCdf};
1935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* initial cdf index for decoder of estimated bandwidth*/
19370946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgconst uint16_t kBwInitIndex[1] = {7};
1938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
19400946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_DecodeSendBandwidth(Bitstr_dec *streamdata, int16_t *BWno) {
1941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int err;
19430946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t BWno32;
1944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy decoding of sender's BW estimation [0..23] */
1946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  err = WebRtcIsacfix_DecHistOneStepMulti(&BWno32, streamdata, kBwCdfPtr, kBwInitIndex, 1);
1947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  if (err<0)  // error check
1948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    return -ISAC_RANGE_ERROR_DECODE_BANDWIDTH;
19490946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  *BWno = (int16_t)BWno32;
1950470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return err;
1951470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1952470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1953470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1954470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
19550946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint WebRtcIsacfix_EncodeReceiveBandwidth(int16_t *BWno, Bitstr_enc *streamdata)
1956470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{
1957470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  int status = 0;
1958470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* entropy encoding of receiver's BW estimation [0..23] */
1959470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  status = WebRtcIsacfix_EncHistMulti(streamdata, BWno, kBwCdfPtr, 1);
1960470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1961470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  return status;
1962470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
1963470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1964470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* estimate codel length of LPC Coef */
19650946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgvoid WebRtcIsacfix_TranscodeLpcCoef(int32_t *gain_lo_hiQ17,
19660946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org                                    int16_t *index_gQQ) {
196723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  int j, k;
19680946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t posQQ, pos2QQ;
19690946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int16_t posg, offsg, gainpos;
19700946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs_gQ6[KLT_ORDER_GAIN];
19710946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs_gQ17[KLT_ORDER_GAIN];
19720946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t tmpcoeffs2_gQ21[KLT_ORDER_GAIN];
19730946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org  int32_t sumQQ;
1974470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1975470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1976470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* log gains, mean removal and scaling */
197723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  posg = 0; gainpos=0;
1978470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1979470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<SUBFRAMES; k++) {
1980470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* log gains */
1981470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1982470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    /* The input argument X to logN(X) is 2^17 times higher than the
1983470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       input floating point argument Y to log(Y), since the X value
1984470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       is a Q17 value. This can be compensated for after the call, by
1985470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       subraction a value Z for each Q-step. One Q-step means that
1986470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       X gets 2 times higher, i.e. Z = logN(2)*256 = 0.693147180559*256 =
1987470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       177.445678 should be subtracted (since logN() returns a Q8 value).
1988470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       For a X value in Q17, the value 177.445678*17 = 3017 should be
1989470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com       subtracted */
1990470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1991470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1992470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posg++; gainpos++;
1993470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1994470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] = CalcLogN(gain_lo_hiQ17[gainpos])-3017; //Q8
1995470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    tmpcoeffs_gQ6[posg] -= WebRtcIsacfix_kMeansGainQ8[0][posg]; //Q8, but Q6 after not-needed mult. by 4
1996470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posg++; gainpos++;
1997470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
1998470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
1999470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2000470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2001470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* KLT  */
2002470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2003470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* left transform */
2004cf8e1081584a3e766a55b2eadf337090047ff14akma@webrtc.org  for (j = 0, offsg = 0; j < SUBFRAMES; j++, offsg += 2) {
2005e5a81ed7939f7c530028b583fabfd54ceeb8a6f2kma@webrtc.org    // Q21 = Q6 * Q15
2006bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org    sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][0] +
2007bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org        tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][2];
2008e5a81ed7939f7c530028b583fabfd54ceeb8a6f2kma@webrtc.org    tmpcoeffs2_gQ21[offsg] = sumQQ;
2009470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2010e5a81ed7939f7c530028b583fabfd54ceeb8a6f2kma@webrtc.org    // Q21 = Q6 * Q15
2011bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org    sumQQ = tmpcoeffs_gQ6[offsg] * WebRtcIsacfix_kT1GainQ15[0][1] +
2012bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org        tmpcoeffs_gQ6[offsg + 1] * WebRtcIsacfix_kT1GainQ15[0][3];
2013e5a81ed7939f7c530028b583fabfd54ceeb8a6f2kma@webrtc.org    tmpcoeffs2_gQ21[offsg + 1] = sumQQ;
2014470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
2015470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2016470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* right transform */
201723da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org  WebRtcIsacfix_MatrixProduct2(WebRtcIsacfix_kT2GainQ15[0], tmpcoeffs2_gQ21,
201823da8622c04ac843f7912dd33b4ad55f41422119kma@webrtc.org                               tmpcoeffs_gQ17, kTIndexFactor3, kTIndexStep1);
2019470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2020470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  /* quantize coefficients */
2021470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  for (k=0; k<KLT_ORDER_GAIN; k++) //ATTN: ok?
2022470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  {
2023470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    posQQ = WebRtcIsacfix_kSelIndGain[k];
20240946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org    pos2QQ= (int16_t)CalcLrIntQ(tmpcoeffs_gQ17[posQQ], 17);
2025470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com
2026470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    index_gQQ[k] = pos2QQ + WebRtcIsacfix_kQuantMinGain[k]; //ATTN: ok?
2027470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    if (index_gQQ[k] < 0) {
2028470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index_gQQ[k] = 0;
2029470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2030470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    else if (index_gQQ[k] > WebRtcIsacfix_kMaxIndGain[k]) {
2031470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com      index_gQQ[k] = WebRtcIsacfix_kMaxIndGain[k];
2032470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com    }
2033470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com  }
2034470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}
2035