Home | History | Annotate | Download | only in decoder
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    221 VOID ixheaacd_acelp_decode_pulses_per_track(WORD32 cb_index[], WORD16 code_bits,
    222                                             FLOAT32 code_vec[]) {
    223   WORD32 track_idx, index, ixheaacd_drc_offset, pos[6], i;
    224   memset(code_vec, 0, 64 * sizeof(FLOAT32));
    225 
    226   if (code_bits == 12) {
    227     for (track_idx = 0; track_idx < 4; track_idx += 2) {
    228       ixheaacd_drc_offset = cb_index[2 * (track_idx / 2)];
    229       index = cb_index[2 * (track_idx / 2) + 1];
    230       ixheaacd_d_acelp_decode_1p_n1(index, 4, 0, pos);
    231       ixheaacd_d_acelp_add_pulse(
    232           pos, 1, 2 * ixheaacd_drc_offset + track_idx / 2, code_vec);
    233     }
    234   } else if (code_bits == 16) {
    235     i = 0;
    236     ixheaacd_drc_offset = cb_index[i++];
    237     ixheaacd_drc_offset = (ixheaacd_drc_offset == 0) ? 1 : 3;
    238     for (track_idx = 0; track_idx < 4; track_idx++) {
    239       if (track_idx != ixheaacd_drc_offset) {
    240         index = cb_index[i++];
    241         ixheaacd_d_acelp_decode_1p_n1(index, 4, 0, pos);
    242         ixheaacd_d_acelp_add_pulse(pos, 1, track_idx, code_vec);
    243       }
    244     }
    245   } else if (code_bits == 20) {
    246     for (track_idx = 0; track_idx < 4; track_idx++) {
    247       index = cb_index[track_idx];
    248       ixheaacd_acelp_decode_1sp_per_track(index, 4, 0, track_idx, code_vec);
    249     }
    250   } else if (code_bits == 28) {
    251     for (track_idx = 0; track_idx < 2; track_idx++) {
    252       index = cb_index[track_idx];
    253       ixheaacd_acelp_decode_2sp_per_track(index, 4, 0, track_idx, code_vec);
    254     }
    255     for (track_idx = 2; track_idx < 4; track_idx++) {
    256       index = cb_index[track_idx];
    257       ixheaacd_acelp_decode_1sp_per_track(index, 4, 0, track_idx, code_vec);
    258     }
    259   } else if (code_bits == 36) {
    260     for (track_idx = 0; track_idx < 4; track_idx++) {
    261       index = cb_index[track_idx];
    262       ixheaacd_acelp_decode_2sp_per_track(index, 4, 0, track_idx, code_vec);
    263     }
    264   } else if (code_bits == 44) {
    265     for (track_idx = 0; track_idx < 2; track_idx++) {
    266       index = cb_index[track_idx];
    267       ixheaacd_acelp_decode_3sp_per_track(index, 4, 0, track_idx, code_vec);
    268     }
    269     for (track_idx = 2; track_idx < 4; track_idx++) {
    270       index = cb_index[track_idx];
    271       ixheaacd_acelp_decode_2sp_per_track(index, 4, 0, track_idx, code_vec);
    272     }
    273   } else if (code_bits == 52) {
    274     for (track_idx = 0; track_idx < 4; track_idx++) {
    275       index = cb_index[track_idx];
    276       ixheaacd_acelp_decode_3sp_per_track(index, 4, 0, track_idx, code_vec);
    277     }
    278   } else if (code_bits == 64) {
    279     for (track_idx = 0; track_idx < 4; track_idx++) {
    280       index = ((cb_index[track_idx] << 14) + cb_index[track_idx + 4]);
    281       ixheaacd_acelp_decode_4sp_per_track(index, track_idx, code_vec);
    282     }
    283   }
    284   return;
    285 }
    286 
    287 static void ixheaacd_acelp_decode_gains(WORD32 index, FLOAT32 code_vec[],
    288                                         FLOAT32 *pitch_gain,
    289                                         FLOAT32 *codebook_gain,
    290                                         FLOAT32 mean_exc_energy,
    291                                         FLOAT32 *energy) {
    292   WORD32 i;
    293   FLOAT32 avg_innov_energy, est_gain;
    294   const FLOAT32 *gain_table = ixheaacd_int_leave_gain_table;
    295 
    296   avg_innov_energy = 0.01f;
    297   for (i = 0; i < LEN_SUBFR; i++) {
    298     avg_innov_energy += code_vec[i] * code_vec[i];
    299   }
    300   *energy = avg_innov_energy;
    301 
    302   avg_innov_energy =
    303       (FLOAT32)(10.0 * log10(avg_innov_energy / (FLOAT32)LEN_SUBFR));
    304 
    305   est_gain = mean_exc_energy - avg_innov_energy;
    306 
    307   est_gain = (FLOAT32)pow(10.0, 0.05 * est_gain);
    308   *pitch_gain = gain_table[index * 2];
    309 
    310   *codebook_gain = gain_table[index * 2 + 1] * est_gain;
    311 
    312   return;
    313 }
    314 
    315 static VOID ixheaacd_cb_exc_calc(FLOAT32 xcitation_curr[], WORD32 pitch_lag,
    316                                  WORD32 frac) {
    317   WORD32 i, j;
    318   FLOAT32 s, *x0, *x1, *x2;
    319   const FLOAT32 *c1, *c2;
    320 
    321   x0 = &xcitation_curr[-pitch_lag];
    322   frac = -frac;
    323   if (frac < 0) {
    324     frac += UP_SAMP;
    325     x0--;
    326   }
    327   for (j = 0; j < LEN_SUBFR + 1; j++) {
    328     x1 = x0++;
    329     x2 = x1 + 1;
    330     c1 = &ixheaacd_interpol_filt[frac];
    331     c2 = &ixheaacd_interpol_filt[UP_SAMP - frac];
    332     s = 0.0;
    333     for (i = 0; i < INTER_LP_FIL_ORDER; i++, c1 += UP_SAMP, c2 += UP_SAMP) {
    334       s += (*x1--) * (*c1) + (*x2++) * (*c2);
    335     }
    336     xcitation_curr[j] = s;
    337   }
    338   return;
    339 }
    340 
    341 WORD32 ixheaacd_acelp_alias_cnx(ia_usac_data_struct *usac_data,
    342                                 ia_td_frame_data_struct *pstr_td_frame_data,
    343                                 WORD32 k, FLOAT32 lp_filt_coeff[],
    344                                 FLOAT32 stability_factor,
    345                                 ia_usac_lpd_decoder_handle st) {
    346   WORD32 i, subfr_idx;
    347   WORD32 pitch_lag, pitch_lag_frac, index, pitch_flag, pitch_lag_max;
    348   WORD32 pitch_lag_min = 0;
    349   FLOAT32 tmp, pitch_gain, gain_code, voicing_factor, r_v, innov_energy,
    350       pitch_energy, mean_ener_code;
    351   FLOAT32 gain_smooth, gain_code0, cpe;
    352   FLOAT32 code[LEN_SUBFR], synth_temp[128 + 16];
    353   FLOAT32 post_process_exc[LEN_SUBFR];
    354   FLOAT32 gain_smooth_factor;
    355   FLOAT32 *ptr_lp_filt_coeff;
    356   WORD32 pitch_min;
    357   WORD32 pitch_fr2;
    358   WORD32 pitch_fr1;
    359   WORD32 pitch_max;
    360   WORD32 subfr_nb = 0;
    361   WORD16 num_codebits_table[8] = {20, 28, 36, 44, 52, 64, 12, 16};
    362   FLOAT32 x[FAC_LENGTH], xn2[2 * FAC_LENGTH + 16];
    363   WORD32 int_x[FAC_LENGTH];
    364   WORD32 TTT;
    365   WORD32 len_subfr = usac_data->len_subfrm;
    366   WORD32 fac_length;
    367   WORD8 shiftp;
    368   WORD32 preshift;
    369   WORD32 *ptr_scratch = &usac_data->scratch_buffer[0];
    370   WORD32 *int_xn2 = &usac_data->x_ac_dec[0];
    371   WORD32 loop_count = 0;
    372   WORD32 core_mode = pstr_td_frame_data->acelp_core_mode;
    373   FLOAT32 *synth_signal =
    374       &usac_data->synth_buf[len_subfr * k + MAX_PITCH +
    375                             (((NUM_FRAMES * usac_data->num_subfrm) / 2) - 1) *
    376                                 LEN_SUBFR];
    377   FLOAT32 *xcitation_curr =
    378       &usac_data->exc_buf[len_subfr * k + MAX_PITCH + (INTER_LP_FIL_ORDER + 1)];
    379   FLOAT32 *ptr_pitch_gain =
    380       &usac_data->pitch_gain[k * usac_data->num_subfrm +
    381                              (((NUM_FRAMES * usac_data->num_subfrm) / 2) - 1)];
    382   WORD32 *ptr_pitch =
    383       &usac_data->pitch[k * usac_data->num_subfrm +
    384                         (((NUM_FRAMES * usac_data->num_subfrm) / 2) - 1)];
    385   WORD32 err = 0;
    386   fac_length = len_subfr / 2;
    387 
    388   if (st->mode_prev > 0) {
    389     for (i = 0; i < fac_length / 2; i++) {
    390       x[i] = st->fac_gain * pstr_td_frame_data->fac[k * FAC_LENGTH + 2 * i];
    391       x[fac_length / 2 + i] =
    392           st->fac_gain *
    393           pstr_td_frame_data->fac[k * FAC_LENGTH + fac_length - 2 * i - 1];
    394     }
    395     for (i = 0; i < fac_length / 8; i++) {
    396       x[i] *= st->fac_fd_data[2 * i];
    397       x[fac_length - i - 1] *= st->fac_fd_data[2 * i + 1];
    398     }
    399 
    400     preshift = 0;
    401     shiftp = ixheaacd_float2fix(x, int_x, fac_length);
    402 
    403     err =
    404         ixheaacd_acelp_mdct(int_x, int_xn2, &preshift, fac_length, ptr_scratch);
    405     if (err == -1) return err;
    406     ixheaacd_fix2float(int_xn2, xn2 + fac_length, fac_length, &shiftp,
    407                        &preshift);
    408 
    409     ixheaacd_vec_cnst_mul((2.0f / (FLOAT32)fac_length), xn2 + fac_length,
    410                           xn2 + fac_length, fac_length);
    411 
    412     memset(xn2, 0, fac_length * sizeof(FLOAT32));
    413 
    414     ixheaacd_lpc_wt_synthesis_tool(st->lp_flt_coeff_a_prev, xn2 + fac_length,
    415                                    fac_length);
    416 
    417     for (i = 0; i < 2 * fac_length; i++)
    418       xn2[i] += synth_signal[i - (2 * fac_length)];
    419 
    420     memcpy(synth_signal - fac_length, xn2 + fac_length,
    421            fac_length * sizeof(FLOAT32));
    422 
    423     tmp = 0.0;
    424     ixheaacd_preemphsis_tool_float(xn2, PREEMPH_FILT_FAC, 2 * fac_length, tmp);
    425 
    426     ptr_lp_filt_coeff = st->lp_flt_coeff_a_prev;
    427     TTT = fac_length % LEN_SUBFR;
    428     if (TTT != 0) {
    429       ixheaacd_residual_tool_float(
    430           ptr_lp_filt_coeff, &xn2[fac_length],
    431           &xcitation_curr[fac_length - (2 * fac_length)], TTT, 1);
    432       ptr_lp_filt_coeff += (ORDER + 1);
    433     }
    434 
    435     loop_count = (fac_length + TTT) / LEN_SUBFR;
    436     ixheaacd_residual_tool_float(ptr_lp_filt_coeff, &xn2[fac_length + TTT],
    437                                  &xcitation_curr[TTT - fac_length], LEN_SUBFR,
    438                                  loop_count);
    439   }
    440 
    441   for (i = 0; i < ORDER; i++)
    442     synth_temp[i] = synth_signal[i - ORDER] -
    443                     (PREEMPH_FILT_FAC * synth_signal[i - ORDER - 1]);
    444 
    445   i = (((st->fscale * TMIN) + (FSCALE_DENOM / 2)) / FSCALE_DENOM) - TMIN;
    446   pitch_min = TMIN + i;
    447   pitch_fr2 = TFR2 - i;
    448   pitch_fr1 = TFR1;
    449   pitch_max = TMAX + (6 * i);
    450 
    451   ptr_lp_filt_coeff = lp_filt_coeff;
    452   for (subfr_idx = 0; subfr_idx < len_subfr; subfr_idx += LEN_SUBFR) {
    453     pitch_flag = subfr_idx;
    454     if ((len_subfr == 256) && (subfr_idx == (2 * LEN_SUBFR))) {
    455       pitch_flag = 0;
    456     }
    457     index = pstr_td_frame_data->acb_index[k * 4 + subfr_nb];
    458 
    459     if (pitch_flag == 0) {
    460       if (index < (pitch_fr2 - pitch_min) * 4) {
    461         pitch_lag = pitch_min + (index / 4);
    462         pitch_lag_frac = index - (pitch_lag - pitch_min) * 4;
    463       } else if (index <
    464                  ((pitch_fr2 - pitch_min) * 4 + (pitch_fr1 - pitch_fr2) * 2)) {
    465         index -= (pitch_fr2 - pitch_min) * 4;
    466         pitch_lag = pitch_fr2 + (index / 2);
    467         pitch_lag_frac = index - (pitch_lag - pitch_fr2) * 2;
    468         pitch_lag_frac *= 2;
    469       } else {
    470         pitch_lag = index + pitch_fr1 - ((pitch_fr2 - pitch_min) * 4) -
    471                     ((pitch_fr1 - pitch_fr2) * 2);
    472         pitch_lag_frac = 0;
    473       }
    474       pitch_lag_min = pitch_lag - 8;
    475       if (pitch_lag_min < pitch_min) pitch_lag_min = pitch_min;
    476 
    477       pitch_lag_max = pitch_lag_min + 15;
    478       if (pitch_lag_max > pitch_max) {
    479         pitch_lag_max = pitch_max;
    480         pitch_lag_min = pitch_lag_max - 15;
    481       }
    482     } else {
    483       pitch_lag = pitch_lag_min + index / 4;
    484       pitch_lag_frac = index - (pitch_lag - pitch_lag_min) * 4;
    485     }
    486 
    487     ixheaacd_cb_exc_calc(&xcitation_curr[subfr_idx], pitch_lag, pitch_lag_frac);
    488 
    489     mean_ener_code =
    490         (((FLOAT32)pstr_td_frame_data->mean_energy[k]) * 12.0f) + 18.0f;
    491 
    492     if (pstr_td_frame_data->ltp_filtering_flag[k * 4 + subfr_nb] == 0) {
    493       for (i = 0; i < LEN_SUBFR; i++)
    494         code[i] = (FLOAT32)(0.18 * xcitation_curr[i - 1 + subfr_idx] +
    495                             0.64 * xcitation_curr[i + subfr_idx] +
    496                             0.18 * xcitation_curr[i + 1 + subfr_idx]);
    497 
    498       ixheaacd_mem_cpy(code, &xcitation_curr[subfr_idx], LEN_SUBFR);
    499     }
    500 
    501     ixheaacd_acelp_decode_pulses_per_track(
    502         &(pstr_td_frame_data->icb_index[k * 4 + subfr_nb][0]),
    503         num_codebits_table[core_mode], code);
    504 
    505     tmp = 0.0;
    506     ixheaacd_preemphsis_tool_float(code, TILT_CODE, LEN_SUBFR, tmp);
    507     i = pitch_lag;
    508     if (pitch_lag_frac > 2) i++;
    509     if (i >= 0) ixheaacd_acelp_pitch_sharpening(code, i);
    510 
    511     index = pstr_td_frame_data->gains[k * 4 + subfr_nb];
    512 
    513     ixheaacd_acelp_decode_gains(index, code, &pitch_gain, &gain_code,
    514                                 mean_ener_code, &innov_energy);
    515 
    516     pitch_energy = 0.0;
    517     for (i = 0; i < LEN_SUBFR; i++)
    518       pitch_energy +=
    519           xcitation_curr[i + subfr_idx] * xcitation_curr[i + subfr_idx];
    520 
    521     pitch_energy *= (pitch_gain * pitch_gain);
    522 
    523     innov_energy *= gain_code * gain_code;
    524 
    525     r_v = (FLOAT32)((pitch_energy - innov_energy) /
    526                     (pitch_energy + innov_energy));
    527 
    528     for (i = 0; i < LEN_SUBFR; i++)
    529       post_process_exc[i] = pitch_gain * xcitation_curr[i + subfr_idx];
    530 
    531     for (i = 0; i < LEN_SUBFR; i++)
    532       xcitation_curr[i + subfr_idx] =
    533           pitch_gain * xcitation_curr[i + subfr_idx] + gain_code * code[i];
    534 
    535     i = pitch_lag;
    536     if (pitch_lag_frac > 2) i++;
    537 
    538     if (i > pitch_max) i = pitch_max;
    539 
    540     *ptr_pitch++ = i;
    541     *ptr_pitch_gain++ = pitch_gain;
    542 
    543     voicing_factor = (FLOAT32)(0.5 * (1.0 - r_v));
    544     gain_smooth_factor = stability_factor * voicing_factor;
    545     gain_code0 = gain_code;
    546     if (gain_code0 < st->gain_threshold) {
    547       gain_code0 = (FLOAT32)(gain_code0 * 1.19);
    548       if (gain_code0 > st->gain_threshold) gain_code0 = st->gain_threshold;
    549     } else {
    550       gain_code0 = (FLOAT32)(gain_code0 / 1.19);
    551       if (gain_code0 < st->gain_threshold) gain_code0 = st->gain_threshold;
    552     }
    553     st->gain_threshold = gain_code0;
    554     gain_smooth = (FLOAT32)((gain_smooth_factor * gain_code0) +
    555                             ((1.0 - gain_smooth_factor) * gain_code));
    556     for (i = 0; i < LEN_SUBFR; i++) code[i] *= gain_smooth;
    557 
    558     cpe = (FLOAT32)(0.125 * (1.0 + r_v));
    559 
    560     post_process_exc[0] += code[0] - (cpe * code[1]);
    561 
    562     for (i = 1; i < LEN_SUBFR - 1; i++)
    563       post_process_exc[i] += code[i] - (cpe * (code[i - 1] + code[i + 1]));
    564 
    565     post_process_exc[LEN_SUBFR - 1] +=
    566         code[LEN_SUBFR - 1] - (cpe * code[LEN_SUBFR - 2]);
    567 
    568     ixheaacd_synthesis_tool_float(ptr_lp_filt_coeff, post_process_exc,
    569                                   &synth_signal[subfr_idx], LEN_SUBFR,
    570                                   synth_temp);
    571     memcpy(synth_temp, &synth_signal[subfr_idx + LEN_SUBFR - ORDER],
    572            ORDER * sizeof(FLOAT32));
    573 
    574     ptr_lp_filt_coeff += (ORDER + 1);
    575     subfr_nb++;
    576   }
    577 
    578   ixheaacd_deemphsis_tool(synth_signal, len_subfr, synth_signal[-1]);
    579 
    580   memset(synth_temp + 16, 0, 128 * sizeof(FLOAT32));
    581   ixheaacd_synthesis_tool_float1(ptr_lp_filt_coeff, synth_temp + 16, 128);
    582 
    583   ptr_lp_filt_coeff -= (2 * (ORDER + 1));
    584   memcpy(st->lp_flt_coeff_a_prev, ptr_lp_filt_coeff,
    585          (2 * (ORDER + 1)) * sizeof(FLOAT32));
    586 
    587   memcpy(st->exc_prev, synth_signal + len_subfr - (1 + fac_length),
    588          (1 + fac_length) * sizeof(FLOAT32));
    589 
    590   memcpy(st->exc_prev + 1 + fac_length, synth_temp + 16,
    591          fac_length * sizeof(FLOAT32));
    592   ixheaacd_deemphsis_tool(st->exc_prev + 1 + fac_length, fac_length,
    593                           synth_signal[len_subfr - 1]);
    594 
    595   return err;
    596 }
    597