xref: /aosp_15_r20/external/libxaac/encoder/iusace_acelp_enc.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1*15dc779aSAndroid Build Coastguard Worker /******************************************************************************
2*15dc779aSAndroid Build Coastguard Worker  *                                                                            *
3*15dc779aSAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
4*15dc779aSAndroid Build Coastguard Worker  *
5*15dc779aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*15dc779aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*15dc779aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at:
8*15dc779aSAndroid Build Coastguard Worker  *
9*15dc779aSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
10*15dc779aSAndroid Build Coastguard Worker  *
11*15dc779aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*15dc779aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*15dc779aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*15dc779aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*15dc779aSAndroid Build Coastguard Worker  * limitations under the License.
16*15dc779aSAndroid Build Coastguard Worker  *
17*15dc779aSAndroid Build Coastguard Worker  *****************************************************************************
18*15dc779aSAndroid Build Coastguard Worker  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*15dc779aSAndroid Build Coastguard Worker  */
20*15dc779aSAndroid Build Coastguard Worker 
21*15dc779aSAndroid Build Coastguard Worker #include <string.h>
22*15dc779aSAndroid Build Coastguard Worker #include <math.h>
23*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_type_def.h"
24*15dc779aSAndroid Build Coastguard Worker #include "iusace_bitbuffer.h"
25*15dc779aSAndroid Build Coastguard Worker 
26*15dc779aSAndroid Build Coastguard Worker /* DRC */
27*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_common_enc.h"
28*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc.h"
29*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_tables.h"
30*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_api.h"
31*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc_eq.h"
32*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc_filter_bank.h"
33*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_gain_enc.h"
34*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_struct_def.h"
35*15dc779aSAndroid Build Coastguard Worker 
36*15dc779aSAndroid Build Coastguard Worker #include "iusace_cnst.h"
37*15dc779aSAndroid Build Coastguard Worker #include "iusace_tns_usac.h"
38*15dc779aSAndroid Build Coastguard Worker #include "iusace_psy_mod.h"
39*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_adjust_threshold_data.h"
40*15dc779aSAndroid Build Coastguard Worker #include "iusace_fd_qc_util.h"
41*15dc779aSAndroid Build Coastguard Worker #include "iusace_config.h"
42*15dc779aSAndroid Build Coastguard Worker #include "iusace_arith_enc.h"
43*15dc779aSAndroid Build Coastguard Worker #include "iusace_block_switch_const.h"
44*15dc779aSAndroid Build Coastguard Worker #include "iusace_block_switch_struct_def.h"
45*15dc779aSAndroid Build Coastguard Worker #include "iusace_lpd_rom.h"
46*15dc779aSAndroid Build Coastguard Worker #include "iusace_lpd.h"
47*15dc779aSAndroid Build Coastguard Worker 
iusace_acelp_encode(FLOAT32 * lp_filt_coeff,FLOAT32 * quant_lp_filt_coeff,FLOAT32 * speech_in,FLOAT32 * wsig_in,FLOAT32 * synth_out,FLOAT32 * wsynth_out,WORD16 acelp_core_mode,ia_usac_lpd_state_struct * lpd_state,WORD32 len_subfrm,FLOAT32 norm_corr,FLOAT32 norm_corr2,WORD32 ol_pitch_lag1,WORD32 ol_pitch_lag2,WORD32 pit_adj,WORD32 * acelp_params,iusace_scratch_mem * pstr_scratch)48*15dc779aSAndroid Build Coastguard Worker VOID iusace_acelp_encode(FLOAT32 *lp_filt_coeff, FLOAT32 *quant_lp_filt_coeff, FLOAT32 *speech_in,
49*15dc779aSAndroid Build Coastguard Worker                          FLOAT32 *wsig_in, FLOAT32 *synth_out, FLOAT32 *wsynth_out,
50*15dc779aSAndroid Build Coastguard Worker                          WORD16 acelp_core_mode, ia_usac_lpd_state_struct *lpd_state,
51*15dc779aSAndroid Build Coastguard Worker                          WORD32 len_subfrm, FLOAT32 norm_corr, FLOAT32 norm_corr2,
52*15dc779aSAndroid Build Coastguard Worker                          WORD32 ol_pitch_lag1, WORD32 ol_pitch_lag2, WORD32 pit_adj,
53*15dc779aSAndroid Build Coastguard Worker                          WORD32 *acelp_params, iusace_scratch_mem *pstr_scratch) {
54*15dc779aSAndroid Build Coastguard Worker   WORD32 i, i_subfr, num_bits, t;
55*15dc779aSAndroid Build Coastguard Worker   WORD32 t0, t0_min, t0_max, index, subfrm_flag;
56*15dc779aSAndroid Build Coastguard Worker   WORD32 t0_frac;
57*15dc779aSAndroid Build Coastguard Worker   FLOAT32 temp, energy, max_ener, mean_ener_code;
58*15dc779aSAndroid Build Coastguard Worker   FLOAT32 pitch_gain, code_gain, gain1, gain2;
59*15dc779aSAndroid Build Coastguard Worker   FLOAT32 tgt_cb_corr[5], tgt_cb_corr2[2];
60*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *p_lp_filt_coeff, *p_quant_lp_filt_coeff, weighted_lpc[ORDER + 1];
61*15dc779aSAndroid Build Coastguard Worker   FLOAT32 imp_res[LEN_SUBFR];
62*15dc779aSAndroid Build Coastguard Worker   FLOAT32 code[LEN_SUBFR];
63*15dc779aSAndroid Build Coastguard Worker   WORD16 cb_exc[LEN_SUBFR];
64*15dc779aSAndroid Build Coastguard Worker   FLOAT32 error[ORDER + LEN_SUBFR + 8];
65*15dc779aSAndroid Build Coastguard Worker   FLOAT32 cn[LEN_SUBFR];
66*15dc779aSAndroid Build Coastguard Worker   FLOAT32 xn[LEN_SUBFR];
67*15dc779aSAndroid Build Coastguard Worker   FLOAT32 xn2[LEN_SUBFR];
68*15dc779aSAndroid Build Coastguard Worker   FLOAT32 dn[LEN_SUBFR];
69*15dc779aSAndroid Build Coastguard Worker   FLOAT32 y0[LEN_SUBFR];
70*15dc779aSAndroid Build Coastguard Worker   FLOAT32 y1[LEN_SUBFR];
71*15dc779aSAndroid Build Coastguard Worker   FLOAT32 y2[LEN_SUBFR];
72*15dc779aSAndroid Build Coastguard Worker   WORD32 min_pitch_lag_res1_4;
73*15dc779aSAndroid Build Coastguard Worker   WORD32 min_pitch_lag_res1_2;
74*15dc779aSAndroid Build Coastguard Worker   WORD32 min_pitch_lag_res1;
75*15dc779aSAndroid Build Coastguard Worker   WORD32 max_pitch_lag;
76*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *exc_buf = pstr_scratch->p_acelp_exc_buf;
77*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *exc;
78*15dc779aSAndroid Build Coastguard Worker   FLOAT32 mem_txn, mem_txnq;
79*15dc779aSAndroid Build Coastguard Worker   WORD32 fac_length = len_subfrm / 2;
80*15dc779aSAndroid Build Coastguard Worker   if (lpd_state->mode > 0) {
81*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < fac_length; i++) {
82*15dc779aSAndroid Build Coastguard Worker       acelp_params[i] = lpd_state->avq_params[i];
83*15dc779aSAndroid Build Coastguard Worker     }
84*15dc779aSAndroid Build Coastguard Worker     acelp_params += fac_length;
85*15dc779aSAndroid Build Coastguard Worker   }
86*15dc779aSAndroid Build Coastguard Worker 
87*15dc779aSAndroid Build Coastguard Worker   if (pit_adj == SR_MAX)
88*15dc779aSAndroid Build Coastguard Worker     exc = exc_buf + (2 * len_subfrm) + 41;
89*15dc779aSAndroid Build Coastguard Worker   else
90*15dc779aSAndroid Build Coastguard Worker     exc = exc_buf + (2 * len_subfrm);
91*15dc779aSAndroid Build Coastguard Worker 
92*15dc779aSAndroid Build Coastguard Worker   memset(exc_buf, 0, (2 * len_subfrm) * sizeof(exc_buf[0]));
93*15dc779aSAndroid Build Coastguard Worker   memcpy(exc_buf, lpd_state->acelp_exc, 2 * len_subfrm * sizeof(FLOAT32));
94*15dc779aSAndroid Build Coastguard Worker   memcpy(synth_out - 128, &(lpd_state->synth[ORDER]), 128 * sizeof(FLOAT32));
95*15dc779aSAndroid Build Coastguard Worker   memcpy(wsynth_out - 128, &(lpd_state->wsynth[1]), 128 * sizeof(FLOAT32));
96*15dc779aSAndroid Build Coastguard Worker 
97*15dc779aSAndroid Build Coastguard Worker   num_bits = ((iusace_acelp_core_numbits_1024[acelp_core_mode] - NBITS_MODE) / 4) - NBITS_LPC;
98*15dc779aSAndroid Build Coastguard Worker 
99*15dc779aSAndroid Build Coastguard Worker   if (pit_adj == 0) {
100*15dc779aSAndroid Build Coastguard Worker     min_pitch_lag_res1_4 = TMIN;
101*15dc779aSAndroid Build Coastguard Worker     min_pitch_lag_res1_2 = TFR2;
102*15dc779aSAndroid Build Coastguard Worker     min_pitch_lag_res1 = TFR1;
103*15dc779aSAndroid Build Coastguard Worker     max_pitch_lag = TMAX;
104*15dc779aSAndroid Build Coastguard Worker   } else {
105*15dc779aSAndroid Build Coastguard Worker     i = (((pit_adj * TMIN) + (FSCALE_DENOM / 2)) / FSCALE_DENOM) - TMIN;
106*15dc779aSAndroid Build Coastguard Worker     min_pitch_lag_res1_4 = TMIN + i;
107*15dc779aSAndroid Build Coastguard Worker     min_pitch_lag_res1_2 = TFR2 - i;
108*15dc779aSAndroid Build Coastguard Worker     min_pitch_lag_res1 = TFR1;
109*15dc779aSAndroid Build Coastguard Worker     max_pitch_lag = TMAX + (6 * i);
110*15dc779aSAndroid Build Coastguard Worker   }
111*15dc779aSAndroid Build Coastguard Worker 
112*15dc779aSAndroid Build Coastguard Worker   ol_pitch_lag1 *= OPL_DECIM;
113*15dc779aSAndroid Build Coastguard Worker   ol_pitch_lag2 *= OPL_DECIM;
114*15dc779aSAndroid Build Coastguard Worker 
115*15dc779aSAndroid Build Coastguard Worker   t0_min = ol_pitch_lag1 - 8;
116*15dc779aSAndroid Build Coastguard Worker 
117*15dc779aSAndroid Build Coastguard Worker   t = MIN(ol_pitch_lag1, ol_pitch_lag2) - 4;
118*15dc779aSAndroid Build Coastguard Worker   if (t0_min < t) t0_min = t;
119*15dc779aSAndroid Build Coastguard Worker 
120*15dc779aSAndroid Build Coastguard Worker   if (t0_min < min_pitch_lag_res1_4) {
121*15dc779aSAndroid Build Coastguard Worker     t0_min = min_pitch_lag_res1_4;
122*15dc779aSAndroid Build Coastguard Worker   }
123*15dc779aSAndroid Build Coastguard Worker   t0_max = t0_min + 15;
124*15dc779aSAndroid Build Coastguard Worker   t = MAX(ol_pitch_lag1, ol_pitch_lag2) + 4;
125*15dc779aSAndroid Build Coastguard Worker   if (t0_max > t) t0_max = t;
126*15dc779aSAndroid Build Coastguard Worker 
127*15dc779aSAndroid Build Coastguard Worker   if (t0_max > max_pitch_lag) {
128*15dc779aSAndroid Build Coastguard Worker     t0_max = max_pitch_lag;
129*15dc779aSAndroid Build Coastguard Worker     t0_min = t0_max - 15;
130*15dc779aSAndroid Build Coastguard Worker   }
131*15dc779aSAndroid Build Coastguard Worker 
132*15dc779aSAndroid Build Coastguard Worker   max_ener = 0.0;
133*15dc779aSAndroid Build Coastguard Worker   mean_ener_code = 0.0;
134*15dc779aSAndroid Build Coastguard Worker   p_quant_lp_filt_coeff = quant_lp_filt_coeff;
135*15dc779aSAndroid Build Coastguard Worker   for (i_subfr = 0; i_subfr < len_subfrm; i_subfr += LEN_SUBFR) {
136*15dc779aSAndroid Build Coastguard Worker     iusace_compute_lp_residual(p_quant_lp_filt_coeff, &speech_in[i_subfr], &exc[i_subfr],
137*15dc779aSAndroid Build Coastguard Worker                                LEN_SUBFR);
138*15dc779aSAndroid Build Coastguard Worker     energy = 0.01f;
139*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
140*15dc779aSAndroid Build Coastguard Worker       energy += exc[i + i_subfr] * exc[i + i_subfr];
141*15dc779aSAndroid Build Coastguard Worker     }
142*15dc779aSAndroid Build Coastguard Worker     energy = 10.0f * (FLOAT32)log10(energy / ((FLOAT32)LEN_SUBFR));
143*15dc779aSAndroid Build Coastguard Worker     if (energy < 0.0) {
144*15dc779aSAndroid Build Coastguard Worker       energy = 0.0;
145*15dc779aSAndroid Build Coastguard Worker     }
146*15dc779aSAndroid Build Coastguard Worker     if (energy > max_ener) {
147*15dc779aSAndroid Build Coastguard Worker       max_ener = energy;
148*15dc779aSAndroid Build Coastguard Worker     }
149*15dc779aSAndroid Build Coastguard Worker     mean_ener_code += 0.25f * energy;
150*15dc779aSAndroid Build Coastguard Worker     p_quant_lp_filt_coeff += (ORDER + 1);
151*15dc779aSAndroid Build Coastguard Worker   }
152*15dc779aSAndroid Build Coastguard Worker 
153*15dc779aSAndroid Build Coastguard Worker   mean_ener_code -= 5.0f * norm_corr;
154*15dc779aSAndroid Build Coastguard Worker   mean_ener_code -= 5.0f * norm_corr2;
155*15dc779aSAndroid Build Coastguard Worker 
156*15dc779aSAndroid Build Coastguard Worker   temp = (mean_ener_code - 18.0f) / 12.0f;
157*15dc779aSAndroid Build Coastguard Worker   index = (WORD32)floor(temp + 0.5);
158*15dc779aSAndroid Build Coastguard Worker   if (index < 0) {
159*15dc779aSAndroid Build Coastguard Worker     index = 0;
160*15dc779aSAndroid Build Coastguard Worker   }
161*15dc779aSAndroid Build Coastguard Worker   if (index > 3) {
162*15dc779aSAndroid Build Coastguard Worker     index = 3;
163*15dc779aSAndroid Build Coastguard Worker   }
164*15dc779aSAndroid Build Coastguard Worker   mean_ener_code = (((FLOAT32)index) * 12.0f) + 18.0f;
165*15dc779aSAndroid Build Coastguard Worker 
166*15dc779aSAndroid Build Coastguard Worker   while ((mean_ener_code < (max_ener - 27.0)) && (index < 3)) {
167*15dc779aSAndroid Build Coastguard Worker     index++;
168*15dc779aSAndroid Build Coastguard Worker     mean_ener_code += 12.0;
169*15dc779aSAndroid Build Coastguard Worker   }
170*15dc779aSAndroid Build Coastguard Worker   *acelp_params = index;
171*15dc779aSAndroid Build Coastguard Worker   acelp_params++;
172*15dc779aSAndroid Build Coastguard Worker 
173*15dc779aSAndroid Build Coastguard Worker   p_lp_filt_coeff = lp_filt_coeff;
174*15dc779aSAndroid Build Coastguard Worker   p_quant_lp_filt_coeff = quant_lp_filt_coeff;
175*15dc779aSAndroid Build Coastguard Worker   for (i_subfr = 0; i_subfr < len_subfrm; i_subfr += LEN_SUBFR) {
176*15dc779aSAndroid Build Coastguard Worker     subfrm_flag = i_subfr;
177*15dc779aSAndroid Build Coastguard Worker     if ((len_subfrm == 256) && (i_subfr == (2 * LEN_SUBFR))) {
178*15dc779aSAndroid Build Coastguard Worker       subfrm_flag = 0;
179*15dc779aSAndroid Build Coastguard Worker 
180*15dc779aSAndroid Build Coastguard Worker       t0_min = ol_pitch_lag2 - 8;
181*15dc779aSAndroid Build Coastguard Worker 
182*15dc779aSAndroid Build Coastguard Worker       t = MIN(ol_pitch_lag1, ol_pitch_lag2) - 4;
183*15dc779aSAndroid Build Coastguard Worker       if (t0_min < t) t0_min = t;
184*15dc779aSAndroid Build Coastguard Worker 
185*15dc779aSAndroid Build Coastguard Worker       if (t0_min < min_pitch_lag_res1_4) {
186*15dc779aSAndroid Build Coastguard Worker         t0_min = min_pitch_lag_res1_4;
187*15dc779aSAndroid Build Coastguard Worker       }
188*15dc779aSAndroid Build Coastguard Worker       t0_max = t0_min + 15;
189*15dc779aSAndroid Build Coastguard Worker 
190*15dc779aSAndroid Build Coastguard Worker       t = MAX(ol_pitch_lag1, ol_pitch_lag2) + 4;
191*15dc779aSAndroid Build Coastguard Worker       if (t0_max > t) t0_max = t;
192*15dc779aSAndroid Build Coastguard Worker 
193*15dc779aSAndroid Build Coastguard Worker       if (t0_max > max_pitch_lag) {
194*15dc779aSAndroid Build Coastguard Worker         t0_max = max_pitch_lag;
195*15dc779aSAndroid Build Coastguard Worker         t0_min = t0_max - 15;
196*15dc779aSAndroid Build Coastguard Worker       }
197*15dc779aSAndroid Build Coastguard Worker     }
198*15dc779aSAndroid Build Coastguard Worker 
199*15dc779aSAndroid Build Coastguard Worker     memcpy(xn, &wsig_in[i_subfr], LEN_SUBFR * sizeof(FLOAT32));
200*15dc779aSAndroid Build Coastguard Worker 
201*15dc779aSAndroid Build Coastguard Worker     memcpy(error, &synth_out[i_subfr - ORDER], ORDER * sizeof(FLOAT32));
202*15dc779aSAndroid Build Coastguard Worker     memset(error + ORDER, 0, LEN_SUBFR * sizeof(FLOAT32));
203*15dc779aSAndroid Build Coastguard Worker     iusace_synthesis_tool_float(p_quant_lp_filt_coeff, error + ORDER, error + ORDER, LEN_SUBFR,
204*15dc779aSAndroid Build Coastguard Worker                                 error, pstr_scratch->p_buf_synthesis_tool);
205*15dc779aSAndroid Build Coastguard Worker     iusace_get_weighted_lpc(p_lp_filt_coeff, weighted_lpc);
206*15dc779aSAndroid Build Coastguard Worker     iusace_compute_lp_residual(weighted_lpc, error + ORDER, xn2, LEN_SUBFR);
207*15dc779aSAndroid Build Coastguard Worker 
208*15dc779aSAndroid Build Coastguard Worker     temp = wsynth_out[i_subfr - 1];
209*15dc779aSAndroid Build Coastguard Worker     iusace_apply_deemph(xn2, TILT_FAC, LEN_SUBFR, &temp);
210*15dc779aSAndroid Build Coastguard Worker     memcpy(y0, xn2, LEN_SUBFR * sizeof(FLOAT32));
211*15dc779aSAndroid Build Coastguard Worker 
212*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
213*15dc779aSAndroid Build Coastguard Worker       xn[i] -= xn2[i];
214*15dc779aSAndroid Build Coastguard Worker     }
215*15dc779aSAndroid Build Coastguard Worker     iusace_compute_lp_residual(p_quant_lp_filt_coeff, &speech_in[i_subfr], &exc[i_subfr],
216*15dc779aSAndroid Build Coastguard Worker                                LEN_SUBFR);
217*15dc779aSAndroid Build Coastguard Worker 
218*15dc779aSAndroid Build Coastguard Worker     memset(&code[0], 0, ORDER * sizeof(code[0]));
219*15dc779aSAndroid Build Coastguard Worker     memcpy(code + ORDER, xn, (LEN_SUBFR / 2) * sizeof(FLOAT32));
220*15dc779aSAndroid Build Coastguard Worker     temp = 0.0;
221*15dc779aSAndroid Build Coastguard Worker     iusace_apply_preemph(code + ORDER, TILT_FAC, LEN_SUBFR / 2, &temp);
222*15dc779aSAndroid Build Coastguard Worker     iusace_get_weighted_lpc(p_lp_filt_coeff, weighted_lpc);
223*15dc779aSAndroid Build Coastguard Worker     iusace_synthesis_tool_float(weighted_lpc, code + ORDER, code + ORDER, LEN_SUBFR / 2, code,
224*15dc779aSAndroid Build Coastguard Worker                                 pstr_scratch->p_buf_synthesis_tool);
225*15dc779aSAndroid Build Coastguard Worker     iusace_compute_lp_residual(p_quant_lp_filt_coeff, code + ORDER, cn, LEN_SUBFR / 2);
226*15dc779aSAndroid Build Coastguard Worker     memcpy(cn + (LEN_SUBFR / 2), &exc[i_subfr + (LEN_SUBFR / 2)],
227*15dc779aSAndroid Build Coastguard Worker            (LEN_SUBFR / 2) * sizeof(FLOAT32));
228*15dc779aSAndroid Build Coastguard Worker 
229*15dc779aSAndroid Build Coastguard Worker     iusace_get_weighted_lpc(p_lp_filt_coeff, weighted_lpc);
230*15dc779aSAndroid Build Coastguard Worker     memset(imp_res, 0, LEN_SUBFR * sizeof(FLOAT32));
231*15dc779aSAndroid Build Coastguard Worker     memcpy(imp_res, weighted_lpc, (ORDER + 1) * sizeof(FLOAT32));
232*15dc779aSAndroid Build Coastguard Worker     iusace_synthesis_tool_float(p_quant_lp_filt_coeff, imp_res, imp_res, LEN_SUBFR,
233*15dc779aSAndroid Build Coastguard Worker                                 &imp_res[ORDER + 1], pstr_scratch->p_buf_synthesis_tool);
234*15dc779aSAndroid Build Coastguard Worker     temp = 0.0;
235*15dc779aSAndroid Build Coastguard Worker     iusace_apply_deemph(imp_res, TILT_FAC, LEN_SUBFR, &temp);
236*15dc779aSAndroid Build Coastguard Worker 
237*15dc779aSAndroid Build Coastguard Worker     iusace_closed_loop_search(&exc[i_subfr], xn, imp_res, t0_min, t0_max, &t0_frac, subfrm_flag,
238*15dc779aSAndroid Build Coastguard Worker                               min_pitch_lag_res1_2, min_pitch_lag_res1, &t0);
239*15dc779aSAndroid Build Coastguard Worker 
240*15dc779aSAndroid Build Coastguard Worker     if (subfrm_flag == 0) {
241*15dc779aSAndroid Build Coastguard Worker       if (t0 < min_pitch_lag_res1_2) {
242*15dc779aSAndroid Build Coastguard Worker         index = t0 * 4 + t0_frac - (min_pitch_lag_res1_4 * 4);
243*15dc779aSAndroid Build Coastguard Worker       } else if (t0 < min_pitch_lag_res1) {
244*15dc779aSAndroid Build Coastguard Worker         index = t0 * 2 + (t0_frac >> 1) - (min_pitch_lag_res1_2 * 2) +
245*15dc779aSAndroid Build Coastguard Worker                 ((min_pitch_lag_res1_2 - min_pitch_lag_res1_4) * 4);
246*15dc779aSAndroid Build Coastguard Worker       } else {
247*15dc779aSAndroid Build Coastguard Worker         index = t0 - min_pitch_lag_res1 + ((min_pitch_lag_res1_2 - min_pitch_lag_res1_4) * 4) +
248*15dc779aSAndroid Build Coastguard Worker                 ((min_pitch_lag_res1 - min_pitch_lag_res1_2) * 2);
249*15dc779aSAndroid Build Coastguard Worker       }
250*15dc779aSAndroid Build Coastguard Worker 
251*15dc779aSAndroid Build Coastguard Worker       t0_min = t0 - 8;
252*15dc779aSAndroid Build Coastguard Worker       if (t0_min < min_pitch_lag_res1_4) {
253*15dc779aSAndroid Build Coastguard Worker         t0_min = min_pitch_lag_res1_4;
254*15dc779aSAndroid Build Coastguard Worker       }
255*15dc779aSAndroid Build Coastguard Worker       t0_max = t0_min + 15;
256*15dc779aSAndroid Build Coastguard Worker       if (t0_max > max_pitch_lag) {
257*15dc779aSAndroid Build Coastguard Worker         t0_max = max_pitch_lag;
258*15dc779aSAndroid Build Coastguard Worker         t0_min = t0_max - 15;
259*15dc779aSAndroid Build Coastguard Worker       }
260*15dc779aSAndroid Build Coastguard Worker     } else {
261*15dc779aSAndroid Build Coastguard Worker       i = t0 - t0_min;
262*15dc779aSAndroid Build Coastguard Worker       index = i * 4 + t0_frac;
263*15dc779aSAndroid Build Coastguard Worker     }
264*15dc779aSAndroid Build Coastguard Worker     *acelp_params = index;
265*15dc779aSAndroid Build Coastguard Worker     acelp_params++;
266*15dc779aSAndroid Build Coastguard Worker 
267*15dc779aSAndroid Build Coastguard Worker     iusace_acelp_ltpred_cb_exc(&exc[i_subfr], t0, t0_frac, LEN_SUBFR + 1);
268*15dc779aSAndroid Build Coastguard Worker     iusace_convolve(&exc[i_subfr], imp_res, y1);
269*15dc779aSAndroid Build Coastguard Worker     gain1 = iusace_acelp_tgt_cb_corr2(xn, y1, tgt_cb_corr);
270*15dc779aSAndroid Build Coastguard Worker     iusace_acelp_cb_target_update(xn, xn2, y1, gain1);
271*15dc779aSAndroid Build Coastguard Worker     energy = 0.0;
272*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
273*15dc779aSAndroid Build Coastguard Worker       energy += xn2[i] * xn2[i];
274*15dc779aSAndroid Build Coastguard Worker     }
275*15dc779aSAndroid Build Coastguard Worker 
276*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
277*15dc779aSAndroid Build Coastguard Worker       code[i] = (FLOAT32)(0.18 * exc[i - 1 + i_subfr] + 0.64 * exc[i + i_subfr] +
278*15dc779aSAndroid Build Coastguard Worker                           0.18 * exc[i + 1 + i_subfr]);
279*15dc779aSAndroid Build Coastguard Worker     }
280*15dc779aSAndroid Build Coastguard Worker     iusace_convolve(code, imp_res, y2);
281*15dc779aSAndroid Build Coastguard Worker     gain2 = iusace_acelp_tgt_cb_corr2(xn, y2, tgt_cb_corr2);
282*15dc779aSAndroid Build Coastguard Worker 
283*15dc779aSAndroid Build Coastguard Worker     iusace_acelp_cb_target_update(xn, xn2, y2, gain2);
284*15dc779aSAndroid Build Coastguard Worker     temp = 0.0;
285*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
286*15dc779aSAndroid Build Coastguard Worker       temp += xn2[i] * xn2[i];
287*15dc779aSAndroid Build Coastguard Worker     }
288*15dc779aSAndroid Build Coastguard Worker 
289*15dc779aSAndroid Build Coastguard Worker     if (temp < energy) {
290*15dc779aSAndroid Build Coastguard Worker       *acelp_params = 0;
291*15dc779aSAndroid Build Coastguard Worker       memcpy(&exc[i_subfr], code, LEN_SUBFR * sizeof(FLOAT32));
292*15dc779aSAndroid Build Coastguard Worker       memcpy(y1, y2, LEN_SUBFR * sizeof(FLOAT32));
293*15dc779aSAndroid Build Coastguard Worker       pitch_gain = gain2;
294*15dc779aSAndroid Build Coastguard Worker       tgt_cb_corr[0] = tgt_cb_corr2[0];
295*15dc779aSAndroid Build Coastguard Worker       tgt_cb_corr[1] = tgt_cb_corr2[1];
296*15dc779aSAndroid Build Coastguard Worker     } else {
297*15dc779aSAndroid Build Coastguard Worker       *acelp_params = 1;
298*15dc779aSAndroid Build Coastguard Worker       pitch_gain = gain1;
299*15dc779aSAndroid Build Coastguard Worker     }
300*15dc779aSAndroid Build Coastguard Worker     acelp_params++;
301*15dc779aSAndroid Build Coastguard Worker 
302*15dc779aSAndroid Build Coastguard Worker     iusace_acelp_cb_target_update(xn, xn2, y1, pitch_gain);
303*15dc779aSAndroid Build Coastguard Worker     iusace_acelp_cb_target_update(cn, cn, &exc[i_subfr], pitch_gain);
304*15dc779aSAndroid Build Coastguard Worker 
305*15dc779aSAndroid Build Coastguard Worker     temp = 0.0;
306*15dc779aSAndroid Build Coastguard Worker     iusace_apply_preemph(imp_res, TILT_CODE, LEN_SUBFR, &temp);
307*15dc779aSAndroid Build Coastguard Worker     if (t0_frac > 2) {
308*15dc779aSAndroid Build Coastguard Worker       t0++;
309*15dc779aSAndroid Build Coastguard Worker     }
310*15dc779aSAndroid Build Coastguard Worker 
311*15dc779aSAndroid Build Coastguard Worker     for (i = t0; i < LEN_SUBFR; i++) {
312*15dc779aSAndroid Build Coastguard Worker       imp_res[i] += imp_res[i - t0] * PIT_SHARP;
313*15dc779aSAndroid Build Coastguard Worker     }
314*15dc779aSAndroid Build Coastguard Worker 
315*15dc779aSAndroid Build Coastguard Worker     iusace_acelp_tgt_ir_corr(xn2, imp_res, dn);
316*15dc779aSAndroid Build Coastguard Worker 
317*15dc779aSAndroid Build Coastguard Worker     if (acelp_core_mode == ACELP_CORE_MODE_9k6) {
318*15dc779aSAndroid Build Coastguard Worker       iusace_acelp_cb_exc(dn, cn, imp_res, cb_exc, y2, ACELP_NUM_BITS_20, acelp_params,
319*15dc779aSAndroid Build Coastguard Worker                           pstr_scratch->p_acelp_ir_buf);
320*15dc779aSAndroid Build Coastguard Worker       acelp_params += 4;
321*15dc779aSAndroid Build Coastguard Worker     } else if (acelp_core_mode == ACELP_CORE_MODE_11k2) {
322*15dc779aSAndroid Build Coastguard Worker       iusace_acelp_cb_exc(dn, cn, imp_res, cb_exc, y2, ACELP_NUM_BITS_28, acelp_params,
323*15dc779aSAndroid Build Coastguard Worker                           pstr_scratch->p_acelp_ir_buf);
324*15dc779aSAndroid Build Coastguard Worker       acelp_params += 4;
325*15dc779aSAndroid Build Coastguard Worker     } else if (acelp_core_mode == ACELP_CORE_MODE_12k8) {
326*15dc779aSAndroid Build Coastguard Worker       iusace_acelp_cb_exc(dn, cn, imp_res, cb_exc, y2, ACELP_NUM_BITS_36, acelp_params,
327*15dc779aSAndroid Build Coastguard Worker                           pstr_scratch->p_acelp_ir_buf);
328*15dc779aSAndroid Build Coastguard Worker       acelp_params += 4;
329*15dc779aSAndroid Build Coastguard Worker     } else if (acelp_core_mode == ACELP_CORE_MODE_14k4) {
330*15dc779aSAndroid Build Coastguard Worker       iusace_acelp_cb_exc(dn, cn, imp_res, cb_exc, y2, ACELP_NUM_BITS_44, acelp_params,
331*15dc779aSAndroid Build Coastguard Worker                           pstr_scratch->p_acelp_ir_buf);
332*15dc779aSAndroid Build Coastguard Worker       acelp_params += 4;
333*15dc779aSAndroid Build Coastguard Worker     } else if (acelp_core_mode == ACELP_CORE_MODE_16k) {
334*15dc779aSAndroid Build Coastguard Worker       iusace_acelp_cb_exc(dn, cn, imp_res, cb_exc, y2, ACELP_NUM_BITS_52, acelp_params,
335*15dc779aSAndroid Build Coastguard Worker                           pstr_scratch->p_acelp_ir_buf);
336*15dc779aSAndroid Build Coastguard Worker       acelp_params += 4;
337*15dc779aSAndroid Build Coastguard Worker     } else if (acelp_core_mode == ACELP_CORE_MODE_18k4) {
338*15dc779aSAndroid Build Coastguard Worker       iusace_acelp_cb_exc(dn, cn, imp_res, cb_exc, y2, ACELP_NUM_BITS_64, acelp_params,
339*15dc779aSAndroid Build Coastguard Worker                           pstr_scratch->p_acelp_ir_buf);
340*15dc779aSAndroid Build Coastguard Worker       acelp_params += 8;
341*15dc779aSAndroid Build Coastguard Worker     } else {
342*15dc779aSAndroid Build Coastguard Worker       iusace_acelp_cb_exc(dn, cn, imp_res, cb_exc, y2, ACELP_NUM_BITS_64, acelp_params,
343*15dc779aSAndroid Build Coastguard Worker                           pstr_scratch->p_acelp_ir_buf);
344*15dc779aSAndroid Build Coastguard Worker       acelp_params += 8;
345*15dc779aSAndroid Build Coastguard Worker     }
346*15dc779aSAndroid Build Coastguard Worker 
347*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
348*15dc779aSAndroid Build Coastguard Worker       code[i] = (FLOAT32)(cb_exc[i] / 512);
349*15dc779aSAndroid Build Coastguard Worker     }
350*15dc779aSAndroid Build Coastguard Worker 
351*15dc779aSAndroid Build Coastguard Worker     temp = 0.0;
352*15dc779aSAndroid Build Coastguard Worker     iusace_apply_preemph(code, TILT_CODE, LEN_SUBFR, &temp);
353*15dc779aSAndroid Build Coastguard Worker     for (i = t0; i < LEN_SUBFR; i++) {
354*15dc779aSAndroid Build Coastguard Worker       code[i] += code[i - t0] * PIT_SHARP;
355*15dc779aSAndroid Build Coastguard Worker     }
356*15dc779aSAndroid Build Coastguard Worker 
357*15dc779aSAndroid Build Coastguard Worker     iusace_acelp_tgt_cb_corr1(xn, y1, y2, tgt_cb_corr);
358*15dc779aSAndroid Build Coastguard Worker     iusace_acelp_quant_gain(code, &pitch_gain, &code_gain, tgt_cb_corr, mean_ener_code,
359*15dc779aSAndroid Build Coastguard Worker                             acelp_params);
360*15dc779aSAndroid Build Coastguard Worker     acelp_params++;
361*15dc779aSAndroid Build Coastguard Worker 
362*15dc779aSAndroid Build Coastguard Worker     temp = 0.0;
363*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
364*15dc779aSAndroid Build Coastguard Worker       temp += code[i] * code[i];
365*15dc779aSAndroid Build Coastguard Worker     }
366*15dc779aSAndroid Build Coastguard Worker     temp *= code_gain * code_gain;
367*15dc779aSAndroid Build Coastguard Worker 
368*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
369*15dc779aSAndroid Build Coastguard Worker       wsynth_out[i + i_subfr] = y0[i] + (pitch_gain * y1[i]) + (code_gain * y2[i]);
370*15dc779aSAndroid Build Coastguard Worker     }
371*15dc779aSAndroid Build Coastguard Worker 
372*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < LEN_SUBFR; i++) {
373*15dc779aSAndroid Build Coastguard Worker       exc[i + i_subfr] = pitch_gain * exc[i + i_subfr] + code_gain * code[i];
374*15dc779aSAndroid Build Coastguard Worker     }
375*15dc779aSAndroid Build Coastguard Worker 
376*15dc779aSAndroid Build Coastguard Worker     iusace_synthesis_tool_float(p_quant_lp_filt_coeff, &exc[i_subfr], &synth_out[i_subfr],
377*15dc779aSAndroid Build Coastguard Worker                                 LEN_SUBFR, &synth_out[i_subfr - ORDER],
378*15dc779aSAndroid Build Coastguard Worker                                 pstr_scratch->p_buf_synthesis_tool);
379*15dc779aSAndroid Build Coastguard Worker     p_lp_filt_coeff += (ORDER + 1);
380*15dc779aSAndroid Build Coastguard Worker     p_quant_lp_filt_coeff += (ORDER + 1);
381*15dc779aSAndroid Build Coastguard Worker   }
382*15dc779aSAndroid Build Coastguard Worker 
383*15dc779aSAndroid Build Coastguard Worker   memcpy(lpd_state->acelp_exc, exc - len_subfrm, 2 * len_subfrm * sizeof(FLOAT32));
384*15dc779aSAndroid Build Coastguard Worker   memcpy(lpd_state->synth, synth_out + len_subfrm - (ORDER + 128),
385*15dc779aSAndroid Build Coastguard Worker          (ORDER + 128) * sizeof(FLOAT32));
386*15dc779aSAndroid Build Coastguard Worker   memcpy(lpd_state->wsynth, wsynth_out + len_subfrm - (1 + 128), (1 + 128) * sizeof(FLOAT32));
387*15dc779aSAndroid Build Coastguard Worker   memcpy(lpd_state->lpc_coeffs_quant, p_quant_lp_filt_coeff - (2 * (ORDER + 1)),
388*15dc779aSAndroid Build Coastguard Worker          (2 * (ORDER + 1)) * sizeof(FLOAT32));
389*15dc779aSAndroid Build Coastguard Worker   memcpy(lpd_state->lpc_coeffs, p_lp_filt_coeff - (2 * (ORDER + 1)),
390*15dc779aSAndroid Build Coastguard Worker          (2 * (ORDER + 1)) * sizeof(FLOAT32));
391*15dc779aSAndroid Build Coastguard Worker 
392*15dc779aSAndroid Build Coastguard Worker   mem_txn = lpd_state->tcx_mem[128 - 1];
393*15dc779aSAndroid Build Coastguard Worker   mem_txnq = lpd_state->tcx_fac;
394*15dc779aSAndroid Build Coastguard Worker 
395*15dc779aSAndroid Build Coastguard Worker   p_quant_lp_filt_coeff = quant_lp_filt_coeff;
396*15dc779aSAndroid Build Coastguard Worker   for (i_subfr = 0; i_subfr < (len_subfrm - 2 * LEN_SUBFR); i_subfr += LEN_SUBFR) {
397*15dc779aSAndroid Build Coastguard Worker     iusace_get_weighted_lpc(p_quant_lp_filt_coeff, weighted_lpc);
398*15dc779aSAndroid Build Coastguard Worker 
399*15dc779aSAndroid Build Coastguard Worker     memcpy(error, &speech_in[i_subfr], LEN_SUBFR * sizeof(FLOAT32));
400*15dc779aSAndroid Build Coastguard Worker     iusace_apply_deemph(error, TILT_FAC, LEN_SUBFR, &mem_txn);
401*15dc779aSAndroid Build Coastguard Worker 
402*15dc779aSAndroid Build Coastguard Worker     memcpy(error, &synth_out[i_subfr], LEN_SUBFR * sizeof(FLOAT32));
403*15dc779aSAndroid Build Coastguard Worker     iusace_apply_deemph(error, TILT_FAC, LEN_SUBFR, &mem_txnq);
404*15dc779aSAndroid Build Coastguard Worker 
405*15dc779aSAndroid Build Coastguard Worker     p_quant_lp_filt_coeff += (ORDER + 1);
406*15dc779aSAndroid Build Coastguard Worker   }
407*15dc779aSAndroid Build Coastguard Worker 
408*15dc779aSAndroid Build Coastguard Worker   lpd_state->tcx_quant[0] = mem_txnq;
409*15dc779aSAndroid Build Coastguard Worker   for (i_subfr = 0; i_subfr < (2 * LEN_SUBFR); i_subfr += LEN_SUBFR) {
410*15dc779aSAndroid Build Coastguard Worker     iusace_get_weighted_lpc(p_quant_lp_filt_coeff, weighted_lpc);
411*15dc779aSAndroid Build Coastguard Worker 
412*15dc779aSAndroid Build Coastguard Worker     memcpy(&(lpd_state->tcx_mem[i_subfr]), &speech_in[i_subfr + (len_subfrm - 2 * LEN_SUBFR)],
413*15dc779aSAndroid Build Coastguard Worker            LEN_SUBFR * sizeof(FLOAT32));
414*15dc779aSAndroid Build Coastguard Worker     iusace_apply_deemph(&(lpd_state->tcx_mem[i_subfr]), TILT_FAC, LEN_SUBFR, &mem_txn);
415*15dc779aSAndroid Build Coastguard Worker 
416*15dc779aSAndroid Build Coastguard Worker     memcpy(&(lpd_state->tcx_quant[1 + i_subfr]),
417*15dc779aSAndroid Build Coastguard Worker            &synth_out[i_subfr + (len_subfrm - 2 * LEN_SUBFR)], LEN_SUBFR * sizeof(FLOAT32));
418*15dc779aSAndroid Build Coastguard Worker     iusace_apply_deemph(&(lpd_state->tcx_quant[1 + i_subfr]), TILT_FAC, LEN_SUBFR, &mem_txnq);
419*15dc779aSAndroid Build Coastguard Worker     p_quant_lp_filt_coeff += (ORDER + 1);
420*15dc779aSAndroid Build Coastguard Worker   }
421*15dc779aSAndroid Build Coastguard Worker   lpd_state->tcx_fac = mem_txnq;
422*15dc779aSAndroid Build Coastguard Worker 
423*15dc779aSAndroid Build Coastguard Worker   iusace_get_weighted_lpc(p_quant_lp_filt_coeff, weighted_lpc);
424*15dc779aSAndroid Build Coastguard Worker 
425*15dc779aSAndroid Build Coastguard Worker   memcpy(error, &synth_out[len_subfrm - ORDER], ORDER * sizeof(FLOAT32));
426*15dc779aSAndroid Build Coastguard Worker   for (i_subfr = (2 * LEN_SUBFR); i_subfr < (4 * LEN_SUBFR); i_subfr += LEN_SUBFR) {
427*15dc779aSAndroid Build Coastguard Worker     memset(error + ORDER, 0, LEN_SUBFR * sizeof(FLOAT32));
428*15dc779aSAndroid Build Coastguard Worker 
429*15dc779aSAndroid Build Coastguard Worker     iusace_synthesis_tool_float(p_quant_lp_filt_coeff, error + ORDER, error + ORDER, LEN_SUBFR,
430*15dc779aSAndroid Build Coastguard Worker                                 error, pstr_scratch->p_buf_synthesis_tool);
431*15dc779aSAndroid Build Coastguard Worker     memcpy(&(lpd_state->tcx_quant[1 + i_subfr]), error + ORDER, LEN_SUBFR * sizeof(FLOAT32));
432*15dc779aSAndroid Build Coastguard Worker     iusace_apply_deemph(&(lpd_state->tcx_quant[1 + i_subfr]), TILT_FAC, LEN_SUBFR, &mem_txnq);
433*15dc779aSAndroid Build Coastguard Worker     memcpy(error, error + LEN_SUBFR, ORDER * sizeof(FLOAT32));
434*15dc779aSAndroid Build Coastguard Worker   }
435*15dc779aSAndroid Build Coastguard Worker 
436*15dc779aSAndroid Build Coastguard Worker   lpd_state->mode = 0;
437*15dc779aSAndroid Build Coastguard Worker 
438*15dc779aSAndroid Build Coastguard Worker   lpd_state->num_bits = num_bits;
439*15dc779aSAndroid Build Coastguard Worker }
440