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 <math.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 
     25 #include <ixheaacd_type_def.h>
     26 #include <ixheaacd_interface.h>
     27 
     28 #include "ixheaacd_bitbuffer.h"
     29 #include "ixheaacd_interface.h"
     30 
     31 #include "ixheaacd_tns_usac.h"
     32 #include "ixheaacd_cnst.h"
     33 #include "ixheaacd_acelp_info.h"
     34 
     35 #include "ixheaacd_td_mdct.h"
     36 
     37 #include "ixheaacd_sbrdecsettings.h"
     38 #include "ixheaacd_info.h"
     39 #include "ixheaacd_sbr_common.h"
     40 #include "ixheaacd_drc_data_struct.h"
     41 #include "ixheaacd_drc_dec.h"
     42 #include "ixheaacd_sbrdecoder.h"
     43 #include "ixheaacd_mps_polyphase.h"
     44 #include "ixheaacd_sbr_const.h"
     45 #include "ixheaacd_main.h"
     46 #include "ixheaacd_arith_dec.h"
     47 #include "ixheaacd_windows.h"
     48 
     49 #include "ixheaacd_vec_baisc_ops.h"
     50 #include "ixheaacd_constants.h"
     51 #include "ixheaacd_function_selector.h"
     52 #include <ixheaacd_type_def.h>
     53 #include <ixheaacd_basic_ops32.h>
     54 #include <ixheaacd_basic_ops40.h>
     55 
     56 #include "ixheaacd_func_def.h"
     57 
     58 #include "ixheaacd_windows.h"
     59 
     60 extern const WORD32 ixheaacd_pre_post_twid_cos_512[512];
     61 extern const WORD32 ixheaacd_pre_post_twid_sin_512[512];
     62 extern const WORD32 ixheaacd_pre_post_twid_cos_384[384];
     63 extern const WORD32 ixheaacd_pre_post_twid_sin_384[384];
     64 extern const WORD32 ixheaacd_pre_post_twid_cos_64[64];
     65 extern const WORD32 ixheaacd_pre_post_twid_sin_64[64];
     66 extern const WORD32 ixheaacd_pre_post_twid_cos_48[48];
     67 extern const WORD32 ixheaacd_pre_post_twid_sin_48[48];
     68 extern const FLOAT64 ixheaacd_power_10_table[28];
     69 
     70 #define ABS(A) ((A) < 0 ? (-A) : (A))
     71 
     72 static WORD32 ixheaacd_calc_max_spectralline(WORD32 *p_in_ibuffer, WORD32 n) {
     73   WORD32 k, shiftp, itemp = 0;
     74   for (k = 0; k < n; k++) {
     75     if (ixheaacd_abs32_sat(p_in_ibuffer[k]) > itemp)
     76       itemp = ixheaacd_abs32_sat(p_in_ibuffer[k]);
     77   }
     78 
     79   shiftp = ixheaacd_norm32(itemp);
     80 
     81   return (shiftp);
     82 }
     83 
     84 static void ixheaacd_normalize(WORD32 *buff, WORD32 shift, WORD len) {
     85   WORD32 i;
     86 
     87   for (i = 0; i < len; i++) {
     88     buff[i] = buff[i] << shift;
     89   }
     90 }
     91 
     92 static FLOAT32 ixheaacd_pow10(WORD32 input) {
     93   FLOAT32 output = 1;
     94   while (input > 0) {
     95     output *= 10;
     96     input--;
     97   }
     98   return (output);
     99 }
    100 
    101 void ixheaacd_calc_pre_twid_dec(WORD32 *ptr_x, WORD32 *r_ptr, WORD32 *i_ptr,
    102                                 WORD32 nlength, const WORD32 *cos_ptr,
    103                                 const WORD32 *sin_ptr) {
    104   WORD32 i;
    105   WORD32 *ptr_y;
    106 
    107   ptr_y = &ptr_x[2 * nlength - 1];
    108 
    109   for (i = 0; i < nlength; i++) {
    110     *r_ptr++ = ((ixheaacd_mult32(ixheaacd_negate32_sat(*ptr_x), (*cos_ptr)) -
    111                  ixheaacd_mult32((*ptr_y), (*sin_ptr))));
    112     *i_ptr++ = ((ixheaacd_mult32((*ptr_y), (*cos_ptr++)) -
    113                  ixheaacd_mult32((*ptr_x), (*sin_ptr++))));
    114     ptr_x += 2;
    115     ptr_y -= 2;
    116   }
    117 }
    118 
    119 void ixheaacd_calc_post_twid_dec(WORD32 *xptr, WORD32 *r_ptr, WORD32 *i_ptr,
    120                                  WORD32 nlength, const WORD32 *cos_ptr,
    121                                  const WORD32 *sin_ptr
    122 
    123                                  ) {
    124   WORD32 i;
    125   WORD32 *yptr;
    126 
    127   yptr = &xptr[2 * nlength - 1];
    128 
    129   for (i = 0; i < nlength; i++) {
    130     *xptr = (-(ixheaacd_mult32((r_ptr[i]), (*cos_ptr)) -
    131                ixheaacd_mult32((i_ptr[i]), (*sin_ptr))));
    132     *yptr = (-(ixheaacd_mult32((i_ptr[i]), (*cos_ptr++)) +
    133                ixheaacd_mult32((r_ptr[i]), (*sin_ptr++))));
    134     xptr += 2;
    135     yptr -= 2;
    136   }
    137 }
    138 
    139 static void ixheaacd_fft_based_imdct(WORD32 *data, WORD32 npoints,
    140                                      WORD32 *preshift, WORD32 *tmp_data) {
    141   WORD32 *data_r;
    142   WORD32 *data_i;
    143   WORD32 nlength = npoints >> 1;
    144   const WORD32 *cos_ptr;
    145   const WORD32 *sin_ptr;
    146 
    147   data_r = tmp_data;
    148   data_i = tmp_data + 512;
    149 
    150   if (nlength == 512) {
    151     cos_ptr = ixheaacd_pre_post_twid_cos_512;
    152     sin_ptr = ixheaacd_pre_post_twid_sin_512;
    153   } else if (nlength == 384) {
    154     cos_ptr = ixheaacd_pre_post_twid_cos_384;
    155     sin_ptr = ixheaacd_pre_post_twid_sin_384;
    156   } else if (nlength == 64) {
    157     cos_ptr = ixheaacd_pre_post_twid_cos_64;
    158     sin_ptr = ixheaacd_pre_post_twid_sin_64;
    159   } else if (nlength == 48) {
    160     cos_ptr = ixheaacd_pre_post_twid_cos_48;
    161     sin_ptr = ixheaacd_pre_post_twid_sin_48;
    162   } else {
    163     cos_ptr = ixheaacd_pre_post_twid_cos_48;
    164     sin_ptr = ixheaacd_pre_post_twid_sin_48;
    165   }
    166 
    167   (*ixheaacd_calc_pre_twid)(data, data_r, data_i, nlength, cos_ptr, sin_ptr);
    168   ixheaacd_complex_fft(data_r, data_i, nlength, 1, preshift);
    169   (*ixheaacd_calc_post_twid)(data, data_r, data_i, nlength, cos_ptr, sin_ptr);
    170 }
    171 
    172 #define N_LONG_LEN_MAX 1024
    173 
    174 void ixheaacd_acelp_imdct(WORD32 *imdct_in, WORD32 npoints, WORD8 *qshift,
    175                           WORD32 *tmp_data) {
    176   WORD32 preshift = 0;
    177   WORD32 i;
    178   WORD32 k = (npoints / 2);
    179 
    180   while (((k & 1) == 0) & (k != 1)) {
    181     k = k >> 1;
    182     preshift++;
    183   }
    184 
    185   if ((k != 1)) {
    186     for (i = 0; i < (npoints / 2); i++) {
    187       imdct_in[i] = (imdct_in[i] / 3) << 1;
    188     }
    189     preshift++;
    190   }
    191 
    192   ixheaacd_fft_based_imdct(imdct_in, npoints / 2, &preshift, tmp_data);
    193   preshift += 2;
    194   *qshift -= preshift;
    195 }
    196 
    197 WORD8 ixheaacd_cal_fac_data(ia_usac_data_struct *usac_data, WORD32 i_ch,
    198                             WORD32 n_long, WORD32 lfac, WORD32 *fac_idata) {
    199   WORD32 gain_fac, scale, k, *i_aq, itemp = 0, *izir;
    200   WORD32 int_aq[ORDER + 1], intzir[2 * LEN_FRAME], x_in[FAC_LENGTH];
    201   FLOAT32 gain, ztemp, ftemp, pow10, rem10;
    202   FLOAT32 qfac1;
    203   WORD8 qshift1, qshift2 = 0, qshift3 = 0;
    204   WORD32 quo, rem, preshift = 0;
    205 
    206   FLOAT32 *last_lpc = usac_data->lpc_prev[i_ch];
    207   FLOAT32 *acelp_in = usac_data->acelp_in[i_ch];
    208   WORD32 *fac_data = usac_data->fac_data[i_ch];
    209   WORD32 *ptr_scratch = &usac_data->scratch_buffer[0];
    210 
    211   quo = fac_data[0] / 28;
    212   rem = fac_data[0] % 28;
    213   pow10 = ixheaacd_pow10(quo);
    214   rem10 = (FLOAT32)ixheaacd_power_10_table[rem];
    215 
    216   gain = pow10 * rem10;
    217   scale = (WORD32)(ixheaacd_norm32((WORD32)((ABS(gain) + 1))));
    218   gain_fac = (WORD32)(gain * (FLOAT32)((WORD64)1 << scale));
    219   scale += 4;
    220   qfac1 = 1.0f / (gain);
    221 
    222   if (acelp_in != NULL) {
    223     izir = intzir;
    224     ftemp = 0.0;
    225     for (k = 0; k < n_long / 4; k++) {
    226       ztemp = acelp_in[k] * (qfac1);
    227       if (ABS(ztemp) > ftemp) ftemp = ABS(ztemp);
    228     }
    229 
    230     itemp = (WORD32)(ftemp);
    231     qshift3 = ixheaacd_norm32(itemp);
    232 
    233     for (k = 0; k < n_long / 4; k++) {
    234       izir[k] =
    235           (WORD32)((acelp_in[k] * (qfac1)) * (FLOAT32)((WORD64)1 << qshift3));
    236     }
    237   } else
    238     izir = NULL;
    239 
    240   if (last_lpc != NULL) {
    241     ftemp = 0.0;
    242     i_aq = int_aq;
    243     for (k = 0; k < ORDER + 1; k++) {
    244       if (ABS(last_lpc[k]) > ftemp) ftemp = ABS(last_lpc[k]);
    245     }
    246 
    247     itemp = (WORD32)(ftemp);
    248     qshift2 = ixheaacd_norm32(itemp);
    249 
    250     for (k = 0; k < ORDER + 1; k++) {
    251       i_aq[k] = (WORD32)(last_lpc[k] * (FLOAT32)((WORD64)1 << qshift2));
    252     }
    253   } else
    254     i_aq = NULL;
    255 
    256   for (k = 0; k < lfac; k++) {
    257     if (ABS(fac_data[k + 1]) > itemp) itemp = ABS(fac_data[k + 1]);
    258   }
    259 
    260   qshift1 = ixheaacd_norm32(itemp);
    261 
    262   for (k = 0; k < lfac; k++) {
    263     fac_data[k + 1] =
    264         (WORD32)(fac_data[k + 1] * (FLOAT32)((WORD64)1 << qshift1));
    265   }
    266 
    267   for (k = 0; k < lfac / 2; k++) {
    268     x_in[k] = fac_data[2 * k + 1];
    269     x_in[lfac / 2 + k] = fac_data[lfac - 2 * k];
    270   }
    271 
    272   ixheaacd_fr_alias_cnx_fix(x_in, n_long / 4, lfac, i_aq, izir, fac_idata + 16,
    273                             &qshift1, qshift2, qshift3, &preshift, ptr_scratch);
    274   preshift += 4;
    275 
    276   if (acelp_in != NULL) {
    277     for (k = 0; k < 2 * lfac; k++) {
    278       fac_idata[k] =
    279           ixheaacd_mul32_sh(fac_idata[k + 16], gain_fac, (WORD8)(scale));
    280     }
    281   }
    282   return (qshift1 - preshift);
    283 }
    284 
    285 static WORD32 ixheaacd_fd_imdct_short(ia_usac_data_struct *usac_data,
    286                                       WORD32 i_ch, WORD32 *fac_data_out,
    287                                       offset_lengths *ixheaacd_drc_offset,
    288                                       WORD8 fac_q) {
    289   FLOAT32 qfac;
    290   WORD32 overlap_data_buf[2 * N_LONG_LEN_MAX] = {0};
    291   WORD32 *window_short, k, *window_short_prev_ptr;
    292   WORD32 *overlap_data, *fp;
    293 
    294   WORD32 *p_overlap_ibuffer = usac_data->overlap_data_ptr[i_ch];
    295   WORD32 *p_in_ibuffer = usac_data->coef_fix[i_ch];
    296   FLOAT32 *p_out_buffer = usac_data->time_sample_vector[i_ch];
    297   WORD32 *p_out_ibuffer = usac_data->output_data_ptr[i_ch];
    298   WORD32 *scratch_mem = usac_data->scratch_buffer;
    299   WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
    300   WORD32 fac_apply = usac_data->fac_data_present[i_ch];
    301   WORD8 shiftp, input_q, output_q, shift_olap = 14;
    302   WORD32 max_shift;
    303 
    304   WORD32 window_select = usac_data->window_shape[i_ch];
    305   WORD32 window_select_prev = usac_data->window_shape_prev[i_ch];
    306   ia_usac_lpd_decoder_handle st = usac_data->str_tddec[i_ch];
    307   WORD32 err_code = 0;
    308 
    309   max_shift =
    310       ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
    311   ixheaacd_normalize(p_in_ibuffer, max_shift, ixheaacd_drc_offset->n_long);
    312   shiftp = max_shift + 6;
    313   input_q = shiftp;
    314 
    315   memcpy(overlap_data_buf, p_overlap_ibuffer,
    316          sizeof(WORD32) * ixheaacd_drc_offset->n_long);
    317   overlap_data = overlap_data_buf;
    318 
    319   fp = overlap_data + ixheaacd_drc_offset->n_flat_ls;
    320 
    321   for (k = 0; k < 8; k++) {
    322     shiftp = input_q;
    323     ixheaacd_acelp_imdct(p_in_ibuffer + (k * ixheaacd_drc_offset->n_short),
    324                          2 * ixheaacd_drc_offset->n_short, &shiftp,
    325                          scratch_mem);
    326   }
    327 
    328   max_shift =
    329       ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
    330   ixheaacd_normalize(p_in_ibuffer, max_shift - 1, ixheaacd_drc_offset->n_long);
    331   shiftp += max_shift - 1;
    332 
    333   err_code = ixheaacd_calc_window(&window_short, ixheaacd_drc_offset->n_short,
    334                                   window_select);
    335   if (err_code == -1) return err_code;
    336   err_code =
    337       ixheaacd_calc_window(&window_short_prev_ptr,
    338                            ixheaacd_drc_offset->n_trans_ls, window_select_prev);
    339   if (err_code == -1) return err_code;
    340 
    341   if (fac_apply)
    342     ixheaacd_windowing_short1(p_in_ibuffer + ixheaacd_drc_offset->n_short / 2,
    343                               window_short_prev_ptr, fp, ixheaacd_drc_offset,
    344                               shiftp, shift_olap);
    345 
    346   else
    347     ixheaacd_windowing_short2(p_in_ibuffer + ixheaacd_drc_offset->n_short / 2,
    348                               window_short_prev_ptr, fp, ixheaacd_drc_offset,
    349                               shiftp, shift_olap);
    350 
    351   output_q = ixheaacd_windowing_short3(
    352       p_in_ibuffer, window_short + ixheaacd_drc_offset->n_short - 1,
    353       fp + ixheaacd_drc_offset->n_short, ixheaacd_drc_offset->n_short, shiftp,
    354       shift_olap);
    355   p_in_ibuffer += ixheaacd_drc_offset->n_short;
    356   fp += ixheaacd_drc_offset->n_short;
    357   window_short_prev_ptr = window_short;
    358 
    359   for (k = 1; k < 7; k++) {
    360     output_q = ixheaacd_windowing_short4(
    361         p_in_ibuffer, window_short_prev_ptr, fp,
    362         window_short_prev_ptr + ixheaacd_drc_offset->n_short - 1,
    363         ixheaacd_drc_offset->n_short, 1, shiftp, shift_olap, output_q);
    364     p_in_ibuffer += ixheaacd_drc_offset->n_short;
    365     fp += ixheaacd_drc_offset->n_short;
    366     window_short_prev_ptr = window_short;
    367   }
    368 
    369   output_q = ixheaacd_windowing_short4(
    370       p_in_ibuffer, window_short_prev_ptr, fp,
    371       window_short_prev_ptr + ixheaacd_drc_offset->n_short - 1,
    372       ixheaacd_drc_offset->n_short, 0, shiftp, shift_olap, output_q);
    373   p_in_ibuffer += ixheaacd_drc_offset->n_short;
    374   fp += ixheaacd_drc_offset->n_short;
    375 
    376   if (fac_apply) {
    377     ixheaacd_combine_fac(overlap_data + ixheaacd_drc_offset->n_flat_ls +
    378                              ixheaacd_drc_offset->lfac,
    379                          fac_data_out,
    380                          overlap_data + ixheaacd_drc_offset->n_flat_ls +
    381                              ixheaacd_drc_offset->lfac,
    382                          2 * ixheaacd_drc_offset->lfac, output_q, fac_q);
    383   }
    384   memset(overlap_data + 2 * ixheaacd_drc_offset->n_long -
    385              ixheaacd_drc_offset->n_flat_ls,
    386          0, sizeof(WORD32) * ixheaacd_drc_offset->n_flat_ls);
    387   ixheaacd_scale_down(overlap_data, overlap_data,
    388                       ixheaacd_drc_offset->n_flat_ls, shift_olap, output_q);
    389 
    390   ixheaacd_scale_down(p_overlap_ibuffer,
    391                       overlap_data + ixheaacd_drc_offset->n_long,
    392                       ixheaacd_drc_offset->n_long, output_q, shift_olap);
    393   ixheaacd_scale_down(p_out_ibuffer, overlap_data, ixheaacd_drc_offset->n_long,
    394                       output_q, 15);
    395 
    396   if (td_frame_prev) {
    397     qfac = 1.0f / (FLOAT32)(1 << 15);
    398 
    399     for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
    400       p_out_buffer[k] = ((FLOAT32)p_out_ibuffer[k]) * qfac;
    401     }
    402     err_code = ixheaacd_lpd_bpf_fix(usac_data, 1, p_out_buffer, st);
    403     if (err_code != 0) return err_code;
    404 
    405     for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
    406       p_out_ibuffer[k] = (WORD32)(p_out_buffer[k] * (1 << 15));
    407     }
    408   }
    409 
    410   return 0;
    411 }
    412 
    413 static WORD32 ixheaacd_fd_imdct_long(ia_usac_data_struct *usac_data,
    414                                      WORD32 i_ch, WORD32 *fac_idata,
    415                                      offset_lengths *ixheaacd_drc_offset,
    416                                      WORD8 fac_q) {
    417   FLOAT32 qfac;
    418   WORD32 *window_long_prev, k, i, *window_short_prev_ptr;
    419 
    420   WORD32 *p_in_ibuffer = usac_data->coef_fix[i_ch];
    421   WORD32 *p_overlap_ibuffer = usac_data->overlap_data_ptr[i_ch];
    422   WORD32 *p_out_ibuffer = usac_data->output_data_ptr[i_ch];
    423   FLOAT32 *p_out_buffer = usac_data->time_sample_vector[i_ch];
    424   WORD32 *scratch_mem = usac_data->scratch_buffer;
    425   WORD32 n_long = usac_data->ccfl;
    426   WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
    427   WORD32 fac_apply = usac_data->fac_data_present[i_ch];
    428   WORD8 shiftp, output_q = 0, shift_olap = 14;
    429   WORD32 max_shift;
    430 
    431   WORD32 window_sequence = usac_data->window_sequence[i_ch];
    432   WORD32 window_select_prev = usac_data->window_shape_prev[i_ch];
    433   ia_usac_lpd_decoder_handle st = usac_data->str_tddec[i_ch];
    434 
    435   WORD32 err_code = 0;
    436 
    437   max_shift =
    438       ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
    439   ixheaacd_normalize(p_in_ibuffer, max_shift, ixheaacd_drc_offset->n_long);
    440   shiftp = max_shift + 6;
    441 
    442   ixheaacd_acelp_imdct(p_in_ibuffer, 2 * ixheaacd_drc_offset->n_long, &shiftp,
    443                        scratch_mem);
    444 
    445   max_shift =
    446       ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
    447   ixheaacd_normalize(p_in_ibuffer, max_shift - 1, ixheaacd_drc_offset->n_long);
    448   shiftp += max_shift - 1;
    449 
    450   switch (window_sequence) {
    451     case ONLY_LONG_SEQUENCE:
    452     case LONG_START_SEQUENCE:
    453       err_code = ixheaacd_calc_window(
    454           &window_long_prev, ixheaacd_drc_offset->n_long, window_select_prev);
    455       if (err_code == -1) return err_code;
    456       output_q = ixheaacd_windowing_long1(
    457           p_in_ibuffer + n_long / 2, p_overlap_ibuffer, window_long_prev,
    458           window_long_prev + ixheaacd_drc_offset->n_long - 1, p_out_ibuffer,
    459           ixheaacd_drc_offset->n_long, shiftp, shift_olap);
    460       break;
    461 
    462     case STOP_START_SEQUENCE:
    463     case LONG_STOP_SEQUENCE:
    464       err_code = ixheaacd_calc_window(&window_short_prev_ptr,
    465                                       ixheaacd_drc_offset->n_trans_ls,
    466                                       window_select_prev);
    467       if (err_code == -1) return err_code;
    468       if (fac_apply) {
    469         output_q = ixheaacd_windowing_long2(
    470             p_in_ibuffer + n_long / 2, window_short_prev_ptr, fac_idata,
    471             p_overlap_ibuffer, p_out_ibuffer, ixheaacd_drc_offset, shiftp,
    472             shift_olap, fac_q);
    473       } else {
    474         output_q = ixheaacd_windowing_long3(
    475             p_in_ibuffer + n_long / 2, window_short_prev_ptr, p_overlap_ibuffer,
    476             p_out_ibuffer,
    477             window_short_prev_ptr + ixheaacd_drc_offset->n_trans_ls - 1,
    478             ixheaacd_drc_offset, shiftp, shift_olap);
    479       }
    480       break;
    481   }
    482 
    483   for (i = 0; i < ixheaacd_drc_offset->n_long / 2; i++) {
    484     p_overlap_ibuffer[ixheaacd_drc_offset->n_long / 2 + i] =
    485         -p_in_ibuffer[i] >> (shiftp - shift_olap);
    486     p_overlap_ibuffer[ixheaacd_drc_offset->n_long / 2 - i - 1] =
    487         -p_in_ibuffer[i] >> (shiftp - shift_olap);
    488   }
    489 
    490   ixheaacd_scale_down(p_out_ibuffer, p_out_ibuffer, ixheaacd_drc_offset->n_long,
    491                       output_q, 15);
    492 
    493   if (td_frame_prev) {
    494     qfac = 1.0f / (FLOAT32)(1 << 15);
    495 
    496     for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
    497       p_out_buffer[k] = ((FLOAT32)p_out_ibuffer[k]) * qfac;
    498     }
    499     err_code = ixheaacd_lpd_bpf_fix(usac_data, 0, p_out_buffer, st);
    500     if (err_code != 0) return err_code;
    501 
    502     for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
    503       p_out_ibuffer[k] = (WORD32)(p_out_buffer[k] * (1 << 15));
    504     }
    505   }
    506 
    507   return 0;
    508 }
    509 
    510 WORD32 ixheaacd_fd_frm_dec(ia_usac_data_struct *usac_data, WORD32 i_ch) {
    511   WORD32 fac_idata[2 * FAC_LENGTH + 16];
    512   offset_lengths ixheaacd_drc_offset;
    513   WORD8 fac_q = 0;
    514   WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
    515   WORD32 fac_apply = usac_data->fac_data_present[i_ch];
    516   WORD32 window_sequence = usac_data->window_sequence[i_ch];
    517   ixheaacd_drc_offset.n_long = usac_data->ccfl;
    518   ixheaacd_drc_offset.n_short = ixheaacd_drc_offset.n_long >> 3;
    519 
    520   memset(fac_idata, 0, sizeof(fac_idata));
    521 
    522   if (td_frame_prev) {
    523     if (window_sequence == EIGHT_SHORT_SEQUENCE) {
    524       ixheaacd_drc_offset.lfac = ixheaacd_drc_offset.n_long >> 4;
    525     } else {
    526       ixheaacd_drc_offset.lfac = ixheaacd_drc_offset.n_long >> 3;
    527     }
    528     ixheaacd_drc_offset.n_flat_ls =
    529         (ixheaacd_drc_offset.n_long - (ixheaacd_drc_offset.lfac) * 2) >> 1;
    530 
    531     ixheaacd_drc_offset.n_trans_ls = (ixheaacd_drc_offset.lfac) << 1;
    532   } else {
    533     ixheaacd_drc_offset.lfac = FAC_LENGTH;
    534     ixheaacd_drc_offset.n_flat_ls =
    535         (ixheaacd_drc_offset.n_long - ixheaacd_drc_offset.n_short) >> 1;
    536     ixheaacd_drc_offset.n_trans_ls = ixheaacd_drc_offset.n_short;
    537   }
    538 
    539   if (fac_apply)
    540     fac_q = ixheaacd_cal_fac_data(usac_data, i_ch, ixheaacd_drc_offset.n_long,
    541                                   ixheaacd_drc_offset.lfac, fac_idata);
    542 
    543   if (window_sequence != EIGHT_SHORT_SEQUENCE)
    544     ixheaacd_fd_imdct_long(usac_data, i_ch, fac_idata, &ixheaacd_drc_offset,
    545                            fac_q);
    546 
    547   else
    548     ixheaacd_fd_imdct_short(usac_data, i_ch, fac_idata, &ixheaacd_drc_offset,
    549                             fac_q);
    550 
    551   return 0;
    552 }