xref: /aosp_15_r20/external/libxaac/encoder/iusace_tcx_enc.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1 /******************************************************************************
2  *                                                                            *
3  * Copyright (C) 2023 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19  */
20 
21 #include <string.h>
22 #include <math.h>
23 #include "ixheaac_type_def.h"
24 #include "ixheaace_adjust_threshold_data.h"
25 #include "iusace_bitbuffer.h"
26 
27 /* DRC */
28 #include "impd_drc_common_enc.h"
29 #include "impd_drc_uni_drc.h"
30 #include "impd_drc_tables.h"
31 #include "impd_drc_api.h"
32 #include "impd_drc_uni_drc_eq.h"
33 #include "impd_drc_uni_drc_filter_bank.h"
34 #include "impd_drc_gain_enc.h"
35 #include "impd_drc_struct_def.h"
36 
37 #include "iusace_cnst.h"
38 #include "iusace_tns_usac.h"
39 #include "iusace_psy_mod.h"
40 #include "iusace_tns_usac.h"
41 #include "iusace_config.h"
42 #include "iusace_fft.h"
43 #include "iusace_tcx_mdct.h"
44 #include "iusace_arith_enc.h"
45 #include "iusace_fd_qc_util.h"
46 #include "iusace_fd_quant.h"
47 #include "iusace_block_switch_const.h"
48 #include "iusace_block_switch_struct_def.h"
49 #include "iusace_ms.h"
50 #include "iusace_signal_classifier.h"
51 #include "ixheaace_sbr_header.h"
52 #include "ixheaace_config.h"
53 #include "ixheaace_asc_write.h"
54 #include "iusace_main.h"
55 #include "iusace_lpd_rom.h"
56 #include "iusace_lpd.h"
57 #include "iusace_avq_enc.h"
58 #include "ixheaace_common_utils.h"
59 
60 const UWORD32 iusace_pow10_gain_div28[128] = {
61     1024,     1112,     1207,     1311,     1423,     1545,     1677,     1821,     1977,
62     2146,     2330,     2530,     2747,     2983,     3238,     3516,     3817,     4144,
63     4499,     4885,     5304,     5758,     6252,     6788,     7370,     8001,     8687,
64     9432,     10240,    11118,    12071,    13105,    14228,    15448,    16772,    18210,
65     19770,    21465,    23305,    25302,    27471,    29825,    32382,    35157,    38171,
66     41442,    44994,    48851,    53038,    57584,    62519,    67878,    73696,    80012,
67     86870,    94316,    102400,   111177,   120706,   131052,   142284,   154480,   167720,
68     182096,   197703,   214649,   233047,   253021,   274708,   298254,   323817,   351572,
69     381706,   414422,   449943,   488508,   530378,   575838,   625193,   678779,   736958,
70     800124,   868703,   943161,   1024000,  1111768,  1207059,  1310517,  1422843,  1544797,
71     1677203,  1820958,  1977034,  2146488,  2330466,  2530213,  2747080,  2982536,  3238172,
72     3515720,  3817056,  4144220,  4499426,  4885077,  5303782,  5758375,  6251932,  6787792,
73     7369581,  8001236,  8687031,  9431606,  10240000, 11117682, 12070591, 13105175, 14228434,
74     15447969, 16772032, 18209581, 19770345, 21464883, 23304662, 25302131, 27470805, 29825358,
75     32381723, 35157197};
76 
77 static const FLOAT64 iusace_lpc_pre_twid_cos[ORDER + 1] = {1.0,
78                                                            0.99969881867944277,
79                                                            0.99879545613814691,
80                                                            0.99729045666498317,
81                                                            0.99518472640441780,
82                                                            0.99247953486470630,
83                                                            0.98917650991010153,
84                                                            0.98527764316379052,
85                                                            0.98078527933727178,
86                                                            0.97570212991605565,
87                                                            0.97003125425052761,
88                                                            0.96377606826277584,
89                                                            0.95694033551585822,
90                                                            0.94952817722361749,
91                                                            0.94154406823678738,
92                                                            0.93299279849944938,
93                                                            0.92387952832938047};
94 
95 static const FLOAT64 iusace_lpc_pre_twid_sin[ORDER + 1] = {0,
96                                                            0.024541229205697054,
97                                                            0.049067675691753569,
98                                                            0.073564563785488826,
99                                                            0.098017143048367339,
100                                                            0.12241067304257494,
101                                                            0.14673047482398086,
102                                                            0.17096188429473480,
103                                                            0.19509032737506427,
104                                                            0.21910124070226658,
105                                                            0.24298017568754085,
106                                                            0.26671274855909161,
107                                                            0.29028467796767482,
108                                                            0.31368175059826858,
109                                                            0.33688984485751389,
110                                                            0.35989503740419343,
111                                                            0.38268344246110436};
112 
iusace_lpc_mdct(FLOAT32 * ptr_lpc_coeffs,FLOAT32 * mdct_gains,WORD32 length,iusace_scratch_mem * pstr_scratch)113 static VOID iusace_lpc_mdct(FLOAT32 *ptr_lpc_coeffs, FLOAT32 *mdct_gains, WORD32 length,
114                             iusace_scratch_mem *pstr_scratch) {
115   FLOAT32 *in_out = pstr_scratch->p_in_out_tcx;
116   WORD32 i;
117 
118   for (i = 0; i < ORDER + 1; i++) {
119     in_out[2 * i] = (FLOAT32)(ptr_lpc_coeffs[i] * iusace_lpc_pre_twid_cos[i]);
120     in_out[2 * i + 1] = (FLOAT32)(-ptr_lpc_coeffs[i] * iusace_lpc_pre_twid_sin[i]);
121   }
122   for (; i < length; i++) {
123     in_out[2 * i] = 0.f;
124     in_out[2 * i + 1] = 0.f;
125   }
126 
127   iusace_complex_fft(in_out, length, pstr_scratch);
128 
129   for (i = 0; i<length>> 1; i++) {
130     mdct_gains[i] = (FLOAT32)(
131         1.0f / sqrt(in_out[2 * i] * in_out[2 * i] + in_out[2 * i + 1] * in_out[2 * i + 1]));
132   }
133 
134   return;
135 }
136 
iusace_rounded_sqrt(UWORD32 pos_num)137 UWORD32 iusace_rounded_sqrt(UWORD32 pos_num) {
138   UWORD32 num = pos_num;
139   UWORD32 value = 0;
140   UWORD32 bit_set = 1 << 30;
141 
142   while (bit_set > num) {
143     bit_set >>= 2;
144   }
145   while (bit_set) {
146     if (num >= value + bit_set) {
147       num -= value + bit_set;
148       value += bit_set << 1;
149     }
150     value >>= 1;
151     bit_set >>= 2;
152   }
153   num = value + 1;
154   if (num * num - pos_num < pos_num - value * value) {
155     return num;
156   }
157   return value;
158 }
159 
iusace_noise_shaping(FLOAT32 * rr,WORD32 lg,WORD32 M,FLOAT32 * gain1,FLOAT32 * gain2)160 static VOID iusace_noise_shaping(FLOAT32 *rr, WORD32 lg, WORD32 M, FLOAT32 *gain1,
161                                  FLOAT32 *gain2) {
162   WORD32 i, k;
163   FLOAT32 r, r_prev, g1, g2, a = 0, b = 0;
164 
165   k = lg/M;
166 
167   r_prev = 0;
168   for (i = 0; i < lg; i++) {
169     if ((i % k) == 0) {
170       g1 = gain1[i / k];
171       g2 = gain2[i / k];
172       a = 2.0f * g1 * g2 / (g1 + g2);
173       b = (g2 - g1) / (g1 + g2);
174     }
175 
176     r = a * rr[i] + b * r_prev;
177 
178     rr[i] = r;
179     r_prev = r;
180   }
181 
182   return;
183 }
184 
iusace_pre_shaping(FLOAT32 * rr,WORD32 lg,WORD32 M,FLOAT32 * gain1,FLOAT32 * gain2)185 static VOID iusace_pre_shaping(FLOAT32 *rr, WORD32 lg, WORD32 M, FLOAT32 *gain1, FLOAT32 *gain2) {
186   WORD32 i, k;
187   FLOAT32 r, r_prev, g1, g2, a = 0, b = 0;
188 
189   k = lg / M;
190 
191   r_prev = 0;
192   for (i = 0; i < lg; i++) {
193     if ((i % k) == 0) {
194       g1 = gain1[i / k];
195       g2 = gain2[i / k];
196 
197       a = (g1 + g2) / (2.0f * g1 * g2);
198       b = (g1 - g2) / (2.0f * g1 * g2);
199     }
200 
201     r = a * rr[i] + b * r_prev;
202 
203     r_prev = rr[i];
204     rr[i] = r;
205   }
206 
207   return;
208 }
209 
iusace_adapt_lo_freq_emph(FLOAT32 * signal,WORD32 length)210 static VOID iusace_adapt_lo_freq_emph(FLOAT32 *signal, WORD32 length) {
211   WORD32 i, j, i_max;
212   FLOAT32 max_energy, factor, temp;
213 
214   i_max = length >> 2;
215 
216   max_energy = 0.01f;
217   for (i = 0; i < i_max; i += 8) {
218     temp = 0.01f;
219     for (j = i; j < i + 8; j++) {
220       temp += signal[j] * signal[j];
221     }
222     if (temp > max_energy) {
223       max_energy = temp;
224     }
225   }
226 
227   factor = 10.0f;
228   for (i = 0; i < i_max; i += 8) {
229     temp = 0.01f;
230     for (j = i; j < i + 8; j++) {
231       temp += signal[j] * signal[j];
232     }
233     temp = (FLOAT32)sqrt(sqrt(max_energy / temp));
234     if (temp < factor) {
235       factor = temp;
236     }
237     for (j = i; j < i + 8; j++) {
238       signal[j] *= factor;
239     }
240   }
241   return;
242 }
243 
iusace_adapt_lo_freq_deemph(FLOAT32 * signal,WORD32 length,FLOAT32 * gains)244 static VOID iusace_adapt_lo_freq_deemph(FLOAT32 *signal, WORD32 length, FLOAT32 *gains) {
245   WORD32 i, j, i_max;
246   FLOAT32 max_energy, factor, energy, rm;
247 
248   i_max = length >> 2;
249 
250   max_energy = 0.01f;
251   for (i = 0; i < i_max; i += 8) {
252     energy = 0.01f;
253     for (j = i; j < i + 8; j++) {
254       energy += signal[j] * signal[j];
255     }
256     if (energy > max_energy) {
257       max_energy = energy;
258     }
259   }
260 
261   factor = 0.1f;
262   for (i = 0; i < i_max; i += 8) {
263     energy = 0.01f;
264     for (j = i; j < i + 8; j++) {
265       energy += signal[j] * signal[j];
266     }
267 
268     rm = (FLOAT32)sqrt(energy / max_energy);
269     if (rm > factor) {
270       factor = rm;
271     }
272     for (j = i; j < i + 8; j++) {
273       signal[j] *= factor;
274     }
275     gains[i / 8] = factor;
276   }
277 
278   return;
279 }
280 
iusace_tcx_fac_encode(ia_usac_data_struct * usac_data,FLOAT32 * lpc_coeffs,FLOAT32 * lpc_coeffs_quant,FLOAT32 * speech,WORD32 frame_len,WORD32 num_bits_per_supfrm,ia_usac_lpd_state_struct * lpd_state,WORD32 * params,WORD32 * n_param,WORD32 ch_idx,WORD32 k_idx)281 VOID iusace_tcx_fac_encode(ia_usac_data_struct *usac_data, FLOAT32 *lpc_coeffs,
282                            FLOAT32 *lpc_coeffs_quant, FLOAT32 *speech, WORD32 frame_len,
283                            WORD32 num_bits_per_supfrm, ia_usac_lpd_state_struct *lpd_state,
284                            WORD32 *params, WORD32 *n_param, WORD32 ch_idx, WORD32 k_idx) {
285   ia_usac_td_encoder_struct *st = usac_data->td_encoder[ch_idx];
286   iusace_scratch_mem *pstr_scratch = &usac_data->str_scratch;
287   FLOAT32 *weighted_sig = &pstr_scratch->p_wsig_buf[k_idx * st->len_subfrm];
288   FLOAT32 *wsynth = pstr_scratch->p_wsyn_tcx_buf;
289   FLOAT32 *synth = pstr_scratch->p_synth_tcx_buf;
290   WORD32 i, k, n, mode, i_subfr, lg, lext, index, target_bits;
291   FLOAT32 tmp, gain, fac_ns, energy, gain_tcx, nsfill_en_thres;
292   FLOAT32 *ptr_lp_flt_coeffs, lp_flt_coeffs[ORDER + 1];
293   const FLOAT32 *sine_window_prev, *sine_window;
294   FLOAT32 mem_tcx_q;
295   FLOAT32 *xn;
296   FLOAT32 *xn1 = pstr_scratch->p_xn1_tcx;
297   FLOAT32 *xn_buf = pstr_scratch->p_xn_buf_tcx;
298   FLOAT32 *x = pstr_scratch->p_x_tcx;
299   FLOAT32 *x_tmp = pstr_scratch->p_x_tmp_tcx;
300   FLOAT32 *en = pstr_scratch->p_en_tcx;
301   FLOAT32 sq_gain;
302   FLOAT32 gain_prev, gain_next;
303   FLOAT32 *alfd_gains = pstr_scratch->p_alfd_gains_tcx;
304   FLOAT32 *sq_enc = pstr_scratch->p_sq_enc_tcx;
305   WORD32 *sq_quant = pstr_scratch->p_sq_quant_tcx;
306   FLOAT32 sq_err_energy;
307   WORD32 max_k;
308   FLOAT32 *gain1 = pstr_scratch->p_gain1_tcx;
309   FLOAT32 *gain2 = pstr_scratch->p_gain2_tcx;
310   FLOAT32 *facelp = pstr_scratch->p_facelp_tcx;
311   FLOAT32 *xn2 = pstr_scratch->p_xn2_tcx;
312   FLOAT32 *fac_window = pstr_scratch->p_fac_window_tcx;
313   FLOAT32 *x1 = pstr_scratch->p_x1_tcx;
314   FLOAT32 *x2 = pstr_scratch->p_x2_tcx;
315   WORD32 *y = pstr_scratch->p_y_tcx;
316 
317   WORD32 TTT;
318   FLOAT32 corr = 0;
319   WORD32 len_subfrm = st->len_subfrm;
320   WORD32 fac_length = len_subfrm >> 1;
321   WORD32 fac_len_prev, fac_len;
322 
323   if (frame_len == 4 * st->len_subfrm) {
324     if (st->last_was_short) {
325       fac_len_prev = (st->len_frame) / 16;
326     } else {
327       fac_len_prev = st->len_subfrm / 2;
328     }
329     if (st->next_is_short) {
330       fac_len = (st->len_frame) / 16;
331     } else {
332       fac_len = st->len_subfrm / 2;
333     }
334   } else if (frame_len == 2 * st->len_subfrm) {
335     if (k_idx == 0 && st->last_was_short) {
336       fac_len_prev = (st->len_frame) / 16;
337     } else {
338       fac_len_prev = st->len_subfrm / 2;
339     }
340     if (k_idx == 2 && st->next_is_short) {
341       fac_len = (st->len_frame) / 16;
342     } else {
343       fac_len = st->len_subfrm / 2;
344     }
345   } else {
346     if (k_idx == 0 && st->last_was_short) {
347       fac_len_prev = (st->len_frame) / 16;
348     } else {
349       fac_len_prev = st->len_subfrm / 2;
350     }
351     if (k_idx == 3 && st->next_is_short) {
352       fac_len = (st->len_frame) / 16;
353     } else {
354       fac_len = st->len_subfrm / 2;
355     }
356   }
357 
358   memset(xn_buf, 0, (128 + frame_len + 128) * sizeof(FLOAT32));
359 
360   mode = frame_len / len_subfrm;
361 
362   if (mode > 2) {
363     mode = 3;
364   }
365 
366   if (lpd_state->mode == 0) {
367     params += fac_len_prev;
368   }
369   switch (fac_len_prev) {
370     case 64:
371       sine_window_prev = iusace_sin_window_128;
372       break;
373     default:
374       sine_window_prev = iusace_sin_window_256;
375       break;
376   }
377   switch (fac_len) {
378     case 64:
379       sine_window = iusace_sin_window_128;
380       break;
381     default:
382       sine_window = iusace_sin_window_256;
383       break;
384   }
385 
386   lg = frame_len;
387   lext = fac_length;
388   xn = xn_buf + fac_length;
389 
390   *n_param = lg;
391 
392   target_bits = num_bits_per_supfrm - 10;
393 
394   for (i = 0; i < fac_length; i++) {
395     xn_buf[i] = lpd_state->tcx_mem[i + 128 - fac_length];
396   }
397 
398   memcpy(xn, speech, (frame_len + fac_length) * sizeof(FLOAT32));
399 
400   tmp = xn[-1];
401 
402   iusace_apply_deemph(xn, TILT_FAC, frame_len, &tmp);
403 
404   memcpy(lpd_state->tcx_mem, &xn[frame_len - 128], 128 * sizeof(FLOAT32));
405 
406   memcpy(&xn[frame_len], &speech[frame_len], lext * sizeof(FLOAT32));
407   iusace_apply_deemph(&xn[frame_len], TILT_FAC, lext, &tmp);
408 
409   for (i = 0; i < ORDER + fac_len_prev; i++) {
410     xn1[i] = xn_buf[fac_length - ORDER + i];
411   }
412   for (i = 0; i < ORDER + fac_len; i++) {
413     xn2[i] = xn_buf[frame_len - ORDER + i];
414   }
415 
416   if (lpd_state->mode >= -1) {
417     for (i = 0; i < fac_length - fac_len_prev; i++) {
418       xn_buf[i] = 0.0f;
419     }
420     for (i = fac_length - fac_len_prev; i < (fac_length + fac_len_prev); i++) {
421       xn_buf[i] *= sine_window_prev[i - fac_length + fac_len_prev];
422     }
423     for (i = 0; i < (2 * fac_len); i++) {
424       xn_buf[frame_len + fac_length - fac_len + i] *= sine_window[(2 * fac_len) - 1 - i];
425     }
426     for (i = 0; i < fac_length - fac_len; i++) {
427       xn_buf[frame_len + fac_length + fac_len + i] = 0.0f;
428     }
429   }
430 
431   iusace_tcx_mdct_main(xn_buf, x, (2 * fac_length), frame_len - (2 * fac_length),
432                        (2 * fac_length), pstr_scratch);
433 
434   iusace_get_weighted_lpc(lpc_coeffs_quant + (ORDER + 1), lp_flt_coeffs);
435   iusace_lpc_mdct(lp_flt_coeffs, gain1, ((FDNS_RESOLUTION * len_subfrm) / LEN_FRAME) << 1,
436                   pstr_scratch);
437 
438   iusace_get_weighted_lpc(lpc_coeffs_quant + (2 * (ORDER + 1)), lp_flt_coeffs);
439   iusace_lpc_mdct(lp_flt_coeffs, gain2, ((FDNS_RESOLUTION * len_subfrm) / LEN_FRAME) << 1,
440                   pstr_scratch);
441 
442   iusace_pre_shaping(x, lg, ((FDNS_RESOLUTION * len_subfrm) / LEN_FRAME), gain1, gain2);
443 
444   for (i = 0; i < lg; i++) {
445     x_tmp[i] = x[i];
446   }
447 
448   iusace_adapt_lo_freq_emph(x, lg);
449 
450   sq_gain = iusace_calc_sq_gain(x, target_bits, lg, pstr_scratch->p_sq_gain_en);
451 
452   for (i = 0; i < lg; i++) {
453     sq_enc[i] = x[i] / sq_gain;
454 
455     if (sq_enc[i] > 0.f)
456       sq_quant[i] = ((WORD32)(0.5f + sq_enc[i]));
457     else
458       sq_quant[i] = ((WORD32)(-0.5f + sq_enc[i]));
459   }
460 
461   for (i = 0; i < lg; i++) {
462     params[i + 2] = sq_quant[i];
463     x[i] = (FLOAT32)sq_quant[i];
464   }
465 
466   for (i = 0; i < lg; i++) {
467     en[i] = x[i] * x[i];
468   }
469   if (mode == 3) {
470     tmp = 0.9441f;
471   } else if (mode == 2) {
472     tmp = 0.8913f;
473   } else {
474     tmp = 0.7943f;
475   }
476   energy = 0.0f;
477   for (i = 0; i < lg; i++) {
478     if (en[i] > energy) {
479       energy = en[i];
480     }
481     en[i] = energy;
482     energy *= tmp;
483   }
484   energy = 0.0f;
485   for (i = lg - 1; i >= 0; i--) {
486     if (en[i] > energy) {
487       energy = en[i];
488     }
489     en[i] = energy;
490     energy *= tmp;
491   }
492 
493   nsfill_en_thres = 0.707f;
494 
495   tmp = 0.0625f;
496   k = 1;
497   for (i = 0; i < lg; i++) {
498     if (en[i] <= nsfill_en_thres) {
499       tmp += sq_enc[i] * sq_enc[i];
500       k++;
501     }
502   }
503 
504   iusace_adapt_lo_freq_deemph(x, lg, alfd_gains);
505 
506   energy = 1e-6f;
507   for (i = 0; i < lg; i++) {
508     corr += x_tmp[i] * x[i];
509     energy += x[i] * x[i];
510   }
511   gain_tcx = (corr / energy);
512 
513   if (gain_tcx == 0.0f) {
514     gain_tcx = sq_gain;
515   }
516 
517   energy = 0.0001f;
518   for (i = 0; i < lg; i++) {
519     tmp = x_tmp[i] - gain_tcx * x[i];
520     energy += tmp * tmp;
521   }
522 
523   tmp = (FLOAT32)sqrt((energy * (2.0f / (FLOAT32)lg)) / (FLOAT32)lg);
524 
525   for (i = 0; i < frame_len; i++) {
526     wsynth[i] = weighted_sig[i] + tmp;
527   }
528 
529   energy = 0.01f;
530   for (i = 0; i < lg; i++) {
531     energy += x[i] * x[i];
532   }
533 
534   tmp = (FLOAT32)(2.0f * sqrt(energy) / (FLOAT32)lg);
535   gain = gain_tcx * tmp;
536 
537   index = (WORD32)floor(0.5f + (28.0f * (FLOAT32)log10(gain)));
538   if (index < 0) {
539     index = 0;
540   }
541   if (index > 127) {
542     index = 127;
543   }
544   params[1] = index;
545 
546   gain_tcx = (FLOAT32)pow(10.0f, ((FLOAT32)index) / 28.0f) / tmp;
547   st->gain_tcx = gain_tcx;
548 
549   sq_err_energy = 0.f;
550   n = 0;
551   for (k = lg / 2; k < lg;) {
552     tmp = 0.f;
553 
554     max_k = MIN(lg, k + 8);
555     for (i = k; i < max_k; i++) {
556       tmp += (FLOAT32)sq_quant[i] * sq_quant[i];
557     }
558     if (tmp == 0.f) {
559       tmp = 0.f;
560       for (i = k; i < max_k; i++) {
561         tmp += sq_enc[i] * sq_enc[i];
562       }
563 
564       sq_err_energy += (FLOAT32)log10((tmp / (FLOAT64)8) + 0.000000001);
565       n += 1;
566     }
567     k = max_k;
568   }
569   if (n > 0) {
570     fac_ns = (FLOAT32)pow(10., sq_err_energy / (FLOAT64)(2 * n));
571   } else {
572     fac_ns = 0.f;
573   }
574 
575   tmp = 8.0f - (16.0f * fac_ns);
576 
577   index = (WORD32)floor(tmp + 0.5);
578   if (index < 0) {
579     index = 0;
580   }
581   if (index > 7) {
582     index = 7;
583   }
584 
585   params[0] = index;
586 
587   iusace_noise_shaping(x, lg, ((FDNS_RESOLUTION * len_subfrm) / LEN_FRAME), gain1, gain2);
588 
589   iusace_tcx_imdct(x, xn_buf, (2 * fac_length), frame_len - (2 * fac_length), (2 * fac_length),
590                    pstr_scratch);
591   for (i = 0; i < frame_len + (2 * fac_length); i++) {
592     xn_buf[i] = xn_buf[i] * (2.0f / lg);
593   }
594 
595   for (i = 0; i < fac_len_prev; i++) {
596     fac_window[i] = sine_window_prev[i] * sine_window_prev[(2 * fac_len_prev) - 1 - i];
597     fac_window[fac_len_prev + i] =
598         1.0f - (sine_window_prev[fac_len_prev + i] * sine_window_prev[fac_len_prev + i]);
599   }
600 
601   for (i = 0; i < fac_len_prev; i++) {
602     xn1[ORDER + i] -= sq_gain * xn_buf[fac_length + i] * sine_window_prev[fac_len_prev + i];
603   }
604   for (i = 0; i < fac_len; i++) {
605     xn2[ORDER + i] -= sq_gain * xn_buf[i + frame_len] * sine_window[(2 * fac_len) - 1 - i];
606   }
607 
608   for (i = 0; i < ORDER; i++) {
609     xn1[i] -= lpd_state->tcx_quant[1 + 128 - ORDER + i];
610     xn2[i] -= sq_gain * xn_buf[frame_len - ORDER + i];
611   }
612 
613   for (i = 0; i < fac_len_prev; i++) {
614     facelp[i] = lpd_state->tcx_quant[1 + 128 + i] * fac_window[fac_len_prev + i] +
615                 lpd_state->tcx_quant[1 + 128 - 1 - i] * fac_window[fac_len_prev - 1 - i];
616   }
617 
618   energy = 0.0f;
619   for (i = 0; i < fac_len_prev; i++) energy += xn1[ORDER + i] * xn1[ORDER + i];
620   energy *= 2.0f;
621   tmp = 0.0f;
622   for (i = 0; i < fac_len_prev; i++) tmp += facelp[i] * facelp[i];
623   if (tmp > energy)
624     gain = (FLOAT32)sqrt(energy / tmp);
625   else
626     gain = 1.0f;
627 
628   for (i = 0; i < fac_len_prev; i++) {
629     xn1[ORDER + i] -= gain * facelp[i];
630   }
631 
632   iusace_get_weighted_lpc(lpc_coeffs_quant + (ORDER + 1), lp_flt_coeffs);
633   iusace_compute_lp_residual(lp_flt_coeffs, xn1 + ORDER, x1, fac_len_prev);
634 
635   iusace_get_weighted_lpc(lpc_coeffs_quant + (2 * (ORDER + 1)), lp_flt_coeffs);
636   iusace_compute_lp_residual(lp_flt_coeffs, xn2 + ORDER, x2, fac_len);
637 
638   iusace_tcx_mdct(x1, x1, fac_len_prev, pstr_scratch);
639   iusace_tcx_mdct(x2, x2, fac_len, pstr_scratch);
640 
641   gain_prev = (FLOAT32)(sq_gain * 0.5f * sqrt(((FLOAT32)fac_len_prev) / (FLOAT32)frame_len));
642   gain_next = (FLOAT32)(sq_gain * 0.5f * sqrt(((FLOAT32)fac_len) / (FLOAT32)frame_len));
643 
644   for (i = 0; i < fac_len_prev; i++) {
645     x1[i] /= gain_prev;
646   }
647   for (i = 0; i < fac_len; i++) {
648     x2[i] /= gain_next;
649   }
650   for (i = 0; i < fac_len_prev / 4; i++) {
651     k = i * lg / (8 * fac_len_prev);
652     x1[i] /= alfd_gains[k];
653   }
654   for (i = 0; i < fac_len / 4; i++) {
655     k = i * lg / (8 * fac_len);
656     x2[i] /= alfd_gains[k];
657   }
658 
659   for (i = 0; i < fac_len; i += 8) {
660     iusace_find_nearest_neighbor(&x2[i], &y[i]);
661   }
662   for (i = 0; i < fac_len; i++) {
663     lpd_state->avq_params[i] = y[i];
664     x2[i] = (FLOAT32)y[i];
665   }
666 
667   for (i = 0; i < fac_len_prev; i += 8) {
668     iusace_find_nearest_neighbor(&x1[i], &y[i]);
669   }
670 
671   for (i = 0; i < fac_len_prev; i++) {
672     x1[i] = (FLOAT32)y[i];
673   }
674 
675   gain_prev = (FLOAT32)(gain_tcx * 0.5f * sqrt(((FLOAT32)fac_len_prev) / (FLOAT32)frame_len));
676   gain_next = (FLOAT32)(gain_tcx * 0.5f * sqrt(((FLOAT32)fac_len) / (FLOAT32)frame_len));
677 
678   for (i = 0; i < fac_len_prev; i++) {
679     x1[i] *= gain_prev;
680   }
681   for (i = 0; i < fac_len; i++) {
682     x2[i] *= gain_next;
683   }
684   for (i = 0; i<fac_len_prev>> 2; i++) {
685     k = i * lg / (fac_len_prev << 3);
686     x1[i] *= alfd_gains[k];
687   }
688   for (i = 0; i<fac_len>> 2; i++) {
689     k = i * lg / (fac_len << 3);
690     x2[i] *= alfd_gains[k];
691   }
692   iusace_tcx_mdct(x1, xn1, fac_len_prev, pstr_scratch);
693   iusace_tcx_mdct(x2, xn2, fac_len, pstr_scratch);
694 
695   FLOAT32 coeff1 = (2.0f / (FLOAT32)fac_len_prev), coeff2 = (2.0f / (FLOAT32)fac_len);
696 
697   for (i = 0; i < fac_len_prev; i++) {
698     xn1[i] = xn1[i] * coeff1;
699   }
700 
701   for (i = 0; i < fac_len; i++) {
702     xn2[i] = xn2[i] * coeff2;
703   }
704 
705   memset(xn1 + fac_len_prev, 0, fac_len_prev * sizeof(FLOAT32));
706   memset(xn2 + fac_len, 0, fac_len * sizeof(FLOAT32));
707 
708   iusace_get_weighted_lpc(lpc_coeffs_quant + (ORDER + 1), lp_flt_coeffs);
709   iusace_synthesis_tool_float(lp_flt_coeffs, xn1, xn1, 2 * fac_len_prev, xn1 + fac_len_prev,
710                               pstr_scratch->p_buf_synthesis_tool);
711 
712   iusace_get_weighted_lpc(lpc_coeffs_quant + (2 * (ORDER + 1)), lp_flt_coeffs);
713   iusace_synthesis_tool_float(lp_flt_coeffs, xn2, xn2, fac_len, xn2 + fac_len,
714                               pstr_scratch->p_buf_synthesis_tool);
715 
716   for (i = 0; i < fac_len_prev; i++) {
717     xn1[i] += facelp[i];
718   }
719 
720   for (i = 0; i < frame_len + (fac_length << 1); i++) {
721     xn_buf[i] *= gain_tcx;
722   }
723 
724   if (lpd_state->mode >= -1) {
725     for (i = 0; i < (2 * fac_len_prev); i++) {
726       xn_buf[i + fac_length - fac_len_prev] *= sine_window_prev[i];
727     }
728     for (i = 0; i < fac_length - fac_len_prev; i++) {
729       xn_buf[i] = 0.0f;
730     }
731   }
732   for (i = 0; i < (2 * fac_len); i++) {
733     xn_buf[i + frame_len + fac_length - fac_len] *= sine_window[(2 * fac_len) - 1 - i];
734   }
735   for (i = 0; i < fac_length - fac_len; i++) {
736     xn_buf[i + frame_len + fac_length + fac_len] = 0.0f;
737   }
738 
739   if (lpd_state->mode != 0) {
740     for (i = 0; i < (2 * fac_length); i++) {
741       xn_buf[i] += lpd_state->tcx_quant[1 + 128 - fac_length + i];
742     }
743 
744     mem_tcx_q = lpd_state->tcx_quant[128 - fac_length];
745   } else {
746     for (i = 0; i < fac_len_prev; i++) {
747       params[i - fac_len_prev] = y[i];
748     }
749 
750     for (i = 0; i < (2 * fac_len_prev); i++) {
751       xn_buf[i + fac_length] += xn1[i];
752     }
753     mem_tcx_q = lpd_state->tcx_quant[128];
754   }
755 
756   memcpy(lpd_state->tcx_quant, xn_buf + frame_len + fac_length - 128 - 1,
757          (1 + 256) * sizeof(FLOAT32));
758 
759   for (i = 0; i < fac_len; i++) {
760     xn_buf[i + frame_len + (fac_length - fac_len)] += xn2[i];
761   }
762 
763   if (lpd_state->mode > 0) {
764     iusace_apply_preemph(xn_buf, TILT_FAC, fac_length, &mem_tcx_q);
765 
766     ptr_lp_flt_coeffs = lpd_state->lpc_coeffs_quant;
767 
768     TTT = fac_length % LEN_SUBFR;
769     if (TTT != 0) {
770       memcpy(&(lpd_state->synth[ORDER + 128 - fac_length]), &xn_buf[0], TTT * sizeof(FLOAT32));
771       iusace_compute_lp_residual(ptr_lp_flt_coeffs, &(lpd_state->synth[ORDER + 128 - fac_length]),
772                                  &(lpd_state->acelp_exc[(2 * len_subfrm) - fac_length]), TTT);
773 
774       ptr_lp_flt_coeffs += (ORDER + 1);
775     }
776 
777     for (i_subfr = TTT; i_subfr < fac_length; i_subfr += LEN_SUBFR) {
778       memcpy(&(lpd_state->synth[ORDER + 128 - fac_length + i_subfr]), &xn_buf[i_subfr],
779              LEN_SUBFR * sizeof(FLOAT32));
780       iusace_compute_lp_residual(
781           ptr_lp_flt_coeffs, &(lpd_state->synth[ORDER + 128 - fac_length + i_subfr]),
782           &(lpd_state->acelp_exc[(2 * len_subfrm) - fac_length + i_subfr]), LEN_SUBFR);
783       ptr_lp_flt_coeffs += (ORDER + 1);
784     }
785 
786     ptr_lp_flt_coeffs = lpd_state->lpc_coeffs;
787     for (i_subfr = 0; i_subfr < fac_length; i_subfr += LEN_SUBFR) {
788       iusace_get_weighted_lpc(ptr_lp_flt_coeffs, lp_flt_coeffs);
789       iusace_compute_lp_residual(lp_flt_coeffs,
790                                  &(lpd_state->synth[ORDER + 128 - fac_length + i_subfr]),
791                                  &(lpd_state->wsynth[1 + 128 - fac_length + i_subfr]), LEN_SUBFR);
792       ptr_lp_flt_coeffs += (ORDER + 1);
793     }
794     tmp = lpd_state->wsynth[0 + 128 - fac_length];
795     iusace_apply_deemph(&(lpd_state->wsynth[1 + 128 - fac_length]), TILT_FAC, fac_length, &tmp);
796   }
797 
798   k = ((frame_len / LEN_SUBFR) - 2) * (ORDER + 1);
799   memcpy(lpd_state->lpc_coeffs, lpc_coeffs + k, 2 * (ORDER + 1) * sizeof(FLOAT32));
800 
801   memcpy(lpd_state->lpc_coeffs_quant, lpc_coeffs_quant + (2 * (ORDER + 1)),
802          (ORDER + 1) * sizeof(FLOAT32));
803   memcpy(lpd_state->lpc_coeffs_quant + (ORDER + 1), lpd_state->lpc_coeffs_quant,
804          (ORDER + 1) * sizeof(FLOAT32));
805 
806   memcpy(synth - 128, &(lpd_state->synth[ORDER]), 128 * sizeof(FLOAT32));
807   lpd_state->tcx_fac = xn[frame_len - 1];
808 
809   iusace_apply_preemph(xn, TILT_FAC, frame_len, &mem_tcx_q);
810   for (i_subfr = 0; i_subfr < frame_len; i_subfr += LEN_SUBFR) {
811     memcpy(&synth[i_subfr], &xn[i_subfr], LEN_SUBFR * sizeof(FLOAT32));
812     iusace_compute_lp_residual(lpc_coeffs_quant + (2 * (ORDER + 1)), &synth[i_subfr],
813                                &xn[i_subfr], LEN_SUBFR);
814   }
815   memcpy(lpd_state->synth, synth + frame_len - (ORDER + 128), (ORDER + 128) * sizeof(FLOAT32));
816 
817   if (frame_len == len_subfrm) {
818     memcpy(x, lpd_state->acelp_exc + len_subfrm, len_subfrm * sizeof(FLOAT32));
819     memcpy(lpd_state->acelp_exc, x, len_subfrm * sizeof(FLOAT32));
820     memcpy(lpd_state->acelp_exc + len_subfrm, xn, len_subfrm * sizeof(FLOAT32));
821   } else {
822     memcpy(lpd_state->acelp_exc, xn + frame_len - (2 * len_subfrm),
823            2 * len_subfrm * sizeof(FLOAT32));
824   }
825 
826   memcpy(wsynth - 128, &(lpd_state->wsynth[1]), 128 * sizeof(FLOAT32));
827 
828   ptr_lp_flt_coeffs = lpc_coeffs;
829   for (i_subfr = 0; i_subfr < frame_len; i_subfr += LEN_SUBFR) {
830     iusace_get_weighted_lpc(ptr_lp_flt_coeffs, lp_flt_coeffs);
831     iusace_compute_lp_residual(lp_flt_coeffs, &synth[i_subfr], &wsynth[i_subfr], LEN_SUBFR);
832     ptr_lp_flt_coeffs += (ORDER + 1);
833   }
834   tmp = wsynth[-1];
835   iusace_apply_deemph(wsynth, TILT_FAC, frame_len, &tmp);
836 
837   memcpy(lpd_state->wsynth, wsynth + frame_len - (1 + 128), (1 + 128) * sizeof(FLOAT32));
838 
839   lpd_state->mode = mode;
840 
841   lpd_state->num_bits = 10 + target_bits;
842 
843   return;
844 }
845