• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ixheaacd_calc_max_spectralline(WORD32 * p_in_ibuffer,WORD32 n)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 
ixheaacd_normalize(WORD32 * buff,WORD32 shift,WORD len)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 
ixheaacd_pow10(WORD32 input)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 
ixheaacd_calc_pre_twid_dec(WORD32 * ptr_x,WORD32 * r_ptr,WORD32 * i_ptr,WORD32 nlength,const WORD32 * cos_ptr,const WORD32 * sin_ptr)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 
ixheaacd_calc_post_twid_dec(WORD32 * xptr,WORD32 * r_ptr,WORD32 * i_ptr,WORD32 nlength,const WORD32 * cos_ptr,const WORD32 * sin_ptr)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 
ixheaacd_fft_based_imdct(WORD32 * data,WORD32 npoints,WORD32 * preshift,WORD32 * tmp_data)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 
ixheaacd_acelp_imdct(WORD32 * imdct_in,WORD32 npoints,WORD8 * qshift,WORD32 * tmp_data)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 
ixheaacd_cal_fac_data(ia_usac_data_struct * usac_data,WORD32 i_ch,WORD32 n_long,WORD32 lfac,WORD32 * fac_idata)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 (ixheaacd_abs32_sat(fac_data[k + 1]) > itemp)
258       itemp = ixheaacd_abs32_sat(fac_data[k + 1]);
259   }
260 
261   qshift1 = ixheaacd_norm32(itemp);
262 
263   for (k = 0; k < lfac; k++) {
264     fac_data[k + 1] =
265         (WORD32)(fac_data[k + 1] * (FLOAT32)((WORD64)1 << qshift1));
266   }
267 
268   for (k = 0; k < lfac / 2; k++) {
269     x_in[k] = fac_data[2 * k + 1];
270     x_in[lfac / 2 + k] = fac_data[lfac - 2 * k];
271   }
272 
273   ixheaacd_fr_alias_cnx_fix(x_in, n_long / 4, lfac, i_aq, izir, fac_idata + 16,
274                             &qshift1, qshift2, qshift3, &preshift, ptr_scratch);
275   preshift += 4;
276 
277   if (acelp_in != NULL) {
278     for (k = 0; k < 2 * lfac; k++) {
279       fac_idata[k] =
280           ixheaacd_mul32_sh(fac_idata[k + 16], gain_fac, (WORD8)(scale));
281     }
282   }
283   return (qshift1 - preshift);
284 }
285 
ixheaacd_fd_imdct_short(ia_usac_data_struct * usac_data,WORD32 i_ch,WORD32 * fac_data_out,offset_lengths * ixheaacd_drc_offset,WORD8 fac_q)286 static WORD32 ixheaacd_fd_imdct_short(ia_usac_data_struct *usac_data,
287                                       WORD32 i_ch, WORD32 *fac_data_out,
288                                       offset_lengths *ixheaacd_drc_offset,
289                                       WORD8 fac_q) {
290   FLOAT32 qfac;
291   WORD32 overlap_data_buf[2 * N_LONG_LEN_MAX] = {0};
292   WORD32 *window_short, k, *window_short_prev_ptr;
293   WORD32 *overlap_data, *fp;
294 
295   WORD32 *p_overlap_ibuffer = usac_data->overlap_data_ptr[i_ch];
296   WORD32 *p_in_ibuffer = usac_data->coef_fix[i_ch];
297   FLOAT32 *p_out_buffer = usac_data->time_sample_vector[i_ch];
298   WORD32 *p_out_ibuffer = usac_data->output_data_ptr[i_ch];
299   WORD32 *scratch_mem = usac_data->scratch_buffer;
300   WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
301   WORD32 fac_apply = usac_data->fac_data_present[i_ch];
302   WORD8 shiftp, input_q, output_q, shift_olap = 14;
303   WORD32 max_shift;
304 
305   WORD32 window_select = usac_data->window_shape[i_ch];
306   WORD32 window_select_prev = usac_data->window_shape_prev[i_ch];
307   ia_usac_lpd_decoder_handle st = usac_data->str_tddec[i_ch];
308   WORD32 err_code = 0;
309 
310   max_shift =
311       ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
312   ixheaacd_normalize(p_in_ibuffer, max_shift, ixheaacd_drc_offset->n_long);
313   shiftp = max_shift + 6;
314   input_q = shiftp;
315 
316   memcpy(overlap_data_buf, p_overlap_ibuffer,
317          sizeof(WORD32) * ixheaacd_drc_offset->n_long);
318   overlap_data = overlap_data_buf;
319 
320   fp = overlap_data + ixheaacd_drc_offset->n_flat_ls;
321 
322   for (k = 0; k < 8; k++) {
323     shiftp = input_q;
324     ixheaacd_acelp_imdct(p_in_ibuffer + (k * ixheaacd_drc_offset->n_short),
325                          2 * ixheaacd_drc_offset->n_short, &shiftp,
326                          scratch_mem);
327   }
328 
329   max_shift =
330       ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
331   ixheaacd_normalize(p_in_ibuffer, max_shift - 1, ixheaacd_drc_offset->n_long);
332   shiftp += max_shift - 1;
333 
334   err_code = ixheaacd_calc_window(&window_short, ixheaacd_drc_offset->n_short,
335                                   window_select);
336   if (err_code == -1) return err_code;
337   err_code =
338       ixheaacd_calc_window(&window_short_prev_ptr,
339                            ixheaacd_drc_offset->n_trans_ls, window_select_prev);
340   if (err_code == -1) return err_code;
341 
342   if (fac_apply)
343     ixheaacd_windowing_short1(p_in_ibuffer + ixheaacd_drc_offset->n_short / 2,
344                               window_short_prev_ptr, fp, ixheaacd_drc_offset,
345                               shiftp, shift_olap);
346 
347   else
348     ixheaacd_windowing_short2(p_in_ibuffer + ixheaacd_drc_offset->n_short / 2,
349                               window_short_prev_ptr, fp, ixheaacd_drc_offset,
350                               shiftp, shift_olap);
351 
352   output_q = ixheaacd_windowing_short3(
353       p_in_ibuffer, window_short + ixheaacd_drc_offset->n_short - 1,
354       fp + ixheaacd_drc_offset->n_short, ixheaacd_drc_offset->n_short, shiftp,
355       shift_olap);
356   p_in_ibuffer += ixheaacd_drc_offset->n_short;
357   fp += ixheaacd_drc_offset->n_short;
358   window_short_prev_ptr = window_short;
359 
360   for (k = 1; k < 7; k++) {
361     output_q = ixheaacd_windowing_short4(
362         p_in_ibuffer, window_short_prev_ptr, fp,
363         window_short_prev_ptr + ixheaacd_drc_offset->n_short - 1,
364         ixheaacd_drc_offset->n_short, 1, shiftp, shift_olap, output_q);
365     p_in_ibuffer += ixheaacd_drc_offset->n_short;
366     fp += ixheaacd_drc_offset->n_short;
367     window_short_prev_ptr = window_short;
368   }
369 
370   output_q = ixheaacd_windowing_short4(
371       p_in_ibuffer, window_short_prev_ptr, fp,
372       window_short_prev_ptr + ixheaacd_drc_offset->n_short - 1,
373       ixheaacd_drc_offset->n_short, 0, shiftp, shift_olap, output_q);
374   p_in_ibuffer += ixheaacd_drc_offset->n_short;
375   fp += ixheaacd_drc_offset->n_short;
376 
377   if (fac_apply) {
378     ixheaacd_combine_fac(overlap_data + ixheaacd_drc_offset->n_flat_ls +
379                              ixheaacd_drc_offset->lfac,
380                          fac_data_out,
381                          overlap_data + ixheaacd_drc_offset->n_flat_ls +
382                              ixheaacd_drc_offset->lfac,
383                          2 * ixheaacd_drc_offset->lfac, output_q, fac_q);
384   }
385   memset(overlap_data + 2 * ixheaacd_drc_offset->n_long -
386              ixheaacd_drc_offset->n_flat_ls,
387          0, sizeof(WORD32) * ixheaacd_drc_offset->n_flat_ls);
388   ixheaacd_scale_down(overlap_data, overlap_data,
389                       ixheaacd_drc_offset->n_flat_ls, shift_olap, output_q);
390 
391   ixheaacd_scale_down(p_overlap_ibuffer,
392                       overlap_data + ixheaacd_drc_offset->n_long,
393                       ixheaacd_drc_offset->n_long, output_q, shift_olap);
394   ixheaacd_scale_down(p_out_ibuffer, overlap_data, ixheaacd_drc_offset->n_long,
395                       output_q, 15);
396 
397   if (td_frame_prev) {
398     qfac = 1.0f / (FLOAT32)(1 << 15);
399 
400     for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
401       p_out_buffer[k] = ((FLOAT32)p_out_ibuffer[k]) * qfac;
402     }
403     err_code = ixheaacd_lpd_bpf_fix(usac_data, 1, p_out_buffer, st);
404     if (err_code != 0) return err_code;
405 
406     for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
407       p_out_ibuffer[k] = (WORD32)(p_out_buffer[k] * (1 << 15));
408     }
409   }
410 
411   return 0;
412 }
413 
ixheaacd_fd_imdct_long(ia_usac_data_struct * usac_data,WORD32 i_ch,WORD32 * fac_idata,offset_lengths * ixheaacd_drc_offset,WORD8 fac_q)414 static WORD32 ixheaacd_fd_imdct_long(ia_usac_data_struct *usac_data,
415                                      WORD32 i_ch, WORD32 *fac_idata,
416                                      offset_lengths *ixheaacd_drc_offset,
417                                      WORD8 fac_q) {
418   FLOAT32 qfac;
419   WORD32 *window_long_prev, k, i, *window_short_prev_ptr;
420 
421   WORD32 *p_in_ibuffer = usac_data->coef_fix[i_ch];
422   WORD32 *p_overlap_ibuffer = usac_data->overlap_data_ptr[i_ch];
423   WORD32 *p_out_ibuffer = usac_data->output_data_ptr[i_ch];
424   FLOAT32 *p_out_buffer = usac_data->time_sample_vector[i_ch];
425   WORD32 *scratch_mem = usac_data->scratch_buffer;
426   WORD32 n_long = usac_data->ccfl;
427   WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
428   WORD32 fac_apply = usac_data->fac_data_present[i_ch];
429   WORD8 shiftp, output_q = 0, shift_olap = 14;
430   WORD32 max_shift;
431 
432   WORD32 window_sequence = usac_data->window_sequence[i_ch];
433   WORD32 window_select_prev = usac_data->window_shape_prev[i_ch];
434   ia_usac_lpd_decoder_handle st = usac_data->str_tddec[i_ch];
435 
436   WORD32 err_code = 0;
437 
438   max_shift =
439       ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
440   ixheaacd_normalize(p_in_ibuffer, max_shift, ixheaacd_drc_offset->n_long);
441   shiftp = max_shift + 6;
442 
443   ixheaacd_acelp_imdct(p_in_ibuffer, 2 * ixheaacd_drc_offset->n_long, &shiftp,
444                        scratch_mem);
445 
446   max_shift =
447       ixheaacd_calc_max_spectralline(p_in_ibuffer, ixheaacd_drc_offset->n_long);
448   ixheaacd_normalize(p_in_ibuffer, max_shift - 1, ixheaacd_drc_offset->n_long);
449   shiftp += max_shift - 1;
450 
451   switch (window_sequence) {
452     case ONLY_LONG_SEQUENCE:
453     case LONG_START_SEQUENCE:
454       err_code = ixheaacd_calc_window(
455           &window_long_prev, ixheaacd_drc_offset->n_long, window_select_prev);
456       if (err_code == -1) return err_code;
457       output_q = ixheaacd_windowing_long1(
458           p_in_ibuffer + n_long / 2, p_overlap_ibuffer, window_long_prev,
459           window_long_prev + ixheaacd_drc_offset->n_long - 1, p_out_ibuffer,
460           ixheaacd_drc_offset->n_long, shiftp, shift_olap);
461       break;
462 
463     case STOP_START_SEQUENCE:
464     case LONG_STOP_SEQUENCE:
465       err_code = ixheaacd_calc_window(&window_short_prev_ptr,
466                                       ixheaacd_drc_offset->n_trans_ls,
467                                       window_select_prev);
468       if (err_code == -1) return err_code;
469       if (fac_apply) {
470         output_q = ixheaacd_windowing_long2(
471             p_in_ibuffer + n_long / 2, window_short_prev_ptr, fac_idata,
472             p_overlap_ibuffer, p_out_ibuffer, ixheaacd_drc_offset, shiftp,
473             shift_olap, fac_q);
474       } else {
475         output_q = ixheaacd_windowing_long3(
476             p_in_ibuffer + n_long / 2, window_short_prev_ptr, p_overlap_ibuffer,
477             p_out_ibuffer,
478             window_short_prev_ptr + ixheaacd_drc_offset->n_trans_ls - 1,
479             ixheaacd_drc_offset, shiftp, shift_olap);
480       }
481       break;
482   }
483 
484   for (i = 0; i < ixheaacd_drc_offset->n_long / 2; i++) {
485     p_overlap_ibuffer[ixheaacd_drc_offset->n_long / 2 + i] =
486         -p_in_ibuffer[i] >> (shiftp - shift_olap);
487     p_overlap_ibuffer[ixheaacd_drc_offset->n_long / 2 - i - 1] =
488         -p_in_ibuffer[i] >> (shiftp - shift_olap);
489   }
490 
491   ixheaacd_scale_down(p_out_ibuffer, p_out_ibuffer, ixheaacd_drc_offset->n_long,
492                       output_q, 15);
493 
494   if (td_frame_prev) {
495     qfac = 1.0f / (FLOAT32)(1 << 15);
496 
497     for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
498       p_out_buffer[k] = ((FLOAT32)p_out_ibuffer[k]) * qfac;
499     }
500     err_code = ixheaacd_lpd_bpf_fix(usac_data, 0, p_out_buffer, st);
501     if (err_code != 0) return err_code;
502 
503     for (k = 0; k < ixheaacd_drc_offset->n_long; k++) {
504       p_out_ibuffer[k] = (WORD32)(p_out_buffer[k] * (1 << 15));
505     }
506   }
507 
508   return 0;
509 }
510 
ixheaacd_fd_frm_dec(ia_usac_data_struct * usac_data,WORD32 i_ch)511 WORD32 ixheaacd_fd_frm_dec(ia_usac_data_struct *usac_data, WORD32 i_ch) {
512   WORD32 fac_idata[2 * FAC_LENGTH + 16];
513   offset_lengths ixheaacd_drc_offset;
514   WORD8 fac_q = 0;
515   WORD32 td_frame_prev = usac_data->td_frame_prev[i_ch];
516   WORD32 fac_apply = usac_data->fac_data_present[i_ch];
517   WORD32 window_sequence = usac_data->window_sequence[i_ch];
518   ixheaacd_drc_offset.n_long = usac_data->ccfl;
519   ixheaacd_drc_offset.n_short = ixheaacd_drc_offset.n_long >> 3;
520 
521   memset(fac_idata, 0, sizeof(fac_idata));
522 
523   if (td_frame_prev) {
524     if (window_sequence == EIGHT_SHORT_SEQUENCE) {
525       ixheaacd_drc_offset.lfac = ixheaacd_drc_offset.n_long >> 4;
526     } else {
527       ixheaacd_drc_offset.lfac = ixheaacd_drc_offset.n_long >> 3;
528     }
529     ixheaacd_drc_offset.n_flat_ls =
530         (ixheaacd_drc_offset.n_long - (ixheaacd_drc_offset.lfac) * 2) >> 1;
531 
532     ixheaacd_drc_offset.n_trans_ls = (ixheaacd_drc_offset.lfac) << 1;
533   } else {
534     ixheaacd_drc_offset.lfac = FAC_LENGTH;
535     ixheaacd_drc_offset.n_flat_ls =
536         (ixheaacd_drc_offset.n_long - ixheaacd_drc_offset.n_short) >> 1;
537     ixheaacd_drc_offset.n_trans_ls = ixheaacd_drc_offset.n_short;
538   }
539 
540   if (fac_apply)
541     fac_q = ixheaacd_cal_fac_data(usac_data, i_ch, ixheaacd_drc_offset.n_long,
542                                   ixheaacd_drc_offset.lfac, fac_idata);
543 
544   if (window_sequence != EIGHT_SHORT_SEQUENCE)
545     ixheaacd_fd_imdct_long(usac_data, i_ch, fac_idata, &ixheaacd_drc_offset,
546                            fac_q);
547 
548   else
549     ixheaacd_fd_imdct_short(usac_data, i_ch, fac_idata, &ixheaacd_drc_offset,
550                             fac_q);
551 
552   return 0;
553 }