1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * encode.c
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * This file contains definition of funtions for encoding.
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdlib.h>
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h>
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdio.h>
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "structs.h"
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "codec.h"
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pitch_estimator.h"
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "entropy_coding.h"
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "arith_routines.h"
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pitch_gain_tables.h"
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "pitch_lag_tables.h"
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "spectrum_ar_model_tables.h"
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_tables.h"
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_analysis.h"
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "bandwidth_estimator.h"
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_shape_swb12_tables.h"
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_shape_swb16_tables.h"
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include "lpc_gain_swb_tables.h"
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define UB_LOOKAHEAD 24
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Rate allocation tables of lower and upper-band bottleneck for
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  12kHz & 16kHz bandwidth.
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  12 kHz bandwidth
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  -----------------
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  The overall bottleneck of the coder is between 38 kbps and 45 kbps. We have
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  considered 7 enteries, uniformly distributed in this interval, i.e. 38,
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  39.17, 40.33, 41.5, 42.67, 43.83 and 45. For every entery, the lower-band
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  and the upper-band bottlenecks are specified in
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  'kLowerBandBitRate12' and 'kUpperBandBitRate12'
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  tables, respectively. E.g. the overall rate of 41.5 kbps corresponts to a
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bottleneck of 31 kbps for lower-band and 27 kbps for upper-band. Given an
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  overall bottleneck of the codec, we use linear interpolation to get
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  lower-band and upper-band bottlenecks.
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  16 kHz bandwidth
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  -----------------
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  The overall bottleneck of the coder is between 50 kbps and 56 kbps. We have
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  considered 7 enteries, uniformly distributed in this interval, i.e. 50, 51.2,
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  52.4, 53.6, 54.8 and 56. For every entery, the lower-band and the upper-band
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bottlenecks are specified in 'kLowerBandBitRate16' and
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  'kUpperBandBitRate16' tables, respectively. E.g. the overall rate
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  of 53.6 kbps corresponts to a bottleneck of 32 kbps for lower-band and 30
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  kbps for upper-band. Given an overall bottleneck of the codec, we use linear
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  interpolation to get lower-band and upper-band bottlenecks.
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*     38  39.17  40.33   41.5  42.67  43.83     45 */
73fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const int16_t kLowerBandBitRate12[7] = {
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    29000, 30000, 30000, 31000, 31000, 32000, 32000 };
75fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const int16_t kUpperBandBitRate12[7] = {
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    25000, 25000, 27000, 27000, 29000, 29000, 32000 };
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*    50     51.2  52.4   53.6   54.8    56 */
79fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const int16_t kLowerBandBitRate16[6] = {
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    31000, 31000, 32000, 32000, 32000, 32000 };
81fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const int16_t kUpperBandBitRate16[6] = {
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    28000, 29000, 29000, 30000, 31000, 32000 };
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/******************************************************************************
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * WebRtcIsac_RateAllocation()
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Internal function to perform a rate-allocation for upper and lower-band,
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * given a total rate.
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Input:
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *   - inRateBitPerSec           : a total bottleneck in bits/sec.
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Output:
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *   - rateLBBitPerSec           : a bottleneck allocated to the lower-band
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *                                 in bits/sec.
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *   - rateUBBitPerSec           : a bottleneck allocated to the upper-band
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *                                 in bits/sec.
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Return value                  : 0 if rate allocation has been successful.
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *                                -1 if failed to allocate rates.
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
102fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_RateAllocation(int32_t inRateBitPerSec,
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                        double* rateLBBitPerSec,
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                        double* rateUBBitPerSec,
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                        enum ISACBandwidth* bandwidthKHz) {
106fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t idx;
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double idxD;
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double idxErr;
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (inRateBitPerSec < 38000) {
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* If the given overall bottleneck is less than 38000 then
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * then codec has to operate in wideband mode, i.e. 8 kHz
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * bandwidth. */
113fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    *rateLBBitPerSec = (int16_t)((inRateBitPerSec > 32000) ?
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        32000 : inRateBitPerSec);
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *rateUBBitPerSec = 0;
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *bandwidthKHz = isac8kHz;
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if ((inRateBitPerSec >= 38000) && (inRateBitPerSec < 50000)) {
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* At a bottleneck between 38 and 50 kbps the codec is operating
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * at 12 kHz bandwidth. Using xxxBandBitRate12[] to calculates
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * upper/lower bottleneck */
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Find the bottlenecks by linear interpolation,
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * step is (45000 - 38000)/6.0 we use the inverse of it. */
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const double stepSizeInv = 8.5714286e-4;
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    idxD = (inRateBitPerSec - 38000) * stepSizeInv;
126fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    idx = (idxD >= 6) ? 6 : ((int16_t)idxD);
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    idxErr = idxD - idx;
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *rateLBBitPerSec = kLowerBandBitRate12[idx];
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *rateUBBitPerSec = kUpperBandBitRate12[idx];
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (idx < 6) {
132fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *rateLBBitPerSec += (int16_t)(
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          idxErr * (kLowerBandBitRate12[idx + 1] - kLowerBandBitRate12[idx]));
134fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *rateUBBitPerSec += (int16_t)(
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          idxErr * (kUpperBandBitRate12[idx + 1] - kUpperBandBitRate12[idx]));
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *bandwidthKHz = isac12kHz;
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if ((inRateBitPerSec >= 50000) && (inRateBitPerSec <= 56000)) {
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* A bottleneck between 50 and 56 kbps corresponds to bandwidth
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * of 16 kHz. Using xxxBandBitRate16[] to calculates
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * upper/lower bottleneck. */
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Find the bottlenecks by linear interpolation
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * step is (56000 - 50000)/5 we use the inverse of it. */
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const double stepSizeInv = 8.3333333e-4;
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    idxD = (inRateBitPerSec - 50000) * stepSizeInv;
147fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    idx = (idxD >= 5) ? 5 : ((int16_t)idxD);
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    idxErr = idxD - idx;
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *rateLBBitPerSec = kLowerBandBitRate16[idx];
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *rateUBBitPerSec  = kUpperBandBitRate16[idx];
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (idx < 5) {
153fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *rateLBBitPerSec += (int16_t)(idxErr *
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          (kLowerBandBitRate16[idx + 1] -
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org              kLowerBandBitRate16[idx]));
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
157fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      *rateUBBitPerSec += (int16_t)(idxErr *
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          (kUpperBandBitRate16[idx + 1] -
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org              kUpperBandBitRate16[idx]));
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *bandwidthKHz = isac16kHz;
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Out-of-range botlteneck value. */
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* limit the values. */
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *rateLBBitPerSec = (*rateLBBitPerSec > 32000) ? 32000 : *rateLBBitPerSec;
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *rateUBBitPerSec = (*rateUBBitPerSec > 32000) ? 32000 : *rateUBBitPerSec;
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid WebRtcIsac_ResetBitstream(Bitstr* bit_stream) {
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bit_stream->W_upper = 0xFFFFFFFF;
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bit_stream->stream_index = 0;
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bit_stream->streamval = 0;
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_EncodeLb(float* in, ISACLBEncStruct* ISACencLB_obj,
181fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t codingMode,
182fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                        int16_t bottleneckIndex) {
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int stream_length = 0;
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int iterCntr;
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lofilt_coef[(ORDERLO + 1)*SUBFRAMES];
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double hifilt_coef[(ORDERHI + 1)*SUBFRAMES];
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float LP[FRAMESAMPLES_HALF];
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float HP[FRAMESAMPLES_HALF];
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double LP_lookahead[FRAMESAMPLES_HALF];
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double HP_lookahead[FRAMESAMPLES_HALF];
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double LP_lookahead_pf[FRAMESAMPLES_HALF + QLOOKAHEAD];
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double LPw[FRAMESAMPLES_HALF];
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double HPw[FRAMESAMPLES_HALF];
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double LPw_pf[FRAMESAMPLES_HALF];
200fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t fre[FRAMESAMPLES_HALF];   /* Q7 */
201fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t fim[FRAMESAMPLES_HALF];   /* Q7 */
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double PitchLags[4];
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double PitchGains[4];
205fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t PitchGains_Q12[4];
206fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t AvgPitchGain_Q12;
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int frame_mode; /* 0 for 30ms, 1 for 60ms */
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int my_index;
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcode_obj transcodingParam;
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double bytesLeftSpecCoding;
213fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint16_t payloadLimitBytes;
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Copy new frame-length and bottleneck rate only for the first 10 ms data */
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (ISACencLB_obj->buffer_index == 0) {
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Set the framelength for the next packet. */
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->current_framesamples = ISACencLB_obj->new_framelength;
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* 'frame_mode' is 0 (30 ms) or 1 (60 ms). */
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_mode = ISACencLB_obj->current_framesamples / MAX_FRAMESAMPLES;
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* buffer speech samples (by 10ms packet) until the frame-length */
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* is reached (30 or 60 ms).                                     */
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /*****************************************************************/
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* fill the buffer with 10ms input data */
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES_10ms; k++) {
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->data_buffer_float[k + ISACencLB_obj->buffer_index] = in[k];
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If buffersize is not equal to current framesize then increase index
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * and return. We do no encoding untill we have enough audio.  */
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (ISACencLB_obj->buffer_index + FRAMESAMPLES_10ms != FRAMESAMPLES) {
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->buffer_index += FRAMESAMPLES_10ms;
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If buffer reached the right size, reset index and continue with
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * encoding the frame. */
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ISACencLB_obj->buffer_index = 0;
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* End of buffer function. */
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /**************************/
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encoding */
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /************/
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) {
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* This is to avoid Linux warnings until we change 'int' to 'Word32'
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * at all places. */
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int intVar;
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* reset bitstream */
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_ResetBitstream(&(ISACencLB_obj->bitstr_obj));
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((codingMode == 0) && (frame_mode == 0) &&
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        (ISACencLB_obj->enforceFrameSize == 0)) {
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencLB_obj->new_framelength = WebRtcIsac_GetNewFrameLength(
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->s2nr = WebRtcIsac_GetSnr(
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Encode frame length. */
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    status = WebRtcIsac_EncodeFrameLen(
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencLB_obj->current_framesamples, &ISACencLB_obj->bitstr_obj);
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (status < 0) {
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Wrong frame size. */
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return status;
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save framelength for multiple packets memory. */
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->SaveEnc_obj.framelength =
273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencLB_obj->current_framesamples;
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* To be used for Redundant Coding. */
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->lastBWIdx = bottleneckIndex;
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    intVar = (int)bottleneckIndex;
278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncodeReceiveBw(&intVar, &ISACencLB_obj->bitstr_obj);
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Split signal in two bands. */
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_SplitAndFilterFloat(ISACencLB_obj->data_buffer_float, LP, HP,
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 LP_lookahead, HP_lookahead,
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 &ISACencLB_obj->prefiltbankstr_obj);
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* estimate pitch parameters and pitch-filter lookahead signal */
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_PitchAnalysis(LP_lookahead, LP_lookahead_pf,
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           &ISACencLB_obj->pitchanalysisstr_obj, PitchLags,
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           PitchGains);
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encode in FIX Q12. */
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Convert PitchGain to Fixed point. */
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < PITCH_SUBFRAMES; k++) {
295fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    PitchGains_Q12[k] = (int16_t)(PitchGains[k] * 4096.0);
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Set where to store data in multiple packets memory. */
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0) {
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->SaveEnc_obj.startIdx = 0;
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->SaveEnc_obj.startIdx = 1;
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Quantize & encode pitch parameters. */
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodePitchGain(PitchGains_Q12, &ISACencLB_obj->bitstr_obj,
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             &ISACencLB_obj->SaveEnc_obj);
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodePitchLag(PitchLags, PitchGains_Q12,
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            &ISACencLB_obj->bitstr_obj,
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            &ISACencLB_obj->SaveEnc_obj);
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      PitchGains_Q12[2] + PitchGains_Q12[3]) >> 2;
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find coefficients for perceptual pre-filters. */
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_GetLpcCoefLb(LP_lookahead_pf, HP_lookahead,
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          &ISACencLB_obj->maskfiltstr_obj, ISACencLB_obj->s2nr,
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          PitchGains_Q12, lofilt_coef, hifilt_coef);
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Code LPC model and shape - gains not quantized yet. */
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeLpcLb(lofilt_coef, hifilt_coef, &ISACencLB_obj->bitstr_obj,
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         &ISACencLB_obj->SaveEnc_obj);
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Convert PitchGains back to FLOAT for pitchfilter_pre. */
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < 4; k++) {
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    PitchGains[k] = ((float)PitchGains_Q12[k]) / 4096;
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store the state of arithmetic coder before coding LPC gains. */
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.W_upper = ISACencLB_obj->bitstr_obj.W_upper;
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream_index = ISACencLB_obj->bitstr_obj.stream_index;
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.streamval = ISACencLB_obj->bitstr_obj.streamval;
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[0] =
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index -
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       2];
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[1] =
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index -
338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       1];
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[2] =
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencLB_obj->bitstr_obj.stream[ISACencLB_obj->bitstr_obj.stream_index];
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store LPC Gains before encoding them. */
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Code gains */
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             &ISACencLB_obj->bitstr_obj,
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             &ISACencLB_obj->SaveEnc_obj);
352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Get the correct value for the payload limit and calculate the
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * number of bytes left for coding the spectrum. */
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* It is a 60ms and we are in the first 30ms then the limit at
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * this point should be half of the assigned value. */
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 >> 1;
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if (frame_mode == 0) {
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* It is a 30ms frame */
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Subract 3 because termination process may add 3 bytes. */
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    payloadLimitBytes = ISACencLB_obj->payloadLimitBytes30 - 3;
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* This is the second half of a 60ms frame. */
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Subract 3 because termination process may add 3 bytes. */
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 - 3;
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Perceptual pre-filtering (using normalized lattice filter). */
371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Low-band filtering. */
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_NormLatticeFilterMa(ORDERLO,
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISACencLB_obj->maskfiltstr_obj.PreStateLoF,
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISACencLB_obj->maskfiltstr_obj.PreStateLoG,
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 LP, lofilt_coef, LPw);
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* High-band filtering. */
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_NormLatticeFilterMa(ORDERHI,
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISACencLB_obj->maskfiltstr_obj.PreStateHiF,
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISACencLB_obj->maskfiltstr_obj.PreStateHiG,
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 HP, hifilt_coef, HPw);
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Pitch filter. */
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_PitchfilterPre(LPw, LPw_pf, &ISACencLB_obj->pitchfiltstr_obj,
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            PitchLags, PitchGains);
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Transform */
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_Time2Spec(LPw_pf, HPw, fre, fim, &ISACencLB_obj->fftstr_obj);
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save data for multiple packets memory. */
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ISACencLB_obj->SaveEnc_obj.AvgPitchGain[ISACencLB_obj->SaveEnc_obj.startIdx] =
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      AvgPitchGain_Q12;
394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Quantization and loss-less coding. */
396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              &ISACencLB_obj->bitstr_obj);
398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* There has been an error but it was not too large payload
400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       (we can cure too large payload). */
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* If this is the second 30ms of a 60ms frame reset
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         this such that in the next call encoder starts fresh. */
404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencLB_obj->frame_nb = 0;
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  iterCntr = 0;
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  while ((ISACencLB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    double bytesSpecCoderUsed;
412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    double transcodeScale;
413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* We were not able to limit the payload size */
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        /* This was the first 30ms of a 60ms frame. Although
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           the payload is larger than it should be but we let
419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           the second 30ms be encoded. Maybe together we
420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           won't exceed the limit. */
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencLB_obj->frame_nb = 1;
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return 0;
423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      } else if ((frame_mode == 1) && (ISACencLB_obj->frame_nb == 1)) {
424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencLB_obj->frame_nb = 0;
425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      } else {
430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return status;
431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bytesSpecCoderUsed = STREAM_SIZE_MAX;
436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Being conservative */
437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bytesSpecCoderUsed = ISACencLB_obj->bitstr_obj.stream_index -
440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          transcodingParam.stream_index;
441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* To be safe, we reduce the scale depending on
445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       the number of iterations. */
446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        (double)MAX_PAYLOAD_LIMIT_ITERATION));
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Scale the LPC Gains. */
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < SUBFRAMES; k++) {
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      lofilt_coef[(LPC_LOBAND_ORDER + 1) * k] =
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          transcodingParam.loFiltGain[k] * transcodeScale;
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      hifilt_coef[(LPC_HIBAND_ORDER + 1) * k] =
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          transcodingParam.hiFiltGain[k] * transcodeScale;
455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER + 1) * k];
456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER + 1) * k];
457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Scale DFT coefficients. */
460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < FRAMESAMPLES_HALF; k++) {
461fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      fre[k] = (int16_t)(fre[k] * transcodeScale);
462fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      fim[k] = (int16_t)(fim[k] * transcodeScale);
463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save data for multiple packets memory. */
466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    my_index = ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF;
467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&ISACencLB_obj->SaveEnc_obj.fre[my_index], fre, sizeof(fre));
468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&ISACencLB_obj->SaveEnc_obj.fim[my_index], fim, sizeof(fim));
469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Re-store the state of arithmetic coder before coding LPC gains. */
471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->bitstr_obj.streamval = transcodingParam.streamval;
474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 2] =
475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam.stream[0];
476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 1] =
477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam.stream[1];
478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index] =
479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam.stream[2];
480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Code gains. */
482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef,
483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               &ISACencLB_obj->bitstr_obj,
484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               &ISACencLB_obj->SaveEnc_obj);
485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Update the number of bytes left for encoding the spectrum. */
487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Encode the spectrum. */
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    err = WebRtcIsac_EncodeSpec(fre, fim, AvgPitchGain_Q12, kIsacLowerBand,
491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                &ISACencLB_obj->bitstr_obj);
492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* There has been an error but it was not too large
495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         payload (we can cure too large payload). */
496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        /* If this is the second 30 ms of a 60 ms frame reset
498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           this such that in the next call encoder starts fresh. */
499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencLB_obj->frame_nb = 0;
500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return err;
502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    iterCntr++;
504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If 60 ms frame-size and just processed the first 30 ms, */
507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* go back to main function to buffer the other 30 ms speech frame. */
508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (frame_mode == 1) {
509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (ISACencLB_obj->frame_nb == 0) {
510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencLB_obj->frame_nb = 1;
511b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return 0;
512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (ISACencLB_obj->frame_nb == 1) {
513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencLB_obj->frame_nb = 0;
514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Also update the frame-length for next packet,
515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         in Adaptive mode only. */
516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (codingMode == 0 && (ISACencLB_obj->enforceFrameSize == 0)) {
517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencLB_obj->new_framelength =
518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            WebRtcIsac_GetNewFrameLength(ISACencLB_obj->bottleneck,
519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                         ISACencLB_obj->current_framesamples);
520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencLB_obj->frame_nb = 0;
524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Complete arithmetic coding. */
527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  stream_length = WebRtcIsac_EncTerminate(&ISACencLB_obj->bitstr_obj);
528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return stream_length;
529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstatic int LimitPayloadUb(ISACUBEncStruct* ISACencUB_obj,
534fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          uint16_t payloadLimitBytes,
535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          double bytesLeftSpecCoding,
536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          transcode_obj* transcodingParam,
537fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int16_t* fre, int16_t* fim,
538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          double* lpcGains, enum ISACBand band, int status) {
539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int iterCntr = 0;
541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double bytesSpecCoderUsed;
543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double transcodeScale;
544fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t kAveragePitchGain = 0.0;
545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  do {
547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* We were not able to limit the payload size. */
549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bytesSpecCoderUsed = STREAM_SIZE_MAX;
554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Being conservative. */
555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      bytesSpecCoderUsed = ISACencUB_obj->bitstr_obj.stream_index -
558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          transcodingParam->stream_index;
559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* To be safe, we reduce the scale depending on the
563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       number of iterations. */
564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        (double)MAX_PAYLOAD_LIMIT_ITERATION));
566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Scale the LPC Gains. */
568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (band == kIsacUpperBand16) {
569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Two sets of coefficients if 16 kHz. */
570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (k = 0; k < SUBFRAMES; k++) {
571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam->loFiltGain[k] *= transcodeScale;
572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam->hiFiltGain[k] *= transcodeScale;
573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* One sets of coefficients if 12 kHz. */
576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (k = 0; k < SUBFRAMES; k++) {
577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam->loFiltGain[k] *= transcodeScale;
578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Scale DFT coefficients. */
582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (k = 0; k < FRAMESAMPLES_HALF; k++) {
583fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      fre[k] = (int16_t)(fre[k] * transcodeScale + 0.5);
584fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      fim[k] = (int16_t)(fim[k] * transcodeScale + 0.5);
585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Store FFT coefficients for multiple encoding. */
587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Store the state of arithmetic coder before coding LPC gains */
593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencUB_obj->bitstr_obj.W_upper = transcodingParam->W_upper;
594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencUB_obj->bitstr_obj.stream_index = transcodingParam->stream_index;
595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencUB_obj->bitstr_obj.streamval = transcodingParam->streamval;
596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 2] =
597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam->stream[0];
598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index - 1] =
599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam->stream[1];
600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencUB_obj->bitstr_obj.stream[transcodingParam->stream_index] =
601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        transcodingParam->stream[2];
602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Store the gains for multiple encoding. */
604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           SUBFRAMES * sizeof(double));
606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Entropy Code lpc-gains, indices are stored for a later use.*/
607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncodeLpcGainUb(transcodingParam->loFiltGain,
608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               &ISACencUB_obj->bitstr_obj,
609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* If 16kHz should do one more set. */
612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (band == kIsacUpperBand16) {
613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Store the gains for multiple encoding. */
614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      memcpy(&ISACencUB_obj->SaveEnc_obj.lpcGain[SUBFRAMES],
615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org             &lpcGains[SUBFRAMES], SUBFRAMES * sizeof(double));
616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Entropy Code lpc-gains, indices are stored for a later use.*/
617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_EncodeLpcGainUb(
618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          transcodingParam->hiFiltGain, &ISACencUB_obj->bitstr_obj,
619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Update the number of bytes left for encoding the spectrum. */
623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    bytesLeftSpecCoding = payloadLimitBytes -
624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencUB_obj->bitstr_obj.stream_index;
625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Save the bit-stream object at this point for FEC. */
627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Encode the spectrum. */
631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    status = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain,
632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   band, &ISACencUB_obj->bitstr_obj);
633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((status < 0) && (status != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* There has been an error but it was not too large payload
635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         (we can cure too large payload). */
636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return status;
637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    iterCntr++;
639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } while ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (status == -ISAC_DISALLOWED_BITSTREAM_LENGTH));
641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_EncodeUb16(float* in, ISACUBEncStruct* ISACencUB_obj,
645fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int32_t jitterInfo) {
646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lpcVecs[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double percepFilterParams[(1 + UB_LPC_ORDER) * (SUBFRAMES << 1) +
651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            (1 + UB_LPC_ORDER)];
652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double LP_lookahead[FRAMESAMPLES];
654fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t fre[FRAMESAMPLES_HALF];   /* Q7 */
655fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t fim[FRAMESAMPLES_HALF];   /* Q7 */
656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double varscale[2];
660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double corr[SUBFRAMES << 1][UB_LPC_ORDER + 1];
661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lpcGains[SUBFRAMES << 1];
662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcode_obj transcodingParam;
663fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint16_t payloadLimitBytes;
664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double s2nr;
665fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t kAveragePitchGain = 0.0;
666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int bytesLeftSpecCoding;
667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Buffer speech samples (by 10ms packet) until the frame-length is   */
669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* reached (30 ms).                                                   */
670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /*********************************************************************/
671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* fill the buffer with 10ms input data */
673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         FRAMESAMPLES_10ms * sizeof(float));
675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If buffer size is not equal to current frame-size, and end of file is
677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * not reached yet, we don't do encoding unless we have the whole frame. */
678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* End of buffer function. */
684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /**************************/
685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encoding */
687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /************/
688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Reset bit-stream */
690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encoding of bandwidth information. */
693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsac_EncodeBandwidth(isac16kHz, &ISACencUB_obj->bitstr_obj);
696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(lpcVecs, ISACencUB_obj->lastLPCVec, UB_LPC_ORDER * sizeof(double));
703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < FRAMESAMPLES; k++) {
705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    LP_lookahead[k] = ISACencUB_obj->data_buffer_float[UB_LOOKAHEAD + k];
706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find coefficients for perceptual pre-filters. */
709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          &lpcVecs[UB_LPC_ORDER], corr, varscale, isac16kHz);
711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(ISACencUB_obj->lastLPCVec,
713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         &lpcVecs[(UB16_LPC_VEC_PER_FRAME - 1) * (UB_LPC_ORDER)],
714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         sizeof(double) * UB_LPC_ORDER);
715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Code LPC model and shape - gains not quantized yet. */
717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         percepFilterParams, isac16kHz,
719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         &ISACencUB_obj->SaveEnc_obj);
720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* the first set of lpc parameters are from the last sub-frame of
722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * the previous frame. so we don't care about them. */
723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_GetLpcGain(s2nr, &percepFilterParams[UB_LPC_ORDER + 1],
724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        (SUBFRAMES << 1), lpcGains, corr, varscale);
725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store the state of arithmetic coder before coding LPC gains */
727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[0] =
731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       2];
733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[1] =
734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       1];
736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[2] =
737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store LPC Gains before encoding them. */
740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    transcodingParam.loFiltGain[k] = lpcGains[k];
742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    transcodingParam.hiFiltGain[k] = lpcGains[SUBFRAMES + k];
743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store the gains for multiple encoding. */
746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         (SUBFRAMES << 1) * sizeof(double));
748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeLpcGainUb(
752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      &lpcGains[SUBFRAMES], &ISACencUB_obj->bitstr_obj,
753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Get the correct value for the payload limit and calculate the number of
756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     bytes left for coding the spectrum. It is a 30ms frame
757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     Subract 3 because termination process may add 3 bytes */
758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->numBytesUsed - 3;
760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bytesLeftSpecCoding = payloadLimitBytes -
761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ISACencUB_obj->bitstr_obj.stream_index;
762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < (SUBFRAMES << 1); k++) {
764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    percepFilterParams[k * (UB_LPC_ORDER + 1) + (UB_LPC_ORDER + 1)] =
765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        lpcGains[k];
766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* LPC filtering (using normalized lattice filter), */
769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* first half-frame. */
770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 &ISACencUB_obj->data_buffer_float[0],
774b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 &percepFilterParams[UB_LPC_ORDER + 1],
775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 &LP_lookahead[0]);
776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Second half-frame filtering. */
778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_NormLatticeFilterMa(
779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      UB_LPC_ORDER, ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      &ISACencUB_obj->data_buffer_float[FRAMESAMPLES_HALF],
782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      &percepFilterParams[(UB_LPC_ORDER + 1) + SUBFRAMES * (UB_LPC_ORDER + 1)],
783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      &LP_lookahead[FRAMESAMPLES_HALF]);
784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_Time2Spec(&LP_lookahead[0], &LP_lookahead[FRAMESAMPLES_HALF],
786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       fre, fim, &ISACencUB_obj->fftstr_obj);
787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store FFT coefficients for multiple encoding. */
789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre, sizeof(fre));
790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim, sizeof(fim));
791b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
792b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Prepare the audio buffer for the next packet
793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * move the last 3 ms to the beginning of the buffer. */
794b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(ISACencUB_obj->data_buffer_float,
795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         &ISACencUB_obj->data_buffer_float[FRAMESAMPLES],
796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         LB_TOTAL_DELAY_SAMPLES * sizeof(float));
797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* start writing with 3 ms delay to compensate for the delay
798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * of the lower-band. */
799b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ISACencUB_obj->buffer_index = LB_TOTAL_DELAY_SAMPLES;
800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save the bit-stream object at this point for FEC. */
802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj, &ISACencUB_obj->bitstr_obj,
803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         sizeof(Bitstr));
804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Qantization and lossless coding */
806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Note that there is no pitch-gain for this band so kAveragePitchGain = 0
807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * is passed to the function. In fact, the function ignores the 3rd parameter
808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * for this band. */
809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand16,
810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              &ISACencUB_obj->bitstr_obj);
811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         &transcodingParam, fre, fim, lpcGains,
819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         kIsacUpperBand16, err);
820b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
823b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Complete arithmetic coding. */
825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_EncodeUb12(float* in, ISACUBEncStruct* ISACencUB_obj,
830fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org                          int32_t jitterInfo) {
831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int k;
833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lpcVecs[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double percepFilterParams[(1 + UB_LPC_ORDER) * SUBFRAMES];
837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float LP[FRAMESAMPLES_HALF];
838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  float HP[FRAMESAMPLES_HALF];
839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
840b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double LP_lookahead[FRAMESAMPLES_HALF];
841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double HP_lookahead[FRAMESAMPLES_HALF];
842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double LPw[FRAMESAMPLES_HALF];
843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double HPw[FRAMESAMPLES_HALF];
845fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t fre[FRAMESAMPLES_HALF];   /* Q7 */
846fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t fim[FRAMESAMPLES_HALF];   /* Q7 */
847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status = 0;
849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double varscale[1];
851b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double corr[UB_LPC_GAIN_DIM][UB_LPC_ORDER + 1];
853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lpcGains[SUBFRAMES];
854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcode_obj transcodingParam;
855fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  uint16_t payloadLimitBytes;
856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double s2nr;
857fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t kAveragePitchGain = 0.0;
858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double bytesLeftSpecCoding;
859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Buffer speech samples (by 10ms packet) until the framelength is  */
861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* reached (30 ms).                                                 */
862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /********************************************************************/
863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Fill the buffer with 10ms input data. */
865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(&ISACencUB_obj->data_buffer_float[ISACencUB_obj->buffer_index], in,
866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         FRAMESAMPLES_10ms * sizeof(float));
867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* if buffer-size is not equal to current frame-size then increase the
869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     index and return. We do the encoding when we have enough audio.     */
870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* If buffer reached the right size, reset index and continue
875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     with encoding the frame */
876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ISACencUB_obj->buffer_index = 0;
877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* End of buffer function */
879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /**************************/
880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encoding */
882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /************/
883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Reset bit-stream. */
885b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_ResetBitstream(&(ISACencUB_obj->bitstr_obj));
886b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encoding bandwidth information. */
888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsac_EncodeBandwidth(isac12kHz, &ISACencUB_obj->bitstr_obj);
890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck, FRAMESAMPLES);
895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Split signal in two bands. */
897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_SplitAndFilterFloat(ISACencUB_obj->data_buffer_float, HP, LP,
898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 HP_lookahead, LP_lookahead,
899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 &ISACencUB_obj->prefiltbankstr_obj);
900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Find coefficients for perceptual pre-filters. */
902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          lpcVecs, corr, varscale, isac12kHz);
904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Code LPC model and shape - gains not quantized yet. */
906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         percepFilterParams, isac12kHz,
908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         &ISACencUB_obj->SaveEnc_obj);
909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_GetLpcGain(s2nr, percepFilterParams, SUBFRAMES, lpcGains, corr,
911b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        varscale);
912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store the state of arithmetic coder before coding LPC gains. */
914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[0] =
918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       2];
920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[1] =
921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index -
922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       1];
923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  transcodingParam.stream[2] =
924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->bitstr_obj.stream[ISACencUB_obj->bitstr_obj.stream_index];
925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store LPC Gains before encoding them. */
927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    transcodingParam.loFiltGain[k] = lpcGains[k];
929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store the gains for multiple encoding. */
932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains, SUBFRAMES *
933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         sizeof(double));
934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (k = 0; k < SUBFRAMES; k++) {
939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    percepFilterParams[k * (UB_LPC_ORDER + 1)] = lpcGains[k];
940b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* perceptual pre-filtering (using normalized lattice filter) */
943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* low-band filtering */
944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ISACencUB_obj->maskfiltstr_obj.PreStateLoG, LP,
947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 percepFilterParams, LPw);
948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Get the correct value for the payload limit and calculate the number
950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     of bytes left for coding the spectrum. It is a 30ms frame Subract 3
951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     because termination process may add 3 bytes */
952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->numBytesUsed - 3;
954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bytesLeftSpecCoding = payloadLimitBytes -
955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      ISACencUB_obj->bitstr_obj.stream_index;
956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memset(HPw, 0, sizeof(HPw));
958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
959b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Transform */
960b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_Time2Spec(LPw, HPw, fre, fim, &ISACencUB_obj->fftstr_obj);
961b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
962b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store FFT coefficients for multiple encoding. */
963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(ISACencUB_obj->SaveEnc_obj.realFFT, fre,
964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         sizeof(ISACencUB_obj->SaveEnc_obj.realFFT));
965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         sizeof(ISACencUB_obj->SaveEnc_obj.imagFFT));
967b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
968b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Save the bit-stream object at this point for FEC. */
969b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
970b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
971b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
972b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Quantization and loss-less coding */
973b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* The 4th parameter to this function is pitch-gain, which is only used
974b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * when encoding 0-8 kHz band, and irrelevant in this function, therefore,
975b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   * we insert zero here. */
976b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_EncodeSpec(fre, fim, kAveragePitchGain, kIsacUpperBand12,
977b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              &ISACencUB_obj->bitstr_obj);
978b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
979b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* There has been an error but it was not too large
980b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       payload (we can cure too large payload) */
981b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
982b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
983b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
984b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
985b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
986b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    err = LimitPayloadUb(ISACencUB_obj, payloadLimitBytes, bytesLeftSpecCoding,
987b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         &transcodingParam, fre, fim, lpcGains,
988b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         kIsacUpperBand12, err);
989b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
990b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
991b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
992b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
993b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Complete arithmetic coding. */
994b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
995b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
996b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
997b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
998b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
999b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1000b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1001b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1002b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* This function is used to create a new bit-stream with new BWE.
1003b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   The same data as previously encoded with the function WebRtcIsac_Encoder().
1004b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   The data needed is taken from the structure, where it was stored
1005b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org   when calling the encoder. */
1006b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1007b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_EncodeStoredDataLb(const ISAC_SaveEncData_t* ISACSavedEnc_obj,
1008b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  Bitstr* ISACBitStr_obj, int BWnumber,
1009b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  float scale) {
1010b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int ii;
1011b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int status;
1012b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int BWno = BWnumber;
1013b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1014fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t* WebRtcIsac_kQPitchGainCdf_ptr[1];
1015fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t** cdf;
1016b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1017b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpLPCcoeffs_lo[(ORDERLO + 1)*SUBFRAMES * 2];
1018b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * 2];
1019b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int tmpLPCindex_g[12 * 2];
1020fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t tmp_fre[FRAMESAMPLES], tmp_fim[FRAMESAMPLES];
1021b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const int kModel = 0;
1022b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1023b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Sanity Check - possible values for BWnumber is 0 - 23. */
1024b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((BWnumber < 0) || (BWnumber > 23)) {
1025b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
1026b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1027b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1028b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Reset bit-stream. */
1029b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_ResetBitstream(ISACBitStr_obj);
1030b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1031b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encode frame length */
1032b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsac_EncodeFrameLen(ISACSavedEnc_obj->framelength,
1033b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     ISACBitStr_obj);
1034b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
1035b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Wrong frame size. */
1036b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1037b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1038b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1039b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Transcoding */
1040b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((scale > 0.0) && (scale < 1.0)) {
1041b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Compensate LPC gain. */
1042b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (ii = 0;
1043b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii < ((ORDERLO + 1)* SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
1044b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii++) {
1045b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpLPCcoeffs_lo[ii] = scale *  ISACSavedEnc_obj->LPCcoeffs_lo[ii];
1046b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1047b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (ii = 0;
1048b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii < ((ORDERHI + 1) * SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
1049b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii++) {
1050b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpLPCcoeffs_hi[ii] = scale *  ISACSavedEnc_obj->LPCcoeffs_hi[ii];
1051b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1052b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Scale DFT. */
1053b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (ii = 0;
1054b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
1055b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii++) {
1056fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      tmp_fre[ii] = (int16_t)((scale) * (float)ISACSavedEnc_obj->fre[ii]);
1057fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      tmp_fim[ii] = (int16_t)((scale) * (float)ISACSavedEnc_obj->fim[ii]);
1058b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1059b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1060b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (ii = 0;
1061b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii < (KLT_ORDER_GAIN * (1 + ISACSavedEnc_obj->startIdx));
1062b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii++) {
1063b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmpLPCindex_g[ii] =  ISACSavedEnc_obj->LPCindex_g[ii];
1064b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1065b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (ii = 0;
1066b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
1067b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        ii++) {
1068b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp_fre[ii] = ISACSavedEnc_obj->fre[ii];
1069b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      tmp_fim[ii] = ISACSavedEnc_obj->fim[ii];
1070b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1071b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1072b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1073b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encode bandwidth estimate. */
1074b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeReceiveBw(&BWno, ISACBitStr_obj);
1075b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1076b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Loop over number of 30 msec */
1077b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (ii = 0; ii <= ISACSavedEnc_obj->startIdx; ii++) {
1078b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Encode pitch gains. */
1079b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
1080b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncHistMulti(ISACBitStr_obj,
1081b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            &ISACSavedEnc_obj->pitchGain_index[ii],
1082b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WebRtcIsac_kQPitchGainCdf_ptr, 1);
1083b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1084b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Entropy coding of quantization pitch lags */
1085b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Voicing classification. */
1086b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (ISACSavedEnc_obj->meanGain[ii] < 0.2) {
1087b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
1088b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else if (ISACSavedEnc_obj->meanGain[ii] < 0.4) {
1089b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
1090b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
1091b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
1092b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1093b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncHistMulti(ISACBitStr_obj,
1094b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            &ISACSavedEnc_obj->pitchIndex[PITCH_SUBFRAMES * ii],
1095b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            cdf, PITCH_SUBFRAMES);
1096b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1097b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* LPC */
1098b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Only one model exists. The entropy coding is done only for backward
1099b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     * compatibility. */
1100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncHistMulti(ISACBitStr_obj, &kModel,
1101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WebRtcIsac_kQKltModelCdfPtr, 1);
1102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Entropy coding of quantization indices - LPC shape only. */
1103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncHistMulti(ISACBitStr_obj,
1104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            &ISACSavedEnc_obj->LPCindex_s[KLT_ORDER_SHAPE * ii],
1105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WebRtcIsac_kQKltCdfPtrShape,
1106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            KLT_ORDER_SHAPE);
1107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* If transcoding, get new LPC gain indices */
1109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (scale < 1.0) {
1110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_TranscodeLPCCoef(
1111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &tmpLPCcoeffs_lo[(ORDERLO + 1) * SUBFRAMES * ii],
1112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &tmpLPCcoeffs_hi[(ORDERHI + 1)*SUBFRAMES * ii],
1113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &tmpLPCindex_g[KLT_ORDER_GAIN * ii]);
1114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Entropy coding of quantization indices - LPC gain. */
1117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncHistMulti(ISACBitStr_obj, &tmpLPCindex_g[KLT_ORDER_GAIN * ii],
1118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WebRtcIsac_kQKltCdfPtrGain, KLT_ORDER_GAIN);
1119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Quantization and loss-less coding. */
1121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    status = WebRtcIsac_EncodeSpec(&tmp_fre[ii * FRAMESAMPLES_HALF],
1122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   &tmp_fim[ii * FRAMESAMPLES_HALF],
1123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   ISACSavedEnc_obj->AvgPitchGain[ii],
1124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                   kIsacLowerBand, ISACBitStr_obj);
1125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (status < 0) {
1126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return status;
1127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Complete arithmetic coding. */
1130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return WebRtcIsac_EncTerminate(ISACBitStr_obj);
1131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint WebRtcIsac_EncodeStoredDataUb(
1135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
1136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Bitstr* bitStream,
1137fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    int32_t jitterInfo,
1138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    float scale,
1139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    enum ISACBandwidth bandwidth) {
1140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int n;
1141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err;
1142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  double lpcGain[SUBFRAMES];
1143fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t realFFT[FRAMESAMPLES_HALF];
1144fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t imagFFT[FRAMESAMPLES_HALF];
1145fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const uint16_t** shape_cdf;
1146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int shape_len;
1147fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t kAveragePitchGain = 0.0;
1148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  enum ISACBand band;
1149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Reset bitstream. */
1150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_ResetBitstream(bitStream);
1151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encode jitter index. */
1153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncodeJitterInfo(jitterInfo, bitStream);
1154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  err = WebRtcIsac_EncodeBandwidth(bandwidth, bitStream);
1156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
1157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
1158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Encode LPC-shape. */
1161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (bandwidth == isac12kHz) {
1162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb12;
1163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shape_len = UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME;
1164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    band = kIsacUpperBand12;
1165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shape_cdf = WebRtcIsac_kLpcShapeCdfMatUb16;
1167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    shape_len = UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME;
1168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    band = kIsacUpperBand16;
1169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->indexLPCShape,
1171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          shape_cdf, shape_len);
1172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if ((scale <= 0.0) || (scale >= 1.0)) {
1174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* We only consider scales between zero and one. */
1175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->lpcGainIndex,
1176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
1177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (bandwidth == isac16kHz) {
1178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Store gain indices of the second half. */
1179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_EncHistMulti(bitStream,
1180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              &ISACSavedEnc_obj->lpcGainIndex[SUBFRAMES],
1181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
1182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Store FFT coefficients. */
1184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    err = WebRtcIsac_EncodeSpec(ISACSavedEnc_obj->realFFT,
1185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                ISACSavedEnc_obj->imagFFT, kAveragePitchGain,
1186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                band, bitStream);
1187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Scale LPC gain and FFT coefficients. */
1189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < SUBFRAMES; n++) {
1190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n];
1191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Store LPC gains. */
1193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
1194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (bandwidth == isac16kHz) {
1196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      /* Scale and code the gains of the second half of the frame, if 16kHz. */
1197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (n = 0; n < SUBFRAMES; n++) {
1198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n + SUBFRAMES];
1199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
1200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
1201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (n = 0; n < FRAMESAMPLES_HALF; n++) {
1204fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      realFFT[n] = (int16_t)(scale * (float)ISACSavedEnc_obj->realFFT[n] +
1205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          0.5f);
1206fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org      imagFFT[n] = (int16_t)(scale * (float)ISACSavedEnc_obj->imagFFT[n] +
1207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          0.5f);
1208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
1209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Store FFT coefficients. */
1210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    err = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain,
1211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                band, bitStream);
1212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err < 0) {
1214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Error happened while encoding FFT coefficients. */
1215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
1216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Complete arithmetic coding. */
1219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return WebRtcIsac_EncTerminate(bitStream);
1220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1222fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint16_t WebRtcIsac_GetRedPayloadUb(
1223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const ISACUBSaveEncDataStruct* ISACSavedEncObj,
1224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Bitstr*                        bitStreamObj,
1225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    enum ISACBandwidth             bandwidth) {
1226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int n;
1227fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t status;
1228fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t realFFT[FRAMESAMPLES_HALF];
1229fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  int16_t imagFFT[FRAMESAMPLES_HALF];
1230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  enum ISACBand band;
1231fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org  const int16_t kAveragePitchGain = 0.0;
1232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Store bit-stream object. */
1233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memcpy(bitStreamObj, &ISACSavedEncObj->bitStreamObj, sizeof(Bitstr));
1234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  /* Scale FFT coefficients. */
1236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (n = 0; n < FRAMESAMPLES_HALF; n++) {
1237fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    realFFT[n] = (int16_t)((float)ISACSavedEncObj->realFFT[n] *
1238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        RCU_TRANSCODING_SCALE_UB + 0.5);
1239fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org    imagFFT[n] = (int16_t)((float)ISACSavedEncObj->imagFFT[n] *
1240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        RCU_TRANSCODING_SCALE_UB + 0.5);
1241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  band = (bandwidth == isac12kHz) ? kIsacUpperBand12 : kIsacUpperBand16;
1244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  status = WebRtcIsac_EncodeSpec(realFFT, imagFFT, kAveragePitchGain, band,
1245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 bitStreamObj);
1246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (status < 0) {
1247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return status;
1248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
1249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    /* Terminate entropy coding */
1250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return WebRtcIsac_EncTerminate(bitStreamObj);
1251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
1253