1*49fe348cSAndroid Build Coastguard Worker /******************************************************************************
2*49fe348cSAndroid Build Coastguard Worker *
3*49fe348cSAndroid Build Coastguard Worker * Copyright 2022 Google LLC
4*49fe348cSAndroid Build Coastguard Worker *
5*49fe348cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*49fe348cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*49fe348cSAndroid Build Coastguard Worker * You may obtain a copy of the License at:
8*49fe348cSAndroid Build Coastguard Worker *
9*49fe348cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
10*49fe348cSAndroid Build Coastguard Worker *
11*49fe348cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*49fe348cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*49fe348cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*49fe348cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*49fe348cSAndroid Build Coastguard Worker * limitations under the License.
16*49fe348cSAndroid Build Coastguard Worker *
17*49fe348cSAndroid Build Coastguard Worker ******************************************************************************/
18*49fe348cSAndroid Build Coastguard Worker
19*49fe348cSAndroid Build Coastguard Worker #include "spec.h"
20*49fe348cSAndroid Build Coastguard Worker #include "bits.h"
21*49fe348cSAndroid Build Coastguard Worker #include "tables.h"
22*49fe348cSAndroid Build Coastguard Worker
23*49fe348cSAndroid Build Coastguard Worker
24*49fe348cSAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
25*49fe348cSAndroid Build Coastguard Worker * Global Gain / Quantization
26*49fe348cSAndroid Build Coastguard Worker * -------------------------------------------------------------------------- */
27*49fe348cSAndroid Build Coastguard Worker
28*49fe348cSAndroid Build Coastguard Worker /**
29*49fe348cSAndroid Build Coastguard Worker * Resolve quantized gain index offset
30*49fe348cSAndroid Build Coastguard Worker * sr, nbytes Samplerate and size of the frame
31*49fe348cSAndroid Build Coastguard Worker * return Gain index offset
32*49fe348cSAndroid Build Coastguard Worker */
resolve_gain_offset(enum lc3_srate sr,int nbytes)33*49fe348cSAndroid Build Coastguard Worker static int resolve_gain_offset(enum lc3_srate sr, int nbytes)
34*49fe348cSAndroid Build Coastguard Worker {
35*49fe348cSAndroid Build Coastguard Worker int sr_ind = lc3_hr(sr) ? 4 + (sr - LC3_SRATE_48K_HR) : sr;
36*49fe348cSAndroid Build Coastguard Worker
37*49fe348cSAndroid Build Coastguard Worker int g_off = (nbytes * 8) / (10 * (1 + sr_ind));
38*49fe348cSAndroid Build Coastguard Worker return LC3_MIN(sr >= LC3_SRATE_96K_HR ? 181 : 255,
39*49fe348cSAndroid Build Coastguard Worker 105 + 5*(1 + sr_ind) + LC3_MIN(g_off, 115));
40*49fe348cSAndroid Build Coastguard Worker }
41*49fe348cSAndroid Build Coastguard Worker
42*49fe348cSAndroid Build Coastguard Worker /**
43*49fe348cSAndroid Build Coastguard Worker * Unquantize gain
44*49fe348cSAndroid Build Coastguard Worker * g_int Quantization gain value
45*49fe348cSAndroid Build Coastguard Worker * return Unquantized gain value
46*49fe348cSAndroid Build Coastguard Worker */
unquantize_gain(int g_int)47*49fe348cSAndroid Build Coastguard Worker static float unquantize_gain(int g_int)
48*49fe348cSAndroid Build Coastguard Worker {
49*49fe348cSAndroid Build Coastguard Worker /* Unquantization gain table :
50*49fe348cSAndroid Build Coastguard Worker * G[i] = 10 ^ (i / 28) , i = [0..27] */
51*49fe348cSAndroid Build Coastguard Worker
52*49fe348cSAndroid Build Coastguard Worker static const float iq_table[] = {
53*49fe348cSAndroid Build Coastguard Worker 1.00000000e+00, 1.08571112e+00, 1.17876863e+00, 1.27980221e+00,
54*49fe348cSAndroid Build Coastguard Worker 1.38949549e+00, 1.50859071e+00, 1.63789371e+00, 1.77827941e+00,
55*49fe348cSAndroid Build Coastguard Worker 1.93069773e+00, 2.09617999e+00, 2.27584593e+00, 2.47091123e+00,
56*49fe348cSAndroid Build Coastguard Worker 2.68269580e+00, 2.91263265e+00, 3.16227766e+00, 3.43332002e+00,
57*49fe348cSAndroid Build Coastguard Worker 3.72759372e+00, 4.04708995e+00, 4.39397056e+00, 4.77058270e+00,
58*49fe348cSAndroid Build Coastguard Worker 5.17947468e+00, 5.62341325e+00, 6.10540230e+00, 6.62870316e+00,
59*49fe348cSAndroid Build Coastguard Worker 7.19685673e+00, 7.81370738e+00, 8.48342898e+00, 9.21055318e+00
60*49fe348cSAndroid Build Coastguard Worker };
61*49fe348cSAndroid Build Coastguard Worker
62*49fe348cSAndroid Build Coastguard Worker float g = 1.f;
63*49fe348cSAndroid Build Coastguard Worker
64*49fe348cSAndroid Build Coastguard Worker for ( ; g_int < 0; g_int += 28, g *= 0.1f);
65*49fe348cSAndroid Build Coastguard Worker for ( ; g_int >= 28; g_int -= 28, g *= 10.f);
66*49fe348cSAndroid Build Coastguard Worker
67*49fe348cSAndroid Build Coastguard Worker return g * iq_table[g_int];
68*49fe348cSAndroid Build Coastguard Worker }
69*49fe348cSAndroid Build Coastguard Worker
70*49fe348cSAndroid Build Coastguard Worker /**
71*49fe348cSAndroid Build Coastguard Worker * Global Gain Estimation
72*49fe348cSAndroid Build Coastguard Worker * dt, sr Duration and samplerate of the frame
73*49fe348cSAndroid Build Coastguard Worker * x Spectral coefficients
74*49fe348cSAndroid Build Coastguard Worker * nbytes Size of the frame
75*49fe348cSAndroid Build Coastguard Worker * nbits_budget Number of bits available coding the spectrum
76*49fe348cSAndroid Build Coastguard Worker * nbits_off Offset on the available bits, temporarily smoothed
77*49fe348cSAndroid Build Coastguard Worker * g_off Gain index offset
78*49fe348cSAndroid Build Coastguard Worker * reset_off Return True when the nbits_off must be reset
79*49fe348cSAndroid Build Coastguard Worker * g_min Return lower bound of quantized gain value
80*49fe348cSAndroid Build Coastguard Worker * return The quantized gain value
81*49fe348cSAndroid Build Coastguard Worker */
estimate_gain(enum lc3_dt dt,enum lc3_srate sr,const float * x,int nbytes,int nbits_budget,float nbits_off,int g_off,bool * reset_off,int * g_min)82*49fe348cSAndroid Build Coastguard Worker LC3_HOT static int estimate_gain(
83*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, const float *x,
84*49fe348cSAndroid Build Coastguard Worker int nbytes, int nbits_budget, float nbits_off, int g_off,
85*49fe348cSAndroid Build Coastguard Worker bool *reset_off, int *g_min)
86*49fe348cSAndroid Build Coastguard Worker {
87*49fe348cSAndroid Build Coastguard Worker int n4 = lc3_ne(dt, sr) / 4;
88*49fe348cSAndroid Build Coastguard Worker union { float f; int32_t q16; } e[LC3_MAX_NE / 4];
89*49fe348cSAndroid Build Coastguard Worker
90*49fe348cSAndroid Build Coastguard Worker /* --- Signal adaptative noise floor --- */
91*49fe348cSAndroid Build Coastguard Worker
92*49fe348cSAndroid Build Coastguard Worker int reg_bits = 0;
93*49fe348cSAndroid Build Coastguard Worker float low_bits = 0;
94*49fe348cSAndroid Build Coastguard Worker
95*49fe348cSAndroid Build Coastguard Worker if (lc3_hr(sr)) {
96*49fe348cSAndroid Build Coastguard Worker int reg_c = (const int [LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_48K_HR]){
97*49fe348cSAndroid Build Coastguard Worker [LC3_DT_2M5] = { -6, -6 },
98*49fe348cSAndroid Build Coastguard Worker [LC3_DT_5M ] = { 0, 0 },
99*49fe348cSAndroid Build Coastguard Worker [LC3_DT_10M] = { 2, 5 }
100*49fe348cSAndroid Build Coastguard Worker }[dt][sr - LC3_SRATE_48K_HR];
101*49fe348cSAndroid Build Coastguard Worker
102*49fe348cSAndroid Build Coastguard Worker reg_bits = (8*nbytes * 4) / (125 * (1 + dt));
103*49fe348cSAndroid Build Coastguard Worker reg_bits = LC3_CLIP(reg_bits + reg_c, 6, 23);
104*49fe348cSAndroid Build Coastguard Worker
105*49fe348cSAndroid Build Coastguard Worker float m0 = 1e-5f, m1 = 1e-5f, k = 0;
106*49fe348cSAndroid Build Coastguard Worker
107*49fe348cSAndroid Build Coastguard Worker for (int i = 0; i < n4; i++) {
108*49fe348cSAndroid Build Coastguard Worker m0 += fabsf(x[4*i + 0]), m1 += fabsf(x[4*i + 0]) * k++;
109*49fe348cSAndroid Build Coastguard Worker m0 += fabsf(x[4*i + 1]), m1 += fabsf(x[4*i + 1]) * k++;
110*49fe348cSAndroid Build Coastguard Worker m0 += fabsf(x[4*i + 2]), m1 += fabsf(x[4*i + 2]) * k++;
111*49fe348cSAndroid Build Coastguard Worker m0 += fabsf(x[4*i + 3]), m1 += fabsf(x[4*i + 3]) * k++;
112*49fe348cSAndroid Build Coastguard Worker }
113*49fe348cSAndroid Build Coastguard Worker
114*49fe348cSAndroid Build Coastguard Worker int m = roundf((1.6f * m0) / ((1 + dt) * m1));
115*49fe348cSAndroid Build Coastguard Worker low_bits = 8 - LC3_MIN(m, 8);
116*49fe348cSAndroid Build Coastguard Worker }
117*49fe348cSAndroid Build Coastguard Worker
118*49fe348cSAndroid Build Coastguard Worker /* --- Energy (dB) by 4 MDCT blocks --- */
119*49fe348cSAndroid Build Coastguard Worker
120*49fe348cSAndroid Build Coastguard Worker float x2_max = 0;
121*49fe348cSAndroid Build Coastguard Worker
122*49fe348cSAndroid Build Coastguard Worker for (int i = 0; i < n4; i++) {
123*49fe348cSAndroid Build Coastguard Worker float x0 = x[4*i + 0] * x[4*i + 0];
124*49fe348cSAndroid Build Coastguard Worker float x1 = x[4*i + 1] * x[4*i + 1];
125*49fe348cSAndroid Build Coastguard Worker float x2 = x[4*i + 2] * x[4*i + 2];
126*49fe348cSAndroid Build Coastguard Worker float x3 = x[4*i + 3] * x[4*i + 3];
127*49fe348cSAndroid Build Coastguard Worker
128*49fe348cSAndroid Build Coastguard Worker x2_max = fmaxf(x2_max, x0);
129*49fe348cSAndroid Build Coastguard Worker x2_max = fmaxf(x2_max, x1);
130*49fe348cSAndroid Build Coastguard Worker x2_max = fmaxf(x2_max, x2);
131*49fe348cSAndroid Build Coastguard Worker x2_max = fmaxf(x2_max, x3);
132*49fe348cSAndroid Build Coastguard Worker
133*49fe348cSAndroid Build Coastguard Worker e[i].f = x0 + x1 + x2 + x3;
134*49fe348cSAndroid Build Coastguard Worker }
135*49fe348cSAndroid Build Coastguard Worker
136*49fe348cSAndroid Build Coastguard Worker float x_max = sqrtf(x2_max);
137*49fe348cSAndroid Build Coastguard Worker float nf = lc3_hr(sr) ?
138*49fe348cSAndroid Build Coastguard Worker lc3_ldexpf(x_max, -reg_bits) * lc3_exp2f(-low_bits) : 0;
139*49fe348cSAndroid Build Coastguard Worker
140*49fe348cSAndroid Build Coastguard Worker for (int i = 0; i < n4; i++)
141*49fe348cSAndroid Build Coastguard Worker e[i].q16 = lc3_db_q16(fmaxf(e[i].f + nf, 1e-10f));
142*49fe348cSAndroid Build Coastguard Worker
143*49fe348cSAndroid Build Coastguard Worker /* --- Determine gain index --- */
144*49fe348cSAndroid Build Coastguard Worker
145*49fe348cSAndroid Build Coastguard Worker int nbits = nbits_budget + nbits_off + 0.5f;
146*49fe348cSAndroid Build Coastguard Worker int g_int = 255 - g_off;
147*49fe348cSAndroid Build Coastguard Worker
148*49fe348cSAndroid Build Coastguard Worker const int k_20_28 = 20.f/28 * 0x1p16f + 0.5f;
149*49fe348cSAndroid Build Coastguard Worker const int k_2u7 = 2.7f * 0x1p16f + 0.5f;
150*49fe348cSAndroid Build Coastguard Worker const int k_1u4 = 1.4f * 0x1p16f + 0.5f;
151*49fe348cSAndroid Build Coastguard Worker
152*49fe348cSAndroid Build Coastguard Worker for (int i = 128, j, j0 = n4-1, j1 ; i > 0; i >>= 1) {
153*49fe348cSAndroid Build Coastguard Worker int gn = (g_int - i) * k_20_28;
154*49fe348cSAndroid Build Coastguard Worker int v = 0;
155*49fe348cSAndroid Build Coastguard Worker
156*49fe348cSAndroid Build Coastguard Worker for (j = j0; j >= 0 && e[j].q16 < gn; j--);
157*49fe348cSAndroid Build Coastguard Worker
158*49fe348cSAndroid Build Coastguard Worker for (j1 = j; j >= 0; j--) {
159*49fe348cSAndroid Build Coastguard Worker int e_diff = e[j].q16 - gn;
160*49fe348cSAndroid Build Coastguard Worker
161*49fe348cSAndroid Build Coastguard Worker v += e_diff < 0 ? k_2u7 :
162*49fe348cSAndroid Build Coastguard Worker e_diff < 43 << 16 ? e_diff + ( 7 << 16)
163*49fe348cSAndroid Build Coastguard Worker : 2*e_diff - (36 << 16);
164*49fe348cSAndroid Build Coastguard Worker }
165*49fe348cSAndroid Build Coastguard Worker
166*49fe348cSAndroid Build Coastguard Worker if (v > nbits * k_1u4)
167*49fe348cSAndroid Build Coastguard Worker j0 = j1;
168*49fe348cSAndroid Build Coastguard Worker else
169*49fe348cSAndroid Build Coastguard Worker g_int = g_int - i;
170*49fe348cSAndroid Build Coastguard Worker }
171*49fe348cSAndroid Build Coastguard Worker
172*49fe348cSAndroid Build Coastguard Worker /* --- Limit gain index --- */
173*49fe348cSAndroid Build Coastguard Worker
174*49fe348cSAndroid Build Coastguard Worker float x_lim = lc3_hr(sr) ? 0x7fffp8f : 0x7fffp0f;
175*49fe348cSAndroid Build Coastguard Worker
176*49fe348cSAndroid Build Coastguard Worker *g_min = 255 - g_off;
177*49fe348cSAndroid Build Coastguard Worker for (int i = 128 ; i > 0; i >>= 1)
178*49fe348cSAndroid Build Coastguard Worker if (x_lim * unquantize_gain(*g_min - i) > x_max)
179*49fe348cSAndroid Build Coastguard Worker *g_min -= i;
180*49fe348cSAndroid Build Coastguard Worker
181*49fe348cSAndroid Build Coastguard Worker *reset_off = g_int < *g_min || x_max == 0;
182*49fe348cSAndroid Build Coastguard Worker if (*reset_off)
183*49fe348cSAndroid Build Coastguard Worker g_int = *g_min;
184*49fe348cSAndroid Build Coastguard Worker
185*49fe348cSAndroid Build Coastguard Worker return g_int;
186*49fe348cSAndroid Build Coastguard Worker }
187*49fe348cSAndroid Build Coastguard Worker
188*49fe348cSAndroid Build Coastguard Worker /**
189*49fe348cSAndroid Build Coastguard Worker * Global Gain Adjustment
190*49fe348cSAndroid Build Coastguard Worker * dt, sr Duration and samplerate of the frame
191*49fe348cSAndroid Build Coastguard Worker * g_idx The estimated quantized gain index
192*49fe348cSAndroid Build Coastguard Worker * nbits Computed number of bits coding the spectrum
193*49fe348cSAndroid Build Coastguard Worker * nbits_budget Number of bits available for coding the spectrum
194*49fe348cSAndroid Build Coastguard Worker * g_idx_min Minimum gain index value
195*49fe348cSAndroid Build Coastguard Worker * return Gain adjust value (-1 to 2)
196*49fe348cSAndroid Build Coastguard Worker */
adjust_gain(enum lc3_dt dt,enum lc3_srate sr,int g_idx,int nbits,int nbits_budget,int g_idx_min)197*49fe348cSAndroid Build Coastguard Worker LC3_HOT static int adjust_gain(
198*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr,
199*49fe348cSAndroid Build Coastguard Worker int g_idx, int nbits, int nbits_budget, int g_idx_min)
200*49fe348cSAndroid Build Coastguard Worker {
201*49fe348cSAndroid Build Coastguard Worker /* --- Compute delta threshold --- */
202*49fe348cSAndroid Build Coastguard Worker
203*49fe348cSAndroid Build Coastguard Worker const int *t = (const int [LC3_NUM_SRATE][3]){
204*49fe348cSAndroid Build Coastguard Worker { 80, 500, 850 }, { 230, 1025, 1700 }, { 380, 1550, 2550 },
205*49fe348cSAndroid Build Coastguard Worker { 530, 2075, 3400 }, { 680, 2600, 4250 },
206*49fe348cSAndroid Build Coastguard Worker { 680, 2600, 4250 }, { 830, 3125, 5100 }
207*49fe348cSAndroid Build Coastguard Worker }[sr];
208*49fe348cSAndroid Build Coastguard Worker
209*49fe348cSAndroid Build Coastguard Worker int delta, den = 48;
210*49fe348cSAndroid Build Coastguard Worker
211*49fe348cSAndroid Build Coastguard Worker if (nbits < t[0]) {
212*49fe348cSAndroid Build Coastguard Worker delta = 3*(nbits + 48);
213*49fe348cSAndroid Build Coastguard Worker
214*49fe348cSAndroid Build Coastguard Worker } else if (nbits < t[1]) {
215*49fe348cSAndroid Build Coastguard Worker int n0 = 3*(t[0] + 48), range = t[1] - t[0];
216*49fe348cSAndroid Build Coastguard Worker delta = n0 * range + (nbits - t[0]) * (t[1] - n0);
217*49fe348cSAndroid Build Coastguard Worker den *= range;
218*49fe348cSAndroid Build Coastguard Worker
219*49fe348cSAndroid Build Coastguard Worker } else {
220*49fe348cSAndroid Build Coastguard Worker delta = LC3_MIN(nbits, t[2]);
221*49fe348cSAndroid Build Coastguard Worker }
222*49fe348cSAndroid Build Coastguard Worker
223*49fe348cSAndroid Build Coastguard Worker delta = (delta + den/2) / den;
224*49fe348cSAndroid Build Coastguard Worker
225*49fe348cSAndroid Build Coastguard Worker /* --- Adjust gain --- */
226*49fe348cSAndroid Build Coastguard Worker
227*49fe348cSAndroid Build Coastguard Worker if (lc3_hr(sr) && nbits > nbits_budget) {
228*49fe348cSAndroid Build Coastguard Worker int factor = 1 + (dt <= LC3_DT_5M) +
229*49fe348cSAndroid Build Coastguard Worker (dt <= LC3_DT_2M5) * (1 + (nbits >= 520));
230*49fe348cSAndroid Build Coastguard Worker
231*49fe348cSAndroid Build Coastguard Worker int g_incr = factor + (factor * (nbits - nbits_budget)) / delta;
232*49fe348cSAndroid Build Coastguard Worker return LC3_MIN(g_idx + g_incr, 255) - g_idx;
233*49fe348cSAndroid Build Coastguard Worker }
234*49fe348cSAndroid Build Coastguard Worker
235*49fe348cSAndroid Build Coastguard Worker if (!lc3_hr(sr) && nbits < nbits_budget - (delta + 2))
236*49fe348cSAndroid Build Coastguard Worker return -(g_idx > g_idx_min);
237*49fe348cSAndroid Build Coastguard Worker
238*49fe348cSAndroid Build Coastguard Worker if (!lc3_hr(sr) && nbits > nbits_budget)
239*49fe348cSAndroid Build Coastguard Worker return (g_idx < 255) + (g_idx < 254 && nbits >= nbits_budget + delta);
240*49fe348cSAndroid Build Coastguard Worker
241*49fe348cSAndroid Build Coastguard Worker return 0;
242*49fe348cSAndroid Build Coastguard Worker }
243*49fe348cSAndroid Build Coastguard Worker
244*49fe348cSAndroid Build Coastguard Worker /**
245*49fe348cSAndroid Build Coastguard Worker * Spectrum quantization
246*49fe348cSAndroid Build Coastguard Worker * dt, sr Duration and samplerate of the frame
247*49fe348cSAndroid Build Coastguard Worker * g_int Quantization gain value
248*49fe348cSAndroid Build Coastguard Worker * x Spectral coefficients, scaled as output
249*49fe348cSAndroid Build Coastguard Worker * n Return count of significants
250*49fe348cSAndroid Build Coastguard Worker */
quantize(enum lc3_dt dt,enum lc3_srate sr,int g_int,float * x,int * n)251*49fe348cSAndroid Build Coastguard Worker LC3_HOT static void quantize(
252*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, int g_int, float *x, int *n)
253*49fe348cSAndroid Build Coastguard Worker {
254*49fe348cSAndroid Build Coastguard Worker float g_inv = unquantize_gain(-g_int);
255*49fe348cSAndroid Build Coastguard Worker int ne = lc3_ne(dt, sr);
256*49fe348cSAndroid Build Coastguard Worker
257*49fe348cSAndroid Build Coastguard Worker *n = ne;
258*49fe348cSAndroid Build Coastguard Worker
259*49fe348cSAndroid Build Coastguard Worker for (int i = 0; i < ne; i += 2) {
260*49fe348cSAndroid Build Coastguard Worker float xq_min = lc3_hr(sr) ? 0.5f : 10.f/16;
261*49fe348cSAndroid Build Coastguard Worker
262*49fe348cSAndroid Build Coastguard Worker x[i+0] *= g_inv;
263*49fe348cSAndroid Build Coastguard Worker x[i+1] *= g_inv;
264*49fe348cSAndroid Build Coastguard Worker
265*49fe348cSAndroid Build Coastguard Worker *n = fabsf(x[i+0]) >= xq_min ||
266*49fe348cSAndroid Build Coastguard Worker fabsf(x[i+1]) >= xq_min ? ne : *n - 2;
267*49fe348cSAndroid Build Coastguard Worker }
268*49fe348cSAndroid Build Coastguard Worker }
269*49fe348cSAndroid Build Coastguard Worker
270*49fe348cSAndroid Build Coastguard Worker /**
271*49fe348cSAndroid Build Coastguard Worker * Spectrum quantization inverse
272*49fe348cSAndroid Build Coastguard Worker * dt, sr Duration and samplerate of the frame
273*49fe348cSAndroid Build Coastguard Worker * g_int Quantization gain value
274*49fe348cSAndroid Build Coastguard Worker * x, nq Spectral quantized, and count of significants
275*49fe348cSAndroid Build Coastguard Worker * return Unquantized gain value
276*49fe348cSAndroid Build Coastguard Worker */
unquantize(enum lc3_dt dt,enum lc3_srate sr,int g_int,float * x,int nq)277*49fe348cSAndroid Build Coastguard Worker LC3_HOT static float unquantize(
278*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr,
279*49fe348cSAndroid Build Coastguard Worker int g_int, float *x, int nq)
280*49fe348cSAndroid Build Coastguard Worker {
281*49fe348cSAndroid Build Coastguard Worker float g = unquantize_gain(g_int);
282*49fe348cSAndroid Build Coastguard Worker int i, ne = lc3_ne(dt, sr);
283*49fe348cSAndroid Build Coastguard Worker
284*49fe348cSAndroid Build Coastguard Worker for (i = 0; i < nq; i++)
285*49fe348cSAndroid Build Coastguard Worker x[i] = x[i] * g;
286*49fe348cSAndroid Build Coastguard Worker
287*49fe348cSAndroid Build Coastguard Worker for ( ; i < ne; i++)
288*49fe348cSAndroid Build Coastguard Worker x[i] = 0;
289*49fe348cSAndroid Build Coastguard Worker
290*49fe348cSAndroid Build Coastguard Worker return g;
291*49fe348cSAndroid Build Coastguard Worker }
292*49fe348cSAndroid Build Coastguard Worker
293*49fe348cSAndroid Build Coastguard Worker
294*49fe348cSAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
295*49fe348cSAndroid Build Coastguard Worker * Spectrum coding
296*49fe348cSAndroid Build Coastguard Worker * -------------------------------------------------------------------------- */
297*49fe348cSAndroid Build Coastguard Worker
298*49fe348cSAndroid Build Coastguard Worker /**
299*49fe348cSAndroid Build Coastguard Worker * Resolve High-bitrate and LSB modes according size of the frame
300*49fe348cSAndroid Build Coastguard Worker * sr, nbytes Samplerate and size of the frame
301*49fe348cSAndroid Build Coastguard Worker * p_lsb_mode True when LSB mode allowed, when not NULL
302*49fe348cSAndroid Build Coastguard Worker * return True when High-Rate mode enabled
303*49fe348cSAndroid Build Coastguard Worker */
resolve_modes(enum lc3_srate sr,int nbytes,bool * p_lsb_mode)304*49fe348cSAndroid Build Coastguard Worker static bool resolve_modes(enum lc3_srate sr, int nbytes, bool *p_lsb_mode)
305*49fe348cSAndroid Build Coastguard Worker {
306*49fe348cSAndroid Build Coastguard Worker int sr_ind = lc3_hr(sr) ? 4 + (sr - LC3_SRATE_48K_HR) : sr;
307*49fe348cSAndroid Build Coastguard Worker
308*49fe348cSAndroid Build Coastguard Worker if (p_lsb_mode)
309*49fe348cSAndroid Build Coastguard Worker *p_lsb_mode = (nbytes >= 20 * (3 + sr_ind)) && (sr < LC3_SRATE_96K_HR);
310*49fe348cSAndroid Build Coastguard Worker
311*49fe348cSAndroid Build Coastguard Worker return (nbytes > 20 * (1 + sr_ind)) && (sr < LC3_SRATE_96K_HR);
312*49fe348cSAndroid Build Coastguard Worker }
313*49fe348cSAndroid Build Coastguard Worker
314*49fe348cSAndroid Build Coastguard Worker /**
315*49fe348cSAndroid Build Coastguard Worker * Bit consumption
316*49fe348cSAndroid Build Coastguard Worker * dt, sr, nbytes Duration, samplerate and size of the frame
317*49fe348cSAndroid Build Coastguard Worker * x Spectral quantized coefficients
318*49fe348cSAndroid Build Coastguard Worker * n Count of significant coefficients, updated on truncation
319*49fe348cSAndroid Build Coastguard Worker * nbits_budget Truncate to stay in budget, when not zero
320*49fe348cSAndroid Build Coastguard Worker * p_lsb_mode Return True when LSB's are not AC coded, or NULL
321*49fe348cSAndroid Build Coastguard Worker * return The number of bits coding the spectrum
322*49fe348cSAndroid Build Coastguard Worker */
compute_nbits(enum lc3_dt dt,enum lc3_srate sr,int nbytes,const float * x,int * n,int nbits_budget,bool * p_lsb_mode)323*49fe348cSAndroid Build Coastguard Worker LC3_HOT static int compute_nbits(
324*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, int nbytes,
325*49fe348cSAndroid Build Coastguard Worker const float *x, int *n, int nbits_budget, bool *p_lsb_mode)
326*49fe348cSAndroid Build Coastguard Worker {
327*49fe348cSAndroid Build Coastguard Worker bool lsb_mode, high_rate = resolve_modes(sr, nbytes, &lsb_mode);
328*49fe348cSAndroid Build Coastguard Worker int ne = lc3_ne(dt, sr);
329*49fe348cSAndroid Build Coastguard Worker
330*49fe348cSAndroid Build Coastguard Worker /* --- Loop on quantized coefficients --- */
331*49fe348cSAndroid Build Coastguard Worker
332*49fe348cSAndroid Build Coastguard Worker int nbits = 0, nbits_lsb = 0;
333*49fe348cSAndroid Build Coastguard Worker uint8_t state = 0;
334*49fe348cSAndroid Build Coastguard Worker
335*49fe348cSAndroid Build Coastguard Worker int nbits_end = 0;
336*49fe348cSAndroid Build Coastguard Worker int n_end = 0;
337*49fe348cSAndroid Build Coastguard Worker
338*49fe348cSAndroid Build Coastguard Worker nbits_budget = nbits_budget ? nbits_budget * 2048 : INT_MAX;
339*49fe348cSAndroid Build Coastguard Worker
340*49fe348cSAndroid Build Coastguard Worker for (int i = 0, h = 0; h < 2; h++) {
341*49fe348cSAndroid Build Coastguard Worker const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
342*49fe348cSAndroid Build Coastguard Worker
343*49fe348cSAndroid Build Coastguard Worker for ( ; i < LC3_MIN(*n, (ne + 2) >> (1 - h))
344*49fe348cSAndroid Build Coastguard Worker && nbits <= nbits_budget; i += 2) {
345*49fe348cSAndroid Build Coastguard Worker
346*49fe348cSAndroid Build Coastguard Worker float xq_off = lc3_hr(sr) ? 0.5f : 6.f/16;
347*49fe348cSAndroid Build Coastguard Worker uint32_t a = fabsf(x[i+0]) + xq_off;
348*49fe348cSAndroid Build Coastguard Worker uint32_t b = fabsf(x[i+1]) + xq_off;
349*49fe348cSAndroid Build Coastguard Worker
350*49fe348cSAndroid Build Coastguard Worker const uint8_t *lut = lut_coeff[state];
351*49fe348cSAndroid Build Coastguard Worker
352*49fe348cSAndroid Build Coastguard Worker /* --- Sign values --- */
353*49fe348cSAndroid Build Coastguard Worker
354*49fe348cSAndroid Build Coastguard Worker int s = (a != 0) + (b != 0);
355*49fe348cSAndroid Build Coastguard Worker nbits += s * 2048;
356*49fe348cSAndroid Build Coastguard Worker
357*49fe348cSAndroid Build Coastguard Worker /* --- LSB values Reduce to 2*2 bits MSB values ---
358*49fe348cSAndroid Build Coastguard Worker * Reduce to 2x2 bits MSB values. The LSB's pair are arithmetic
359*49fe348cSAndroid Build Coastguard Worker * coded with an escape code followed by 1 bit for each values.
360*49fe348cSAndroid Build Coastguard Worker * The LSB mode does not arthmetic code the first LSB,
361*49fe348cSAndroid Build Coastguard Worker * add the sign of the LSB when one of pair was at value 1 */
362*49fe348cSAndroid Build Coastguard Worker
363*49fe348cSAndroid Build Coastguard Worker uint32_t m = (a | b) >> 2;
364*49fe348cSAndroid Build Coastguard Worker unsigned k = 0;
365*49fe348cSAndroid Build Coastguard Worker
366*49fe348cSAndroid Build Coastguard Worker if (m) {
367*49fe348cSAndroid Build Coastguard Worker
368*49fe348cSAndroid Build Coastguard Worker if (lsb_mode) {
369*49fe348cSAndroid Build Coastguard Worker nbits += lc3_spectrum_bits[lut[k++]][16] - 2*2048;
370*49fe348cSAndroid Build Coastguard Worker nbits_lsb += 2 + (a == 1) + (b == 1);
371*49fe348cSAndroid Build Coastguard Worker }
372*49fe348cSAndroid Build Coastguard Worker
373*49fe348cSAndroid Build Coastguard Worker for (m >>= lsb_mode; m; m >>= 1, k++)
374*49fe348cSAndroid Build Coastguard Worker nbits += lc3_spectrum_bits[lut[LC3_MIN(k, 3)]][16];
375*49fe348cSAndroid Build Coastguard Worker
376*49fe348cSAndroid Build Coastguard Worker nbits += k * 2*2048;
377*49fe348cSAndroid Build Coastguard Worker a >>= k;
378*49fe348cSAndroid Build Coastguard Worker b >>= k;
379*49fe348cSAndroid Build Coastguard Worker
380*49fe348cSAndroid Build Coastguard Worker k = LC3_MIN(k, 3);
381*49fe348cSAndroid Build Coastguard Worker }
382*49fe348cSAndroid Build Coastguard Worker
383*49fe348cSAndroid Build Coastguard Worker /* --- MSB values --- */
384*49fe348cSAndroid Build Coastguard Worker
385*49fe348cSAndroid Build Coastguard Worker nbits += lc3_spectrum_bits[lut[k]][a + 4*b];
386*49fe348cSAndroid Build Coastguard Worker
387*49fe348cSAndroid Build Coastguard Worker /* --- Update state --- */
388*49fe348cSAndroid Build Coastguard Worker
389*49fe348cSAndroid Build Coastguard Worker if (s && nbits <= nbits_budget) {
390*49fe348cSAndroid Build Coastguard Worker n_end = i + 2;
391*49fe348cSAndroid Build Coastguard Worker nbits_end = nbits;
392*49fe348cSAndroid Build Coastguard Worker }
393*49fe348cSAndroid Build Coastguard Worker
394*49fe348cSAndroid Build Coastguard Worker state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
395*49fe348cSAndroid Build Coastguard Worker }
396*49fe348cSAndroid Build Coastguard Worker }
397*49fe348cSAndroid Build Coastguard Worker
398*49fe348cSAndroid Build Coastguard Worker /* --- Return --- */
399*49fe348cSAndroid Build Coastguard Worker
400*49fe348cSAndroid Build Coastguard Worker *n = n_end;
401*49fe348cSAndroid Build Coastguard Worker
402*49fe348cSAndroid Build Coastguard Worker if (p_lsb_mode)
403*49fe348cSAndroid Build Coastguard Worker *p_lsb_mode = lsb_mode &&
404*49fe348cSAndroid Build Coastguard Worker nbits_end + nbits_lsb * 2048 > nbits_budget;
405*49fe348cSAndroid Build Coastguard Worker
406*49fe348cSAndroid Build Coastguard Worker if (nbits_budget >= INT_MAX)
407*49fe348cSAndroid Build Coastguard Worker nbits_end += nbits_lsb * 2048;
408*49fe348cSAndroid Build Coastguard Worker
409*49fe348cSAndroid Build Coastguard Worker return (nbits_end + 2047) / 2048;
410*49fe348cSAndroid Build Coastguard Worker }
411*49fe348cSAndroid Build Coastguard Worker
412*49fe348cSAndroid Build Coastguard Worker /**
413*49fe348cSAndroid Build Coastguard Worker * Put quantized spectrum
414*49fe348cSAndroid Build Coastguard Worker * bits Bitstream context
415*49fe348cSAndroid Build Coastguard Worker * dt, sr, nbytes Duration, samplerate and size of the frame
416*49fe348cSAndroid Build Coastguard Worker * x Spectral quantized coefficients
417*49fe348cSAndroid Build Coastguard Worker * nq, lsb_mode Count of significants, and LSB discard indication
418*49fe348cSAndroid Build Coastguard Worker */
put_quantized(lc3_bits_t * bits,enum lc3_dt dt,enum lc3_srate sr,int nbytes,const float * x,int nq,bool lsb_mode)419*49fe348cSAndroid Build Coastguard Worker LC3_HOT static void put_quantized(lc3_bits_t *bits,
420*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, int nbytes,
421*49fe348cSAndroid Build Coastguard Worker const float *x, int nq, bool lsb_mode)
422*49fe348cSAndroid Build Coastguard Worker {
423*49fe348cSAndroid Build Coastguard Worker bool high_rate = resolve_modes(sr, nbytes, NULL);
424*49fe348cSAndroid Build Coastguard Worker int ne = lc3_ne(dt, sr);
425*49fe348cSAndroid Build Coastguard Worker
426*49fe348cSAndroid Build Coastguard Worker /* --- Loop on quantized coefficients --- */
427*49fe348cSAndroid Build Coastguard Worker
428*49fe348cSAndroid Build Coastguard Worker uint8_t state = 0;
429*49fe348cSAndroid Build Coastguard Worker
430*49fe348cSAndroid Build Coastguard Worker for (int i = 0, h = 0; h < 2; h++) {
431*49fe348cSAndroid Build Coastguard Worker const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
432*49fe348cSAndroid Build Coastguard Worker
433*49fe348cSAndroid Build Coastguard Worker for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) {
434*49fe348cSAndroid Build Coastguard Worker
435*49fe348cSAndroid Build Coastguard Worker float xq_off = lc3_hr(sr) ? 0.5f : 6.f/16;
436*49fe348cSAndroid Build Coastguard Worker uint32_t a = fabsf(x[i+0]) + xq_off;
437*49fe348cSAndroid Build Coastguard Worker uint32_t b = fabsf(x[i+1]) + xq_off;
438*49fe348cSAndroid Build Coastguard Worker
439*49fe348cSAndroid Build Coastguard Worker const uint8_t *lut = lut_coeff[state];
440*49fe348cSAndroid Build Coastguard Worker
441*49fe348cSAndroid Build Coastguard Worker /* --- LSB values Reduce to 2*2 bits MSB values ---
442*49fe348cSAndroid Build Coastguard Worker * Reduce to 2x2 bits MSB values. The LSB's pair are arithmetic
443*49fe348cSAndroid Build Coastguard Worker * coded with an escape code and 1 bits for each values.
444*49fe348cSAndroid Build Coastguard Worker * The LSB mode discard the first LSB (at this step) */
445*49fe348cSAndroid Build Coastguard Worker
446*49fe348cSAndroid Build Coastguard Worker uint32_t m = (a | b) >> 2;
447*49fe348cSAndroid Build Coastguard Worker unsigned k = 0, shr = 0;
448*49fe348cSAndroid Build Coastguard Worker
449*49fe348cSAndroid Build Coastguard Worker if (m) {
450*49fe348cSAndroid Build Coastguard Worker
451*49fe348cSAndroid Build Coastguard Worker if (lsb_mode)
452*49fe348cSAndroid Build Coastguard Worker lc3_put_symbol(bits,
453*49fe348cSAndroid Build Coastguard Worker lc3_spectrum_models + lut[k++], 16);
454*49fe348cSAndroid Build Coastguard Worker
455*49fe348cSAndroid Build Coastguard Worker for (m >>= lsb_mode; m; m >>= 1, k++) {
456*49fe348cSAndroid Build Coastguard Worker lc3_put_bit(bits, (a >> k) & 1);
457*49fe348cSAndroid Build Coastguard Worker lc3_put_bit(bits, (b >> k) & 1);
458*49fe348cSAndroid Build Coastguard Worker lc3_put_symbol(bits,
459*49fe348cSAndroid Build Coastguard Worker lc3_spectrum_models + lut[LC3_MIN(k, 3)], 16);
460*49fe348cSAndroid Build Coastguard Worker }
461*49fe348cSAndroid Build Coastguard Worker
462*49fe348cSAndroid Build Coastguard Worker a >>= lsb_mode;
463*49fe348cSAndroid Build Coastguard Worker b >>= lsb_mode;
464*49fe348cSAndroid Build Coastguard Worker
465*49fe348cSAndroid Build Coastguard Worker shr = k - lsb_mode;
466*49fe348cSAndroid Build Coastguard Worker k = LC3_MIN(k, 3);
467*49fe348cSAndroid Build Coastguard Worker }
468*49fe348cSAndroid Build Coastguard Worker
469*49fe348cSAndroid Build Coastguard Worker /* --- Sign values --- */
470*49fe348cSAndroid Build Coastguard Worker
471*49fe348cSAndroid Build Coastguard Worker if (a) lc3_put_bit(bits, x[i+0] < 0);
472*49fe348cSAndroid Build Coastguard Worker if (b) lc3_put_bit(bits, x[i+1] < 0);
473*49fe348cSAndroid Build Coastguard Worker
474*49fe348cSAndroid Build Coastguard Worker /* --- MSB values --- */
475*49fe348cSAndroid Build Coastguard Worker
476*49fe348cSAndroid Build Coastguard Worker a >>= shr;
477*49fe348cSAndroid Build Coastguard Worker b >>= shr;
478*49fe348cSAndroid Build Coastguard Worker
479*49fe348cSAndroid Build Coastguard Worker lc3_put_symbol(bits, lc3_spectrum_models + lut[k], a + 4*b);
480*49fe348cSAndroid Build Coastguard Worker
481*49fe348cSAndroid Build Coastguard Worker /* --- Update state --- */
482*49fe348cSAndroid Build Coastguard Worker
483*49fe348cSAndroid Build Coastguard Worker state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
484*49fe348cSAndroid Build Coastguard Worker }
485*49fe348cSAndroid Build Coastguard Worker }
486*49fe348cSAndroid Build Coastguard Worker }
487*49fe348cSAndroid Build Coastguard Worker
488*49fe348cSAndroid Build Coastguard Worker /**
489*49fe348cSAndroid Build Coastguard Worker * Get quantized spectrum
490*49fe348cSAndroid Build Coastguard Worker * bits Bitstream context
491*49fe348cSAndroid Build Coastguard Worker * dt, sr, nbytes Duration, samplerate and size of the frame
492*49fe348cSAndroid Build Coastguard Worker * nq, lsb_mode Count of significants, and LSB discard indication
493*49fe348cSAndroid Build Coastguard Worker * x Return `nq` spectral quantized coefficients
494*49fe348cSAndroid Build Coastguard Worker * nf_seed Return the noise factor seed associated
495*49fe348cSAndroid Build Coastguard Worker * return 0: Ok -1: Invalid bitstream data
496*49fe348cSAndroid Build Coastguard Worker */
get_quantized(lc3_bits_t * bits,enum lc3_dt dt,enum lc3_srate sr,int nbytes,int nq,bool lsb_mode,float * x,uint16_t * nf_seed)497*49fe348cSAndroid Build Coastguard Worker LC3_HOT static int get_quantized(lc3_bits_t *bits,
498*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, int nbytes,
499*49fe348cSAndroid Build Coastguard Worker int nq, bool lsb_mode, float *x, uint16_t *nf_seed)
500*49fe348cSAndroid Build Coastguard Worker {
501*49fe348cSAndroid Build Coastguard Worker bool high_rate = resolve_modes(sr, nbytes, NULL);
502*49fe348cSAndroid Build Coastguard Worker int ne = lc3_ne(dt, sr);
503*49fe348cSAndroid Build Coastguard Worker
504*49fe348cSAndroid Build Coastguard Worker *nf_seed = 0;
505*49fe348cSAndroid Build Coastguard Worker
506*49fe348cSAndroid Build Coastguard Worker /* --- Loop on quantized coefficients --- */
507*49fe348cSAndroid Build Coastguard Worker
508*49fe348cSAndroid Build Coastguard Worker uint8_t state = 0;
509*49fe348cSAndroid Build Coastguard Worker
510*49fe348cSAndroid Build Coastguard Worker for (int i = 0, h = 0; h < 2; h++) {
511*49fe348cSAndroid Build Coastguard Worker const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
512*49fe348cSAndroid Build Coastguard Worker
513*49fe348cSAndroid Build Coastguard Worker for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) {
514*49fe348cSAndroid Build Coastguard Worker
515*49fe348cSAndroid Build Coastguard Worker const uint8_t *lut = lut_coeff[state];
516*49fe348cSAndroid Build Coastguard Worker int max_shl = lc3_hr(sr) ? 22 : 14;
517*49fe348cSAndroid Build Coastguard Worker
518*49fe348cSAndroid Build Coastguard Worker /* --- LSB values ---
519*49fe348cSAndroid Build Coastguard Worker * Until the symbol read indicates the escape value 16,
520*49fe348cSAndroid Build Coastguard Worker * read an LSB bit for each values.
521*49fe348cSAndroid Build Coastguard Worker * The LSB mode discard the first LSB (at this step) */
522*49fe348cSAndroid Build Coastguard Worker
523*49fe348cSAndroid Build Coastguard Worker int u = 0, v = 0;
524*49fe348cSAndroid Build Coastguard Worker int k = 0, shl = 0;
525*49fe348cSAndroid Build Coastguard Worker
526*49fe348cSAndroid Build Coastguard Worker unsigned s = lc3_get_symbol(bits, lc3_spectrum_models + lut[k]);
527*49fe348cSAndroid Build Coastguard Worker
528*49fe348cSAndroid Build Coastguard Worker if (lsb_mode && s >= 16) {
529*49fe348cSAndroid Build Coastguard Worker s = lc3_get_symbol(bits, lc3_spectrum_models + lut[++k]);
530*49fe348cSAndroid Build Coastguard Worker shl++;
531*49fe348cSAndroid Build Coastguard Worker }
532*49fe348cSAndroid Build Coastguard Worker
533*49fe348cSAndroid Build Coastguard Worker for ( ; s >= 16 && shl < max_shl; shl++) {
534*49fe348cSAndroid Build Coastguard Worker u |= lc3_get_bit(bits) << shl;
535*49fe348cSAndroid Build Coastguard Worker v |= lc3_get_bit(bits) << shl;
536*49fe348cSAndroid Build Coastguard Worker
537*49fe348cSAndroid Build Coastguard Worker k += (k < 3);
538*49fe348cSAndroid Build Coastguard Worker s = lc3_get_symbol(bits, lc3_spectrum_models + lut[k]);
539*49fe348cSAndroid Build Coastguard Worker }
540*49fe348cSAndroid Build Coastguard Worker
541*49fe348cSAndroid Build Coastguard Worker if (s >= 16)
542*49fe348cSAndroid Build Coastguard Worker return -1;
543*49fe348cSAndroid Build Coastguard Worker
544*49fe348cSAndroid Build Coastguard Worker /* --- MSB & sign values --- */
545*49fe348cSAndroid Build Coastguard Worker
546*49fe348cSAndroid Build Coastguard Worker int a = s % 4;
547*49fe348cSAndroid Build Coastguard Worker int b = s / 4;
548*49fe348cSAndroid Build Coastguard Worker
549*49fe348cSAndroid Build Coastguard Worker u |= a << shl;
550*49fe348cSAndroid Build Coastguard Worker v |= b << shl;
551*49fe348cSAndroid Build Coastguard Worker
552*49fe348cSAndroid Build Coastguard Worker x[i+0] = u && lc3_get_bit(bits) ? -u : u;
553*49fe348cSAndroid Build Coastguard Worker x[i+1] = v && lc3_get_bit(bits) ? -v : v;
554*49fe348cSAndroid Build Coastguard Worker
555*49fe348cSAndroid Build Coastguard Worker *nf_seed = (*nf_seed + (u & 0x7fff) * (i )
556*49fe348cSAndroid Build Coastguard Worker + (v & 0x7fff) * (i+1)) & 0xffff;
557*49fe348cSAndroid Build Coastguard Worker
558*49fe348cSAndroid Build Coastguard Worker /* --- Update state --- */
559*49fe348cSAndroid Build Coastguard Worker
560*49fe348cSAndroid Build Coastguard Worker state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
561*49fe348cSAndroid Build Coastguard Worker }
562*49fe348cSAndroid Build Coastguard Worker }
563*49fe348cSAndroid Build Coastguard Worker
564*49fe348cSAndroid Build Coastguard Worker return 0;
565*49fe348cSAndroid Build Coastguard Worker }
566*49fe348cSAndroid Build Coastguard Worker
567*49fe348cSAndroid Build Coastguard Worker /**
568*49fe348cSAndroid Build Coastguard Worker * Put residual bits of quantization
569*49fe348cSAndroid Build Coastguard Worker * bits Bitstream context
570*49fe348cSAndroid Build Coastguard Worker * nbits Maximum number of bits to output
571*49fe348cSAndroid Build Coastguard Worker * hrmode High-Resolution mode
572*49fe348cSAndroid Build Coastguard Worker * x, n Spectral quantized, and count of significants
573*49fe348cSAndroid Build Coastguard Worker */
put_residual(lc3_bits_t * bits,int nbits,bool hrmode,float * x,int n)574*49fe348cSAndroid Build Coastguard Worker LC3_HOT static void put_residual(lc3_bits_t *bits,
575*49fe348cSAndroid Build Coastguard Worker int nbits, bool hrmode, float *x, int n)
576*49fe348cSAndroid Build Coastguard Worker {
577*49fe348cSAndroid Build Coastguard Worker float xq_lim = hrmode ? 0.5f : 10.f/16;
578*49fe348cSAndroid Build Coastguard Worker float xq_off = xq_lim / 2;
579*49fe348cSAndroid Build Coastguard Worker
580*49fe348cSAndroid Build Coastguard Worker for (int iter = 0; iter < (hrmode ? 20 : 1) && nbits > 0; iter++) {
581*49fe348cSAndroid Build Coastguard Worker for (int i = 0; i < n && nbits > 0; i++) {
582*49fe348cSAndroid Build Coastguard Worker
583*49fe348cSAndroid Build Coastguard Worker float xr = fabsf(x[i]);
584*49fe348cSAndroid Build Coastguard Worker if (xr < xq_lim)
585*49fe348cSAndroid Build Coastguard Worker continue;
586*49fe348cSAndroid Build Coastguard Worker
587*49fe348cSAndroid Build Coastguard Worker bool b = (xr - truncf(xr) < xq_lim) ^ (x[i] < 0);
588*49fe348cSAndroid Build Coastguard Worker lc3_put_bit(bits, b);
589*49fe348cSAndroid Build Coastguard Worker nbits--;
590*49fe348cSAndroid Build Coastguard Worker
591*49fe348cSAndroid Build Coastguard Worker x[i] += b ? -xq_off : xq_off;
592*49fe348cSAndroid Build Coastguard Worker }
593*49fe348cSAndroid Build Coastguard Worker
594*49fe348cSAndroid Build Coastguard Worker xq_off *= xq_lim;
595*49fe348cSAndroid Build Coastguard Worker }
596*49fe348cSAndroid Build Coastguard Worker }
597*49fe348cSAndroid Build Coastguard Worker
598*49fe348cSAndroid Build Coastguard Worker /**
599*49fe348cSAndroid Build Coastguard Worker * Get residual bits of quantization
600*49fe348cSAndroid Build Coastguard Worker * bits Bitstream context
601*49fe348cSAndroid Build Coastguard Worker * nbits Maximum number of bits to output
602*49fe348cSAndroid Build Coastguard Worker * hrmode High-Resolution mode
603*49fe348cSAndroid Build Coastguard Worker * x, nq Spectral quantized, and count of significants
604*49fe348cSAndroid Build Coastguard Worker */
get_residual(lc3_bits_t * bits,int nbits,bool hrmode,float * x,int n)605*49fe348cSAndroid Build Coastguard Worker LC3_HOT static void get_residual(lc3_bits_t *bits,
606*49fe348cSAndroid Build Coastguard Worker int nbits, bool hrmode, float *x, int n)
607*49fe348cSAndroid Build Coastguard Worker {
608*49fe348cSAndroid Build Coastguard Worker float xq_off_1 = hrmode ? 0.25f : 5.f/16;
609*49fe348cSAndroid Build Coastguard Worker float xq_off_2 = hrmode ? 0.25f : 3.f/16;
610*49fe348cSAndroid Build Coastguard Worker
611*49fe348cSAndroid Build Coastguard Worker for (int iter = 0; iter < (hrmode ? 20 : 1) && nbits > 0; iter++) {
612*49fe348cSAndroid Build Coastguard Worker for (int i = 0; i < n && nbits > 0; i++) {
613*49fe348cSAndroid Build Coastguard Worker
614*49fe348cSAndroid Build Coastguard Worker if (x[i] == 0)
615*49fe348cSAndroid Build Coastguard Worker continue;
616*49fe348cSAndroid Build Coastguard Worker
617*49fe348cSAndroid Build Coastguard Worker if (lc3_get_bit(bits) == 0)
618*49fe348cSAndroid Build Coastguard Worker x[i] -= x[i] < 0 ? xq_off_1 : xq_off_2;
619*49fe348cSAndroid Build Coastguard Worker else
620*49fe348cSAndroid Build Coastguard Worker x[i] += x[i] > 0 ? xq_off_1 : xq_off_2;
621*49fe348cSAndroid Build Coastguard Worker
622*49fe348cSAndroid Build Coastguard Worker nbits--;
623*49fe348cSAndroid Build Coastguard Worker }
624*49fe348cSAndroid Build Coastguard Worker
625*49fe348cSAndroid Build Coastguard Worker xq_off_1 *= 0.5f;
626*49fe348cSAndroid Build Coastguard Worker xq_off_2 *= 0.5f;
627*49fe348cSAndroid Build Coastguard Worker }
628*49fe348cSAndroid Build Coastguard Worker }
629*49fe348cSAndroid Build Coastguard Worker
630*49fe348cSAndroid Build Coastguard Worker /**
631*49fe348cSAndroid Build Coastguard Worker * Put LSB values of quantized spectrum values
632*49fe348cSAndroid Build Coastguard Worker * bits Bitstream context
633*49fe348cSAndroid Build Coastguard Worker * nbits Maximum number of bits to output
634*49fe348cSAndroid Build Coastguard Worker * hrmode High-Resolution mode
635*49fe348cSAndroid Build Coastguard Worker * x, n Spectral quantized, and count of significants
636*49fe348cSAndroid Build Coastguard Worker */
put_lsb(lc3_bits_t * bits,int nbits,bool hrmode,const float * x,int n)637*49fe348cSAndroid Build Coastguard Worker LC3_HOT static void put_lsb(lc3_bits_t *bits,
638*49fe348cSAndroid Build Coastguard Worker int nbits, bool hrmode, const float *x, int n)
639*49fe348cSAndroid Build Coastguard Worker {
640*49fe348cSAndroid Build Coastguard Worker for (int i = 0; i < n && nbits > 0; i += 2) {
641*49fe348cSAndroid Build Coastguard Worker
642*49fe348cSAndroid Build Coastguard Worker float xq_off = hrmode ? 0.5f : 6.f/16;
643*49fe348cSAndroid Build Coastguard Worker uint32_t a = fabsf(x[i+0]) + xq_off;
644*49fe348cSAndroid Build Coastguard Worker uint32_t b = fabsf(x[i+1]) + xq_off;
645*49fe348cSAndroid Build Coastguard Worker
646*49fe348cSAndroid Build Coastguard Worker if ((a | b) >> 2 == 0)
647*49fe348cSAndroid Build Coastguard Worker continue;
648*49fe348cSAndroid Build Coastguard Worker
649*49fe348cSAndroid Build Coastguard Worker if (nbits-- > 0)
650*49fe348cSAndroid Build Coastguard Worker lc3_put_bit(bits, a & 1);
651*49fe348cSAndroid Build Coastguard Worker
652*49fe348cSAndroid Build Coastguard Worker if (a == 1 && nbits-- > 0)
653*49fe348cSAndroid Build Coastguard Worker lc3_put_bit(bits, x[i+0] < 0);
654*49fe348cSAndroid Build Coastguard Worker
655*49fe348cSAndroid Build Coastguard Worker if (nbits-- > 0)
656*49fe348cSAndroid Build Coastguard Worker lc3_put_bit(bits, b & 1);
657*49fe348cSAndroid Build Coastguard Worker
658*49fe348cSAndroid Build Coastguard Worker if (b == 1 && nbits-- > 0)
659*49fe348cSAndroid Build Coastguard Worker lc3_put_bit(bits, x[i+1] < 0);
660*49fe348cSAndroid Build Coastguard Worker }
661*49fe348cSAndroid Build Coastguard Worker }
662*49fe348cSAndroid Build Coastguard Worker
663*49fe348cSAndroid Build Coastguard Worker /**
664*49fe348cSAndroid Build Coastguard Worker * Get LSB values of quantized spectrum values
665*49fe348cSAndroid Build Coastguard Worker * bits Bitstream context
666*49fe348cSAndroid Build Coastguard Worker * nbits Maximum number of bits to output
667*49fe348cSAndroid Build Coastguard Worker * x, nq Spectral quantized, and count of significants
668*49fe348cSAndroid Build Coastguard Worker * nf_seed Update the noise factor seed according
669*49fe348cSAndroid Build Coastguard Worker */
get_lsb(lc3_bits_t * bits,int nbits,float * x,int nq,uint16_t * nf_seed)670*49fe348cSAndroid Build Coastguard Worker LC3_HOT static void get_lsb(lc3_bits_t *bits,
671*49fe348cSAndroid Build Coastguard Worker int nbits, float *x, int nq, uint16_t *nf_seed)
672*49fe348cSAndroid Build Coastguard Worker {
673*49fe348cSAndroid Build Coastguard Worker for (int i = 0; i < nq && nbits > 0; i += 2) {
674*49fe348cSAndroid Build Coastguard Worker
675*49fe348cSAndroid Build Coastguard Worker float a = fabsf(x[i]), b = fabsf(x[i+1]);
676*49fe348cSAndroid Build Coastguard Worker
677*49fe348cSAndroid Build Coastguard Worker if (fmaxf(a, b) < 4)
678*49fe348cSAndroid Build Coastguard Worker continue;
679*49fe348cSAndroid Build Coastguard Worker
680*49fe348cSAndroid Build Coastguard Worker if (nbits-- > 0 && lc3_get_bit(bits)) {
681*49fe348cSAndroid Build Coastguard Worker if (a) {
682*49fe348cSAndroid Build Coastguard Worker x[i] += x[i] < 0 ? -1 : 1;
683*49fe348cSAndroid Build Coastguard Worker *nf_seed = (*nf_seed + i) & 0xffff;
684*49fe348cSAndroid Build Coastguard Worker } else if (nbits-- > 0) {
685*49fe348cSAndroid Build Coastguard Worker x[i] = lc3_get_bit(bits) ? -1 : 1;
686*49fe348cSAndroid Build Coastguard Worker *nf_seed = (*nf_seed + i) & 0xffff;
687*49fe348cSAndroid Build Coastguard Worker }
688*49fe348cSAndroid Build Coastguard Worker }
689*49fe348cSAndroid Build Coastguard Worker
690*49fe348cSAndroid Build Coastguard Worker if (nbits-- > 0 && lc3_get_bit(bits)) {
691*49fe348cSAndroid Build Coastguard Worker if (b) {
692*49fe348cSAndroid Build Coastguard Worker x[i+1] += x[i+1] < 0 ? -1 : 1;
693*49fe348cSAndroid Build Coastguard Worker *nf_seed = (*nf_seed + i+1) & 0xffff;
694*49fe348cSAndroid Build Coastguard Worker } else if (nbits-- > 0) {
695*49fe348cSAndroid Build Coastguard Worker x[i+1] = lc3_get_bit(bits) ? -1 : 1;
696*49fe348cSAndroid Build Coastguard Worker *nf_seed = (*nf_seed + i+1) & 0xffff;
697*49fe348cSAndroid Build Coastguard Worker }
698*49fe348cSAndroid Build Coastguard Worker }
699*49fe348cSAndroid Build Coastguard Worker }
700*49fe348cSAndroid Build Coastguard Worker }
701*49fe348cSAndroid Build Coastguard Worker
702*49fe348cSAndroid Build Coastguard Worker
703*49fe348cSAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
704*49fe348cSAndroid Build Coastguard Worker * Noise coding
705*49fe348cSAndroid Build Coastguard Worker * -------------------------------------------------------------------------- */
706*49fe348cSAndroid Build Coastguard Worker
707*49fe348cSAndroid Build Coastguard Worker /**
708*49fe348cSAndroid Build Coastguard Worker * Estimate noise level
709*49fe348cSAndroid Build Coastguard Worker * dt, bw Duration and bandwidth of the frame
710*49fe348cSAndroid Build Coastguard Worker * hrmode High-Resolution mode
711*49fe348cSAndroid Build Coastguard Worker * x, n Spectral quantized, and count of significants
712*49fe348cSAndroid Build Coastguard Worker * return Noise factor (0 to 7)
713*49fe348cSAndroid Build Coastguard Worker */
estimate_noise(enum lc3_dt dt,enum lc3_bandwidth bw,bool hrmode,const float * x,int n)714*49fe348cSAndroid Build Coastguard Worker LC3_HOT static int estimate_noise(
715*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_bandwidth bw, bool hrmode, const float *x, int n)
716*49fe348cSAndroid Build Coastguard Worker {
717*49fe348cSAndroid Build Coastguard Worker int bw_stop = lc3_ne(dt, (enum lc3_srate)LC3_MIN(bw, LC3_BANDWIDTH_FB));
718*49fe348cSAndroid Build Coastguard Worker int w = 1 + (dt >= LC3_DT_7M5) + (dt>= LC3_DT_10M);
719*49fe348cSAndroid Build Coastguard Worker
720*49fe348cSAndroid Build Coastguard Worker float xq_lim = hrmode ? 0.5f : 10.f/16;
721*49fe348cSAndroid Build Coastguard Worker float sum = 0;
722*49fe348cSAndroid Build Coastguard Worker int i, ns = 0, z = 0;
723*49fe348cSAndroid Build Coastguard Worker
724*49fe348cSAndroid Build Coastguard Worker for (i = 6 * (1 + dt) - w; i < LC3_MIN(n, bw_stop); i++) {
725*49fe348cSAndroid Build Coastguard Worker z = fabsf(x[i]) < xq_lim ? z + 1 : 0;
726*49fe348cSAndroid Build Coastguard Worker if (z > 2*w)
727*49fe348cSAndroid Build Coastguard Worker sum += fabsf(x[i - w]), ns++;
728*49fe348cSAndroid Build Coastguard Worker }
729*49fe348cSAndroid Build Coastguard Worker
730*49fe348cSAndroid Build Coastguard Worker for ( ; i < bw_stop + w; i++)
731*49fe348cSAndroid Build Coastguard Worker if (++z > 2*w)
732*49fe348cSAndroid Build Coastguard Worker sum += fabsf(x[i - w]), ns++;
733*49fe348cSAndroid Build Coastguard Worker
734*49fe348cSAndroid Build Coastguard Worker int nf = ns ? 8 - (int)((16 * sum) / ns + 0.5f) : 8;
735*49fe348cSAndroid Build Coastguard Worker
736*49fe348cSAndroid Build Coastguard Worker return LC3_CLIP(nf, 0, 7);
737*49fe348cSAndroid Build Coastguard Worker }
738*49fe348cSAndroid Build Coastguard Worker
739*49fe348cSAndroid Build Coastguard Worker /**
740*49fe348cSAndroid Build Coastguard Worker * Noise filling
741*49fe348cSAndroid Build Coastguard Worker * dt, bw Duration and bandwidth of the frame
742*49fe348cSAndroid Build Coastguard Worker * nf, nf_seed The noise factor and pseudo-random seed
743*49fe348cSAndroid Build Coastguard Worker * g Quantization gain
744*49fe348cSAndroid Build Coastguard Worker * x, nq Spectral quantized, and count of significants
745*49fe348cSAndroid Build Coastguard Worker */
fill_noise(enum lc3_dt dt,enum lc3_bandwidth bw,int nf,uint16_t nf_seed,float g,float * x,int nq)746*49fe348cSAndroid Build Coastguard Worker LC3_HOT static void fill_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
747*49fe348cSAndroid Build Coastguard Worker int nf, uint16_t nf_seed, float g, float *x, int nq)
748*49fe348cSAndroid Build Coastguard Worker {
749*49fe348cSAndroid Build Coastguard Worker int bw_stop = lc3_ne(dt, (enum lc3_srate)LC3_MIN(bw, LC3_BANDWIDTH_FB));
750*49fe348cSAndroid Build Coastguard Worker int w = 1 + (dt >= LC3_DT_7M5) + (dt>= LC3_DT_10M);
751*49fe348cSAndroid Build Coastguard Worker
752*49fe348cSAndroid Build Coastguard Worker float s = g * (float)(8 - nf) / 16;
753*49fe348cSAndroid Build Coastguard Worker int i, z = 0;
754*49fe348cSAndroid Build Coastguard Worker
755*49fe348cSAndroid Build Coastguard Worker for (i = 6 * (1 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
756*49fe348cSAndroid Build Coastguard Worker z = x[i] ? 0 : z + 1;
757*49fe348cSAndroid Build Coastguard Worker if (z > 2*w) {
758*49fe348cSAndroid Build Coastguard Worker nf_seed = (13849 + nf_seed*31821) & 0xffff;
759*49fe348cSAndroid Build Coastguard Worker x[i - w] = nf_seed & 0x8000 ? -s : s;
760*49fe348cSAndroid Build Coastguard Worker }
761*49fe348cSAndroid Build Coastguard Worker }
762*49fe348cSAndroid Build Coastguard Worker
763*49fe348cSAndroid Build Coastguard Worker for ( ; i < bw_stop + w; i++)
764*49fe348cSAndroid Build Coastguard Worker if (++z > 2*w) {
765*49fe348cSAndroid Build Coastguard Worker nf_seed = (13849 + nf_seed*31821) & 0xffff;
766*49fe348cSAndroid Build Coastguard Worker x[i - w] = nf_seed & 0x8000 ? -s : s;
767*49fe348cSAndroid Build Coastguard Worker }
768*49fe348cSAndroid Build Coastguard Worker }
769*49fe348cSAndroid Build Coastguard Worker
770*49fe348cSAndroid Build Coastguard Worker /**
771*49fe348cSAndroid Build Coastguard Worker * Put noise factor
772*49fe348cSAndroid Build Coastguard Worker * bits Bitstream context
773*49fe348cSAndroid Build Coastguard Worker * nf Noise factor (0 to 7)
774*49fe348cSAndroid Build Coastguard Worker */
put_noise_factor(lc3_bits_t * bits,int nf)775*49fe348cSAndroid Build Coastguard Worker static void put_noise_factor(lc3_bits_t *bits, int nf)
776*49fe348cSAndroid Build Coastguard Worker {
777*49fe348cSAndroid Build Coastguard Worker lc3_put_bits(bits, nf, 3);
778*49fe348cSAndroid Build Coastguard Worker }
779*49fe348cSAndroid Build Coastguard Worker
780*49fe348cSAndroid Build Coastguard Worker /**
781*49fe348cSAndroid Build Coastguard Worker * Get noise factor
782*49fe348cSAndroid Build Coastguard Worker * bits Bitstream context
783*49fe348cSAndroid Build Coastguard Worker * return Noise factor (0 to 7)
784*49fe348cSAndroid Build Coastguard Worker */
get_noise_factor(lc3_bits_t * bits)785*49fe348cSAndroid Build Coastguard Worker static int get_noise_factor(lc3_bits_t *bits)
786*49fe348cSAndroid Build Coastguard Worker {
787*49fe348cSAndroid Build Coastguard Worker return lc3_get_bits(bits, 3);
788*49fe348cSAndroid Build Coastguard Worker }
789*49fe348cSAndroid Build Coastguard Worker
790*49fe348cSAndroid Build Coastguard Worker
791*49fe348cSAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
792*49fe348cSAndroid Build Coastguard Worker * Encoding
793*49fe348cSAndroid Build Coastguard Worker * -------------------------------------------------------------------------- */
794*49fe348cSAndroid Build Coastguard Worker
795*49fe348cSAndroid Build Coastguard Worker /**
796*49fe348cSAndroid Build Coastguard Worker * Bit consumption of the number of coded coefficients
797*49fe348cSAndroid Build Coastguard Worker * dt, sr, nbytes Duration, samplerate and size of the frame
798*49fe348cSAndroid Build Coastguard Worker * return Bit consumpution of the number of coded coefficients
799*49fe348cSAndroid Build Coastguard Worker */
get_nbits_nq(enum lc3_dt dt,enum lc3_srate sr)800*49fe348cSAndroid Build Coastguard Worker static int get_nbits_nq(enum lc3_dt dt, enum lc3_srate sr)
801*49fe348cSAndroid Build Coastguard Worker {
802*49fe348cSAndroid Build Coastguard Worker int ne = lc3_ne(dt, sr);
803*49fe348cSAndroid Build Coastguard Worker return 4 + (ne > 32) + (ne > 64) + (ne > 128) + (ne > 256) + (ne > 512);
804*49fe348cSAndroid Build Coastguard Worker }
805*49fe348cSAndroid Build Coastguard Worker
806*49fe348cSAndroid Build Coastguard Worker /**
807*49fe348cSAndroid Build Coastguard Worker * Bit consumption of the arithmetic coder
808*49fe348cSAndroid Build Coastguard Worker * dt, sr, nbytes Duration, samplerate and size of the frame
809*49fe348cSAndroid Build Coastguard Worker * return Bit consumption of bitstream data
810*49fe348cSAndroid Build Coastguard Worker */
get_nbits_ac(enum lc3_dt dt,enum lc3_srate sr,int nbytes)811*49fe348cSAndroid Build Coastguard Worker static int get_nbits_ac(enum lc3_dt dt, enum lc3_srate sr, int nbytes)
812*49fe348cSAndroid Build Coastguard Worker {
813*49fe348cSAndroid Build Coastguard Worker return get_nbits_nq(dt, sr) +
814*49fe348cSAndroid Build Coastguard Worker 3 + lc3_hr(sr) + LC3_MIN((nbytes-1) / 160, 2);
815*49fe348cSAndroid Build Coastguard Worker }
816*49fe348cSAndroid Build Coastguard Worker
817*49fe348cSAndroid Build Coastguard Worker /**
818*49fe348cSAndroid Build Coastguard Worker * Spectrum analysis
819*49fe348cSAndroid Build Coastguard Worker */
lc3_spec_analyze(enum lc3_dt dt,enum lc3_srate sr,int nbytes,bool pitch,const lc3_tns_data_t * tns,struct lc3_spec_analysis * spec,float * x,struct lc3_spec_side * side)820*49fe348cSAndroid Build Coastguard Worker void lc3_spec_analyze(
821*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, int nbytes,
822*49fe348cSAndroid Build Coastguard Worker bool pitch, const lc3_tns_data_t *tns,
823*49fe348cSAndroid Build Coastguard Worker struct lc3_spec_analysis *spec,
824*49fe348cSAndroid Build Coastguard Worker float *x, struct lc3_spec_side *side)
825*49fe348cSAndroid Build Coastguard Worker {
826*49fe348cSAndroid Build Coastguard Worker bool reset_off;
827*49fe348cSAndroid Build Coastguard Worker
828*49fe348cSAndroid Build Coastguard Worker /* --- Bit budget --- */
829*49fe348cSAndroid Build Coastguard Worker
830*49fe348cSAndroid Build Coastguard Worker const int nbits_gain = 8;
831*49fe348cSAndroid Build Coastguard Worker const int nbits_nf = 3;
832*49fe348cSAndroid Build Coastguard Worker
833*49fe348cSAndroid Build Coastguard Worker int nbits_budget = 8*nbytes - get_nbits_ac(dt, sr, nbytes) -
834*49fe348cSAndroid Build Coastguard Worker lc3_bwdet_get_nbits(sr) - lc3_ltpf_get_nbits(pitch) -
835*49fe348cSAndroid Build Coastguard Worker lc3_sns_get_nbits() - lc3_tns_get_nbits(tns) - nbits_gain - nbits_nf;
836*49fe348cSAndroid Build Coastguard Worker
837*49fe348cSAndroid Build Coastguard Worker /* --- Global gain --- */
838*49fe348cSAndroid Build Coastguard Worker
839*49fe348cSAndroid Build Coastguard Worker float nbits_off = spec->nbits_off + spec->nbits_spare;
840*49fe348cSAndroid Build Coastguard Worker nbits_off = fminf(fmaxf(nbits_off, -40), 40);
841*49fe348cSAndroid Build Coastguard Worker nbits_off = 0.8f * spec->nbits_off + 0.2f * nbits_off;
842*49fe348cSAndroid Build Coastguard Worker
843*49fe348cSAndroid Build Coastguard Worker int g_off = resolve_gain_offset(sr, nbytes);
844*49fe348cSAndroid Build Coastguard Worker
845*49fe348cSAndroid Build Coastguard Worker int g_min, g_int = estimate_gain(dt, sr,
846*49fe348cSAndroid Build Coastguard Worker x, nbytes, nbits_budget, nbits_off, g_off, &reset_off, &g_min);
847*49fe348cSAndroid Build Coastguard Worker
848*49fe348cSAndroid Build Coastguard Worker /* --- Quantization --- */
849*49fe348cSAndroid Build Coastguard Worker
850*49fe348cSAndroid Build Coastguard Worker quantize(dt, sr, g_int, x, &side->nq);
851*49fe348cSAndroid Build Coastguard Worker
852*49fe348cSAndroid Build Coastguard Worker int nbits = compute_nbits(dt, sr, nbytes, x, &side->nq, 0, NULL);
853*49fe348cSAndroid Build Coastguard Worker
854*49fe348cSAndroid Build Coastguard Worker spec->nbits_off = reset_off ? 0 : nbits_off;
855*49fe348cSAndroid Build Coastguard Worker spec->nbits_spare = reset_off ? 0 : nbits_budget - nbits;
856*49fe348cSAndroid Build Coastguard Worker
857*49fe348cSAndroid Build Coastguard Worker /* --- Adjust gain and requantize --- */
858*49fe348cSAndroid Build Coastguard Worker
859*49fe348cSAndroid Build Coastguard Worker int g_adj = adjust_gain(dt, sr,
860*49fe348cSAndroid Build Coastguard Worker g_off + g_int, nbits, nbits_budget, g_off + g_min);
861*49fe348cSAndroid Build Coastguard Worker
862*49fe348cSAndroid Build Coastguard Worker if (g_adj)
863*49fe348cSAndroid Build Coastguard Worker quantize(dt, sr, g_adj, x, &side->nq);
864*49fe348cSAndroid Build Coastguard Worker
865*49fe348cSAndroid Build Coastguard Worker side->g_idx = g_int + g_adj + g_off;
866*49fe348cSAndroid Build Coastguard Worker nbits = compute_nbits(dt, sr, nbytes,
867*49fe348cSAndroid Build Coastguard Worker x, &side->nq, nbits_budget, &side->lsb_mode);
868*49fe348cSAndroid Build Coastguard Worker }
869*49fe348cSAndroid Build Coastguard Worker
870*49fe348cSAndroid Build Coastguard Worker /**
871*49fe348cSAndroid Build Coastguard Worker * Put spectral quantization side data
872*49fe348cSAndroid Build Coastguard Worker */
lc3_spec_put_side(lc3_bits_t * bits,enum lc3_dt dt,enum lc3_srate sr,const struct lc3_spec_side * side)873*49fe348cSAndroid Build Coastguard Worker void lc3_spec_put_side(lc3_bits_t *bits,
874*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr,
875*49fe348cSAndroid Build Coastguard Worker const struct lc3_spec_side *side)
876*49fe348cSAndroid Build Coastguard Worker {
877*49fe348cSAndroid Build Coastguard Worker int nbits_nq = get_nbits_nq(dt, sr);
878*49fe348cSAndroid Build Coastguard Worker
879*49fe348cSAndroid Build Coastguard Worker lc3_put_bits(bits, LC3_MAX(side->nq >> 1, 1) - 1, nbits_nq);
880*49fe348cSAndroid Build Coastguard Worker lc3_put_bits(bits, side->lsb_mode, 1);
881*49fe348cSAndroid Build Coastguard Worker lc3_put_bits(bits, side->g_idx, 8);
882*49fe348cSAndroid Build Coastguard Worker }
883*49fe348cSAndroid Build Coastguard Worker
884*49fe348cSAndroid Build Coastguard Worker /**
885*49fe348cSAndroid Build Coastguard Worker * Encode spectral coefficients
886*49fe348cSAndroid Build Coastguard Worker */
lc3_spec_encode(lc3_bits_t * bits,enum lc3_dt dt,enum lc3_srate sr,enum lc3_bandwidth bw,int nbytes,const lc3_spec_side_t * side,float * x)887*49fe348cSAndroid Build Coastguard Worker void lc3_spec_encode(lc3_bits_t *bits,
888*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw,
889*49fe348cSAndroid Build Coastguard Worker int nbytes, const lc3_spec_side_t *side, float *x)
890*49fe348cSAndroid Build Coastguard Worker {
891*49fe348cSAndroid Build Coastguard Worker bool lsb_mode = side->lsb_mode;
892*49fe348cSAndroid Build Coastguard Worker int nq = side->nq;
893*49fe348cSAndroid Build Coastguard Worker
894*49fe348cSAndroid Build Coastguard Worker put_noise_factor(bits, estimate_noise(dt, bw, lc3_hr(sr), x, nq));
895*49fe348cSAndroid Build Coastguard Worker
896*49fe348cSAndroid Build Coastguard Worker put_quantized(bits, dt, sr, nbytes, x, nq, lsb_mode);
897*49fe348cSAndroid Build Coastguard Worker
898*49fe348cSAndroid Build Coastguard Worker int nbits_left = lc3_get_bits_left(bits);
899*49fe348cSAndroid Build Coastguard Worker
900*49fe348cSAndroid Build Coastguard Worker if (lsb_mode)
901*49fe348cSAndroid Build Coastguard Worker put_lsb(bits, nbits_left, lc3_hr(sr), x, nq);
902*49fe348cSAndroid Build Coastguard Worker else
903*49fe348cSAndroid Build Coastguard Worker put_residual(bits, nbits_left, lc3_hr(sr), x, nq);
904*49fe348cSAndroid Build Coastguard Worker }
905*49fe348cSAndroid Build Coastguard Worker
906*49fe348cSAndroid Build Coastguard Worker
907*49fe348cSAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
908*49fe348cSAndroid Build Coastguard Worker * Decoding
909*49fe348cSAndroid Build Coastguard Worker * -------------------------------------------------------------------------- */
910*49fe348cSAndroid Build Coastguard Worker
911*49fe348cSAndroid Build Coastguard Worker /**
912*49fe348cSAndroid Build Coastguard Worker * Get spectral quantization side data
913*49fe348cSAndroid Build Coastguard Worker */
lc3_spec_get_side(lc3_bits_t * bits,enum lc3_dt dt,enum lc3_srate sr,struct lc3_spec_side * side)914*49fe348cSAndroid Build Coastguard Worker int lc3_spec_get_side(lc3_bits_t *bits,
915*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, struct lc3_spec_side *side)
916*49fe348cSAndroid Build Coastguard Worker {
917*49fe348cSAndroid Build Coastguard Worker int nbits_nq = get_nbits_nq(dt, sr);
918*49fe348cSAndroid Build Coastguard Worker int ne = lc3_ne(dt, sr);
919*49fe348cSAndroid Build Coastguard Worker
920*49fe348cSAndroid Build Coastguard Worker side->nq = (lc3_get_bits(bits, nbits_nq) + 1) << 1;
921*49fe348cSAndroid Build Coastguard Worker side->lsb_mode = lc3_get_bit(bits);
922*49fe348cSAndroid Build Coastguard Worker side->g_idx = lc3_get_bits(bits, 8);
923*49fe348cSAndroid Build Coastguard Worker
924*49fe348cSAndroid Build Coastguard Worker return side->nq > ne ? (side->nq = ne), -1 : 0;
925*49fe348cSAndroid Build Coastguard Worker }
926*49fe348cSAndroid Build Coastguard Worker
927*49fe348cSAndroid Build Coastguard Worker /**
928*49fe348cSAndroid Build Coastguard Worker * Decode spectral coefficients
929*49fe348cSAndroid Build Coastguard Worker */
lc3_spec_decode(lc3_bits_t * bits,enum lc3_dt dt,enum lc3_srate sr,enum lc3_bandwidth bw,int nbytes,const lc3_spec_side_t * side,float * x)930*49fe348cSAndroid Build Coastguard Worker int lc3_spec_decode(lc3_bits_t *bits,
931*49fe348cSAndroid Build Coastguard Worker enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw,
932*49fe348cSAndroid Build Coastguard Worker int nbytes, const lc3_spec_side_t *side, float *x)
933*49fe348cSAndroid Build Coastguard Worker {
934*49fe348cSAndroid Build Coastguard Worker bool lsb_mode = side->lsb_mode;
935*49fe348cSAndroid Build Coastguard Worker int nq = side->nq;
936*49fe348cSAndroid Build Coastguard Worker int ret = 0;
937*49fe348cSAndroid Build Coastguard Worker
938*49fe348cSAndroid Build Coastguard Worker int nf = get_noise_factor(bits);
939*49fe348cSAndroid Build Coastguard Worker uint16_t nf_seed;
940*49fe348cSAndroid Build Coastguard Worker
941*49fe348cSAndroid Build Coastguard Worker if ((ret = get_quantized(bits, dt, sr, nbytes,
942*49fe348cSAndroid Build Coastguard Worker nq, lsb_mode, x, &nf_seed)) < 0)
943*49fe348cSAndroid Build Coastguard Worker return ret;
944*49fe348cSAndroid Build Coastguard Worker
945*49fe348cSAndroid Build Coastguard Worker int nbits_left = lc3_get_bits_left(bits);
946*49fe348cSAndroid Build Coastguard Worker
947*49fe348cSAndroid Build Coastguard Worker if (lsb_mode)
948*49fe348cSAndroid Build Coastguard Worker get_lsb(bits, nbits_left, x, nq, &nf_seed);
949*49fe348cSAndroid Build Coastguard Worker else
950*49fe348cSAndroid Build Coastguard Worker get_residual(bits, nbits_left, lc3_hr(sr), x, nq);
951*49fe348cSAndroid Build Coastguard Worker
952*49fe348cSAndroid Build Coastguard Worker int g_int = side->g_idx - resolve_gain_offset(sr, nbytes);
953*49fe348cSAndroid Build Coastguard Worker float g = unquantize(dt, sr, g_int, x, nq);
954*49fe348cSAndroid Build Coastguard Worker
955*49fe348cSAndroid Build Coastguard Worker if (nq > 2 || x[0] || x[1] || side->g_idx > 0 || nf < 7)
956*49fe348cSAndroid Build Coastguard Worker fill_noise(dt, bw, nf, nf_seed, g, x, nq);
957*49fe348cSAndroid Build Coastguard Worker
958*49fe348cSAndroid Build Coastguard Worker return 0;
959*49fe348cSAndroid Build Coastguard Worker }
960