1 /******************************************************************************
2  *                                                                            *
3  * Copyright (C) 2018 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 #include <float.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <string.h>
25 
26 #include "ixheaacd_type_def.h"
27 
28 #include "ixheaacd_bitbuffer.h"
29 
30 #include "ixheaacd_interface.h"
31 
32 #include "ixheaacd_tns_usac.h"
33 #include "ixheaacd_cnst.h"
34 
35 #include "ixheaacd_acelp_info.h"
36 
37 #include "ixheaacd_td_mdct.h"
38 
39 #include "ixheaacd_sbrdecsettings.h"
40 #include "ixheaacd_info.h"
41 #include "ixheaacd_sbr_common.h"
42 #include "ixheaacd_drc_data_struct.h"
43 #include "ixheaacd_drc_dec.h"
44 #include "ixheaacd_sbrdecoder.h"
45 #include "ixheaacd_mps_polyphase.h"
46 #include "ixheaacd_sbr_const.h"
47 #include "ixheaacd_main.h"
48 #include "ixheaacd_arith_dec.h"
49 #include "ixheaacd_func_def.h"
50 
51 #include "ixheaacd_acelp_com.h"
52 
53 #define F_PIT_SHARP 0.85F
54 #define MEAN_ENER 30
55 
56 extern const FLOAT32 ixheaacd_interpol_filt[INTER_LP_FIL_LEN];
57 
ixheaacd_acelp_pitch_sharpening(FLOAT32 * x,WORD32 pit_lag)58 VOID ixheaacd_acelp_pitch_sharpening(FLOAT32 *x, WORD32 pit_lag) {
59   WORD32 i;
60   for (i = pit_lag; i < LEN_SUBFR; i++) {
61     x[i] += x[i - pit_lag] * F_PIT_SHARP;
62   }
63   return;
64 }
65 
ixheaacd_acelp_decode_1sp_per_track(WORD32 idx_1p,WORD32 M,WORD32 ixheaacd_drc_offset,WORD32 track,FLOAT32 code_vec[])66 static VOID ixheaacd_acelp_decode_1sp_per_track(WORD32 idx_1p, WORD32 M,
67                                                 WORD32 ixheaacd_drc_offset,
68                                                 WORD32 track,
69                                                 FLOAT32 code_vec[]) {
70   WORD32 sign_index, mask, m;
71   WORD32 sp_pos;
72   mask = ((1 << M) - 1);
73 
74   sp_pos = (idx_1p & mask) + ixheaacd_drc_offset;
75   sign_index = ((idx_1p >> M) & 1);
76 
77   m = (sp_pos << 2) + track;
78   if (sign_index == 1)
79     code_vec[m] = (code_vec[m] - 1.0f);
80   else
81     code_vec[m] = (code_vec[m] + 1.0f);
82 
83   return;
84 }
85 
ixheaacd_acelp_decode_2sp_per_track(WORD32 idx_2p,WORD32 M,WORD32 ixheaacd_drc_offset,WORD32 track,FLOAT32 code_vec[])86 static VOID ixheaacd_acelp_decode_2sp_per_track(WORD32 idx_2p, WORD32 M,
87                                                 WORD32 ixheaacd_drc_offset,
88                                                 WORD32 track,
89                                                 FLOAT32 code_vec[]) {
90   WORD32 sign_index;
91   WORD32 mask, m0, m1;
92   WORD32 sp_pos[2];
93   mask = ((1 << M) - 1);
94 
95   sp_pos[0] = (((idx_2p >> M) & mask) + ixheaacd_drc_offset);
96   sp_pos[1] = ((idx_2p & mask) + ixheaacd_drc_offset);
97 
98   sign_index = (idx_2p >> 2 * M) & 1;
99 
100   m0 = (sp_pos[0] << 2) + track;
101   m1 = (sp_pos[1] << 2) + track;
102 
103   if ((sp_pos[1] - sp_pos[0]) < 0) {
104     if (sign_index == 1) {
105       code_vec[m0] = (code_vec[m0] - 1.0f);
106       code_vec[m1] = (code_vec[m1] + 1.0f);
107     } else {
108       code_vec[m0] = (code_vec[m0] + 1.0f);
109       code_vec[m1] = (code_vec[m1] - 1.0f);
110     }
111   } else {
112     if (sign_index == 1) {
113       code_vec[m0] = (code_vec[m0] - 1.0f);
114       code_vec[m1] = (code_vec[m1] - 1.0f);
115     } else {
116       code_vec[m0] = (code_vec[m0] + 1.0f);
117       code_vec[m1] = (code_vec[m1] + 1.0f);
118     }
119   }
120   return;
121 }
122 
ixheaacd_acelp_decode_3sp_per_track(WORD32 idx_3p,WORD32 M,WORD32 ixheaacd_drc_offset,WORD32 track,FLOAT32 code_vec[])123 static VOID ixheaacd_acelp_decode_3sp_per_track(WORD32 idx_3p, WORD32 M,
124                                                 WORD32 ixheaacd_drc_offset,
125                                                 WORD32 track,
126                                                 FLOAT32 code_vec[]) {
127   WORD32 j, mask, idx_2p, idx_1p;
128 
129   mask = ((1 << (2 * M - 1)) - 1);
130   idx_2p = idx_3p & mask;
131   j = ixheaacd_drc_offset;
132   if (((idx_3p >> ((2 * M) - 1)) & 1) == 1) {
133     j += (1 << (M - 1));
134   }
135   ixheaacd_acelp_decode_2sp_per_track(idx_2p, M - 1, j, track, code_vec);
136   mask = ((1 << (M + 1)) - 1);
137   idx_1p = (idx_3p >> 2 * M) & mask;
138   ixheaacd_acelp_decode_1sp_per_track(idx_1p, M, ixheaacd_drc_offset, track,
139                                       code_vec);
140   return;
141 }
142 
ixheaacd_d_acelp_decode_4sp_per_track_section(WORD32 index,WORD32 ixheaacd_drc_offset,WORD32 track,FLOAT32 code_vec[])143 static VOID ixheaacd_d_acelp_decode_4sp_per_track_section(
144     WORD32 index, WORD32 ixheaacd_drc_offset, WORD32 track,
145     FLOAT32 code_vec[]) {
146   WORD32 j, idx_2p;
147 
148   idx_2p = index & 31;
149   j = ixheaacd_drc_offset;
150   if (((index >> 5) & 1) == 1) {
151     j += 4;
152   }
153   ixheaacd_acelp_decode_2sp_per_track(idx_2p, 2, j, track, code_vec);
154   idx_2p = (index >> 6) & 127;
155   ixheaacd_acelp_decode_2sp_per_track(idx_2p, 3, ixheaacd_drc_offset, track,
156                                       code_vec);
157   return;
158 }
159 
ixheaacd_acelp_decode_4sp_per_track(WORD32 idx_4p,WORD32 track,FLOAT32 code_vec[])160 static VOID ixheaacd_acelp_decode_4sp_per_track(WORD32 idx_4p, WORD32 track,
161                                                 FLOAT32 code_vec[]) {
162   WORD32 idx_1p, idx_2p, idx_3p;
163 
164   switch ((idx_4p >> 14) & 3) {
165     case 0:
166       if (((idx_4p >> 13) & 1) == 0)
167         ixheaacd_d_acelp_decode_4sp_per_track_section(idx_4p, 0, track,
168                                                       code_vec);
169       else
170         ixheaacd_d_acelp_decode_4sp_per_track_section(idx_4p, 8, track,
171                                                       code_vec);
172       break;
173     case 1:
174       idx_1p = idx_4p >> 10;
175       ixheaacd_acelp_decode_1sp_per_track(idx_1p, 3, 0, track, code_vec);
176       ixheaacd_acelp_decode_3sp_per_track(idx_4p, 3, 8, track, code_vec);
177       break;
178     case 2:
179       idx_2p = idx_4p >> 7;
180       ixheaacd_acelp_decode_2sp_per_track(idx_2p, 3, 0, track, code_vec);
181       ixheaacd_acelp_decode_2sp_per_track(idx_4p, 3, 8, track, code_vec);
182       break;
183     case 3:
184       idx_3p = idx_4p >> 4;
185       ixheaacd_acelp_decode_3sp_per_track(idx_3p, 3, 0, track, code_vec);
186       ixheaacd_acelp_decode_1sp_per_track(idx_4p, 3, 8, track, code_vec);
187       break;
188   }
189   return;
190 }
191 
ixheaacd_d_acelp_add_pulse(WORD32 pos[],WORD32 nb_pulse,WORD32 track,FLOAT32 code[])192 static VOID ixheaacd_d_acelp_add_pulse(WORD32 pos[], WORD32 nb_pulse,
193                                        WORD32 track, FLOAT32 code[]) {
194   WORD32 i, k;
195   for (k = 0; k < nb_pulse; k++) {
196     i = ((pos[k] & (16 - 1)) << 2) + track;
197     if ((pos[k] & 16) == 0) {
198       code[i] = (WORD16)(code[i] + 1.0f);
199     } else {
200       code[i] = (WORD16)(code[i] - 1.0f);
201     }
202   }
203   return;
204 }
205 
ixheaacd_d_acelp_decode_1p_n1(WORD32 index,WORD32 N,WORD32 ixheaacd_drc_offset,WORD32 pos[])206 static VOID ixheaacd_d_acelp_decode_1p_n1(WORD32 index, WORD32 N,
207                                           WORD32 ixheaacd_drc_offset,
208                                           WORD32 pos[]) {
209   WORD32 i, pos1, mask;
210   mask = ((1 << N) - 1);
211 
212   pos1 = ((index & mask) + ixheaacd_drc_offset);
213   i = ((index >> N) & 1);
214   if (i == 1) {
215     pos1 += 16;
216   }
217   pos[0] = pos1;
218   return;
219 }
220 
ixheaacd_acelp_decode_pulses_per_track(WORD32 cb_index[],const WORD16 code_bits,FLOAT32 code_vec[])221 VOID ixheaacd_acelp_decode_pulses_per_track(WORD32 cb_index[],
222                                             const WORD16 code_bits,
223                                             FLOAT32 code_vec[]) {
224   WORD32 track_idx, index, ixheaacd_drc_offset, pos[6], i;
225   memset(code_vec, 0, 64 * sizeof(FLOAT32));
226 
227   if (code_bits == 12) {
228     for (track_idx = 0; track_idx < 4; track_idx += 2) {
229       ixheaacd_drc_offset = cb_index[2 * (track_idx / 2)];
230       index = cb_index[2 * (track_idx / 2) + 1];
231       ixheaacd_d_acelp_decode_1p_n1(index, 4, 0, pos);
232       ixheaacd_d_acelp_add_pulse(
233           pos, 1, 2 * ixheaacd_drc_offset + track_idx / 2, code_vec);
234     }
235   } else if (code_bits == 16) {
236     i = 0;
237     ixheaacd_drc_offset = cb_index[i++];
238     ixheaacd_drc_offset = (ixheaacd_drc_offset == 0) ? 1 : 3;
239     for (track_idx = 0; track_idx < 4; track_idx++) {
240       if (track_idx != ixheaacd_drc_offset) {
241         index = cb_index[i++];
242         ixheaacd_d_acelp_decode_1p_n1(index, 4, 0, pos);
243         ixheaacd_d_acelp_add_pulse(pos, 1, track_idx, code_vec);
244       }
245     }
246   } else if (code_bits == 20) {
247     for (track_idx = 0; track_idx < 4; track_idx++) {
248       index = cb_index[track_idx];
249       ixheaacd_acelp_decode_1sp_per_track(index, 4, 0, track_idx, code_vec);
250     }
251   } else if (code_bits == 28) {
252     for (track_idx = 0; track_idx < 2; track_idx++) {
253       index = cb_index[track_idx];
254       ixheaacd_acelp_decode_2sp_per_track(index, 4, 0, track_idx, code_vec);
255     }
256     for (track_idx = 2; track_idx < 4; track_idx++) {
257       index = cb_index[track_idx];
258       ixheaacd_acelp_decode_1sp_per_track(index, 4, 0, track_idx, code_vec);
259     }
260   } else if (code_bits == 36) {
261     for (track_idx = 0; track_idx < 4; track_idx++) {
262       index = cb_index[track_idx];
263       ixheaacd_acelp_decode_2sp_per_track(index, 4, 0, track_idx, code_vec);
264     }
265   } else if (code_bits == 44) {
266     for (track_idx = 0; track_idx < 2; track_idx++) {
267       index = cb_index[track_idx];
268       ixheaacd_acelp_decode_3sp_per_track(index, 4, 0, track_idx, code_vec);
269     }
270     for (track_idx = 2; track_idx < 4; track_idx++) {
271       index = cb_index[track_idx];
272       ixheaacd_acelp_decode_2sp_per_track(index, 4, 0, track_idx, code_vec);
273     }
274   } else if (code_bits == 52) {
275     for (track_idx = 0; track_idx < 4; track_idx++) {
276       index = cb_index[track_idx];
277       ixheaacd_acelp_decode_3sp_per_track(index, 4, 0, track_idx, code_vec);
278     }
279   } else if (code_bits == 64) {
280     for (track_idx = 0; track_idx < 4; track_idx++) {
281       index = ((cb_index[track_idx] << 14) + cb_index[track_idx + 4]);
282       ixheaacd_acelp_decode_4sp_per_track(index, track_idx, code_vec);
283     }
284   }
285   return;
286 }
287 
ixheaacd_acelp_decode_gains(WORD32 index,FLOAT32 code_vec[],FLOAT32 * pitch_gain,FLOAT32 * codebook_gain,FLOAT32 mean_exc_energy,FLOAT32 * energy)288 static void ixheaacd_acelp_decode_gains(WORD32 index, FLOAT32 code_vec[],
289                                         FLOAT32 *pitch_gain,
290                                         FLOAT32 *codebook_gain,
291                                         FLOAT32 mean_exc_energy,
292                                         FLOAT32 *energy) {
293   WORD32 i;
294   FLOAT32 avg_innov_energy, est_gain;
295   const FLOAT32 *gain_table = ixheaacd_int_leave_gain_table;
296 
297   avg_innov_energy = 0.01f;
298   for (i = 0; i < LEN_SUBFR; i++) {
299     avg_innov_energy += code_vec[i] * code_vec[i];
300   }
301   *energy = avg_innov_energy;
302 
303   avg_innov_energy =
304       (FLOAT32)(10.0 * log10(avg_innov_energy / (FLOAT32)LEN_SUBFR));
305 
306   est_gain = mean_exc_energy - avg_innov_energy;
307 
308   est_gain = (FLOAT32)pow(10.0, 0.05 * est_gain);
309   *pitch_gain = gain_table[index * 2];
310 
311   *codebook_gain = gain_table[index * 2 + 1] * est_gain;
312 
313   return;
314 }
315 
ixheaacd_cb_exc_calc(FLOAT32 xcitation_curr[],WORD32 pitch_lag,WORD32 frac)316 static VOID ixheaacd_cb_exc_calc(FLOAT32 xcitation_curr[], WORD32 pitch_lag,
317                                  WORD32 frac) {
318   WORD32 i, j;
319   FLOAT32 s, *x0, *x1, *x2;
320   const FLOAT32 *c1, *c2;
321 
322   x0 = &xcitation_curr[-pitch_lag];
323   frac = -frac;
324   if (frac < 0) {
325     frac += UP_SAMP;
326     x0--;
327   }
328   for (j = 0; j < LEN_SUBFR + 1; j++) {
329     x1 = x0++;
330     x2 = x1 + 1;
331     c1 = &ixheaacd_interpol_filt[frac];
332     c2 = &ixheaacd_interpol_filt[UP_SAMP - frac];
333     s = 0.0;
334     for (i = 0; i < INTER_LP_FIL_ORDER; i++, c1 += UP_SAMP, c2 += UP_SAMP) {
335       s += (*x1--) * (*c1) + (*x2++) * (*c2);
336     }
337     xcitation_curr[j] = s;
338   }
339   return;
340 }
341 
ixheaacd_acelp_alias_cnx(ia_usac_data_struct * usac_data,ia_td_frame_data_struct * pstr_td_frame_data,WORD32 k,FLOAT32 lp_filt_coeff[],FLOAT32 stability_factor,ia_usac_lpd_decoder_handle st)342 WORD32 ixheaacd_acelp_alias_cnx(ia_usac_data_struct *usac_data,
343                                 ia_td_frame_data_struct *pstr_td_frame_data,
344                                 WORD32 k, FLOAT32 lp_filt_coeff[],
345                                 FLOAT32 stability_factor,
346                                 ia_usac_lpd_decoder_handle st) {
347   WORD32 i, subfr_idx;
348   WORD32 pitch_lag, pitch_lag_frac, index, pitch_flag, pitch_lag_max;
349   WORD32 pitch_lag_min = 0;
350   FLOAT32 tmp, pitch_gain, gain_code, voicing_factor, r_v, innov_energy,
351       pitch_energy, mean_ener_code;
352   FLOAT32 gain_smooth, gain_code0, cpe;
353   FLOAT32 code[LEN_SUBFR] = {0}, synth_temp[128 + 16] = {0};
354   FLOAT32 post_process_exc[LEN_SUBFR] = {0};
355   FLOAT32 gain_smooth_factor;
356   FLOAT32 *ptr_lp_filt_coeff;
357   WORD32 pitch_min;
358   WORD32 pitch_fr2;
359   WORD32 pitch_fr1;
360   WORD32 pitch_max;
361   WORD32 subfr_nb = 0;
362   static const WORD16 num_codebits_table[8] = {20, 28, 36, 44, 52, 64, 12, 16};
363   FLOAT32 x[FAC_LENGTH] = {0}, xn2[2 * FAC_LENGTH + 16] = {0};
364   WORD32 int_x[FAC_LENGTH] = {0};
365   WORD32 TTT;
366   WORD32 len_subfr = usac_data->len_subfrm;
367   WORD32 fac_length;
368   WORD8 shiftp;
369   WORD32 preshift;
370   WORD32 *ptr_scratch = &usac_data->scratch_buffer[0];
371   WORD32 *int_xn2 = &usac_data->x_ac_dec[0];
372   WORD32 loop_count = 0;
373   WORD32 core_mode = pstr_td_frame_data->acelp_core_mode;
374   FLOAT32 *synth_signal =
375       &usac_data->synth_buf[len_subfr * k + MAX_PITCH +
376                             (((NUM_FRAMES * usac_data->num_subfrm) / 2) - 1) *
377                                 LEN_SUBFR];
378   FLOAT32 *xcitation_curr =
379       &usac_data->exc_buf[len_subfr * k + MAX_PITCH + (INTER_LP_FIL_ORDER + 1)];
380   FLOAT32 *ptr_pitch_gain =
381       &usac_data->pitch_gain[k * usac_data->num_subfrm +
382                              (((NUM_FRAMES * usac_data->num_subfrm) / 2) - 1)];
383   WORD32 *ptr_pitch =
384       &usac_data->pitch[k * usac_data->num_subfrm +
385                         (((NUM_FRAMES * usac_data->num_subfrm) / 2) - 1)];
386   WORD32 err = 0;
387   fac_length = len_subfr / 2;
388 
389   if (st->mode_prev > 0) {
390     for (i = 0; i < fac_length / 2; i++) {
391       x[i] = st->fac_gain * pstr_td_frame_data->fac[k * FAC_LENGTH + 2 * i];
392       x[fac_length / 2 + i] =
393           st->fac_gain *
394           pstr_td_frame_data->fac[k * FAC_LENGTH + fac_length - 2 * i - 1];
395     }
396     for (i = 0; i < fac_length / 8; i++) {
397       x[i] *= st->fac_fd_data[2 * i];
398       x[fac_length - i - 1] *= st->fac_fd_data[2 * i + 1];
399     }
400 
401     preshift = 0;
402     shiftp = ixheaacd_float2fix(x, int_x, fac_length);
403 
404     err =
405         ixheaacd_acelp_mdct(int_x, int_xn2, &preshift, fac_length, ptr_scratch);
406     if (err == -1) return err;
407     ixheaacd_fix2float(int_xn2, xn2 + fac_length, fac_length, &shiftp,
408                        &preshift);
409 
410     ixheaacd_vec_cnst_mul((2.0f / (FLOAT32)fac_length), xn2 + fac_length,
411                           xn2 + fac_length, fac_length);
412 
413     memset(xn2, 0, fac_length * sizeof(FLOAT32));
414 
415     ixheaacd_lpc_wt_synthesis_tool(st->lp_flt_coeff_a_prev, xn2 + fac_length,
416                                    fac_length);
417 
418     for (i = 0; i < 2 * fac_length; i++)
419       xn2[i] += synth_signal[i - (2 * fac_length)];
420 
421     memcpy(synth_signal - fac_length, xn2 + fac_length,
422            fac_length * sizeof(FLOAT32));
423 
424     tmp = 0.0;
425     ixheaacd_preemphsis_tool_float(xn2, PREEMPH_FILT_FAC, 2 * fac_length, tmp);
426 
427     ptr_lp_filt_coeff = st->lp_flt_coeff_a_prev;
428     TTT = fac_length % LEN_SUBFR;
429     if (TTT != 0) {
430       ixheaacd_residual_tool_float(
431           ptr_lp_filt_coeff, &xn2[fac_length],
432           &xcitation_curr[fac_length - (2 * fac_length)], TTT, 1);
433       ptr_lp_filt_coeff += (ORDER + 1);
434     }
435 
436     loop_count = (fac_length + TTT) / LEN_SUBFR;
437     ixheaacd_residual_tool_float(ptr_lp_filt_coeff, &xn2[fac_length + TTT],
438                                  &xcitation_curr[TTT - fac_length], LEN_SUBFR,
439                                  loop_count);
440   }
441 
442   for (i = 0; i < ORDER; i++)
443     synth_temp[i] = synth_signal[i - ORDER] -
444                     (PREEMPH_FILT_FAC * synth_signal[i - ORDER - 1]);
445 
446   i = (((st->fscale * TMIN) + (FSCALE_DENOM / 2)) / FSCALE_DENOM) - TMIN;
447   pitch_min = TMIN + i;
448   pitch_fr2 = TFR2 - i;
449   pitch_fr1 = TFR1;
450   pitch_max = TMAX + (6 * i);
451 
452   ptr_lp_filt_coeff = lp_filt_coeff;
453   for (subfr_idx = 0; subfr_idx < len_subfr; subfr_idx += LEN_SUBFR) {
454     pitch_flag = subfr_idx;
455     if ((len_subfr == 256) && (subfr_idx == (2 * LEN_SUBFR))) {
456       pitch_flag = 0;
457     }
458     index = pstr_td_frame_data->acb_index[k * 4 + subfr_nb];
459 
460     if (pitch_flag == 0) {
461       if (index < (pitch_fr2 - pitch_min) * 4) {
462         pitch_lag = pitch_min + (index / 4);
463         pitch_lag_frac = index - (pitch_lag - pitch_min) * 4;
464       } else if (index <
465                  ((pitch_fr2 - pitch_min) * 4 + (pitch_fr1 - pitch_fr2) * 2)) {
466         index -= (pitch_fr2 - pitch_min) * 4;
467         pitch_lag = pitch_fr2 + (index / 2);
468         pitch_lag_frac = index - (pitch_lag - pitch_fr2) * 2;
469         pitch_lag_frac *= 2;
470       } else {
471         pitch_lag = index + pitch_fr1 - ((pitch_fr2 - pitch_min) * 4) -
472                     ((pitch_fr1 - pitch_fr2) * 2);
473         pitch_lag_frac = 0;
474       }
475       pitch_lag_min = pitch_lag - 8;
476       if (pitch_lag_min < pitch_min) pitch_lag_min = pitch_min;
477 
478       pitch_lag_max = pitch_lag_min + 15;
479       if (pitch_lag_max > pitch_max) {
480         pitch_lag_max = pitch_max;
481         pitch_lag_min = pitch_lag_max - 15;
482       }
483     } else {
484       pitch_lag = pitch_lag_min + index / 4;
485       pitch_lag_frac = index - (pitch_lag - pitch_lag_min) * 4;
486     }
487 
488     ixheaacd_cb_exc_calc(&xcitation_curr[subfr_idx], pitch_lag, pitch_lag_frac);
489 
490     mean_ener_code =
491         (((FLOAT32)pstr_td_frame_data->mean_energy[k]) * 12.0f) + 18.0f;
492 
493     if (pstr_td_frame_data->ltp_filtering_flag[k * 4 + subfr_nb] == 0) {
494       for (i = 0; i < LEN_SUBFR; i++)
495         code[i] = (FLOAT32)(0.18 * xcitation_curr[i - 1 + subfr_idx] +
496                             0.64 * xcitation_curr[i + subfr_idx] +
497                             0.18 * xcitation_curr[i + 1 + subfr_idx]);
498 
499       ixheaacd_mem_cpy(code, &xcitation_curr[subfr_idx], LEN_SUBFR);
500     }
501 
502     ixheaacd_acelp_decode_pulses_per_track(
503         &(pstr_td_frame_data->icb_index[k * 4 + subfr_nb][0]),
504         num_codebits_table[core_mode], code);
505 
506     tmp = 0.0;
507     ixheaacd_preemphsis_tool_float(code, TILT_CODE, LEN_SUBFR, tmp);
508     i = pitch_lag;
509     if (pitch_lag_frac > 2) i++;
510     if (i >= 0) ixheaacd_acelp_pitch_sharpening(code, i);
511 
512     index = pstr_td_frame_data->gains[k * 4 + subfr_nb];
513 
514     ixheaacd_acelp_decode_gains(index, code, &pitch_gain, &gain_code,
515                                 mean_ener_code, &innov_energy);
516 
517     pitch_energy = 0.0;
518     for (i = 0; i < LEN_SUBFR; i++)
519       pitch_energy +=
520           xcitation_curr[i + subfr_idx] * xcitation_curr[i + subfr_idx];
521 
522     pitch_energy *= (pitch_gain * pitch_gain);
523 
524     innov_energy *= gain_code * gain_code;
525 
526     r_v = (FLOAT32)((pitch_energy - innov_energy) /
527                     (pitch_energy + innov_energy));
528 
529     for (i = 0; i < LEN_SUBFR; i++)
530       post_process_exc[i] = pitch_gain * xcitation_curr[i + subfr_idx];
531 
532     for (i = 0; i < LEN_SUBFR; i++)
533       xcitation_curr[i + subfr_idx] =
534           pitch_gain * xcitation_curr[i + subfr_idx] + gain_code * code[i];
535 
536     i = pitch_lag;
537     if (pitch_lag_frac > 2) i++;
538 
539     if (i > pitch_max) i = pitch_max;
540 
541     *ptr_pitch++ = i;
542     *ptr_pitch_gain++ = pitch_gain;
543 
544     voicing_factor = (FLOAT32)(0.5 * (1.0 - r_v));
545     gain_smooth_factor = stability_factor * voicing_factor;
546     gain_code0 = gain_code;
547     if (gain_code0 < st->gain_threshold) {
548       gain_code0 = (FLOAT32)(gain_code0 * 1.19);
549       if (gain_code0 > st->gain_threshold) gain_code0 = st->gain_threshold;
550     } else {
551       gain_code0 = (FLOAT32)(gain_code0 / 1.19);
552       if (gain_code0 < st->gain_threshold) gain_code0 = st->gain_threshold;
553     }
554     st->gain_threshold = gain_code0;
555     gain_smooth = (FLOAT32)((gain_smooth_factor * gain_code0) +
556                             ((1.0 - gain_smooth_factor) * gain_code));
557     for (i = 0; i < LEN_SUBFR; i++) code[i] *= gain_smooth;
558 
559     cpe = (FLOAT32)(0.125 * (1.0 + r_v));
560 
561     post_process_exc[0] += code[0] - (cpe * code[1]);
562 
563     for (i = 1; i < LEN_SUBFR - 1; i++)
564       post_process_exc[i] += code[i] - (cpe * (code[i - 1] + code[i + 1]));
565 
566     post_process_exc[LEN_SUBFR - 1] +=
567         code[LEN_SUBFR - 1] - (cpe * code[LEN_SUBFR - 2]);
568 
569     ixheaacd_synthesis_tool_float(ptr_lp_filt_coeff, post_process_exc,
570                                   &synth_signal[subfr_idx], LEN_SUBFR,
571                                   synth_temp);
572     memcpy(synth_temp, &synth_signal[subfr_idx + LEN_SUBFR - ORDER],
573            ORDER * sizeof(FLOAT32));
574 
575     ptr_lp_filt_coeff += (ORDER + 1);
576     subfr_nb++;
577   }
578 
579   ixheaacd_deemphsis_tool(synth_signal, len_subfr, synth_signal[-1]);
580 
581   memset(synth_temp + 16, 0, 128 * sizeof(FLOAT32));
582   ixheaacd_synthesis_tool_float1(ptr_lp_filt_coeff, synth_temp + 16, 128);
583 
584   ptr_lp_filt_coeff -= (2 * (ORDER + 1));
585   memcpy(st->lp_flt_coeff_a_prev, ptr_lp_filt_coeff,
586          (2 * (ORDER + 1)) * sizeof(FLOAT32));
587 
588   memcpy(st->exc_prev, synth_signal + len_subfr - (1 + fac_length),
589          (1 + fac_length) * sizeof(FLOAT32));
590 
591   memcpy(st->exc_prev + 1 + fac_length, synth_temp + 16,
592          fac_length * sizeof(FLOAT32));
593   ixheaacd_deemphsis_tool(st->exc_prev + 1 + fac_length, fac_length,
594                           synth_signal[len_subfr - 1]);
595 
596   return err;
597 }
598