xref: /aosp_15_r20/external/libxaac/decoder/ixheaacd_hbe_dft_trans.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
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 <stdlib.h>
22 #include <string.h>
23 
24 #include "ixheaac_type_def.h"
25 
26 #include "ixheaacd_bitbuffer.h"
27 
28 #include "ixheaacd_interface.h"
29 
30 #include "ixheaacd_tns_usac.h"
31 #include "ixheaacd_cnst.h"
32 
33 #include "ixheaacd_acelp_info.h"
34 
35 #include "ixheaacd_sbrdecsettings.h"
36 #include "ixheaacd_info.h"
37 #include "ixheaacd_sbr_common.h"
38 #include "ixheaacd_drc_data_struct.h"
39 #include "ixheaacd_drc_dec.h"
40 #include "ixheaacd_sbrdecoder.h"
41 #include "ixheaacd_mps_polyphase.h"
42 #include "ixheaac_sbr_const.h"
43 
44 #include "ixheaacd_env_extr_part.h"
45 #include "ixheaacd_sbr_rom.h"
46 #include "ixheaacd_common_rom.h"
47 #include "ixheaacd_hybrid.h"
48 #include "ixheaacd_sbr_scale.h"
49 #include "ixheaacd_ps_dec.h"
50 #include "ixheaacd_freq_sca.h"
51 #include "ixheaacd_lpp_tran.h"
52 #include "ixheaacd_bitbuffer.h"
53 #include "ixheaacd_env_extr.h"
54 #include "ixheaacd_qmf_dec.h"
55 #include "ixheaacd_env_calc.h"
56 #include "ixheaacd_pvc_dec.h"
57 
58 #include "ixheaacd_sbr_dec.h"
59 #include "ixheaac_error_standards.h"
60 #include "ixheaacd_sbrqmftrans.h"
61 #include "ixheaacd_qmf_poly.h"
62 
63 #include "ixheaac_constants.h"
64 #include "ixheaac_basic_ops32.h"
65 #include "ixheaac_basic_op.h"
66 
67 #include "ixheaac_esbr_rom.h"
68 
ixheaacd_map_prot_filter(WORD32 filt_length)69 static FLOAT32 *ixheaacd_map_prot_filter(WORD32 filt_length) {
70   switch (filt_length) {
71     case 4:
72       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[0];
73       break;
74     case 8:
75       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[40];
76       break;
77     case 12:
78       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[120];
79       break;
80     case 16:
81       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[240];
82       break;
83     case 20:
84       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[400];
85       break;
86     case 24:
87       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[600];
88       break;
89     case 28:
90       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff_28_36[0];
91       break;
92     case 32:
93       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[840];
94       break;
95     case 36:
96       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff_28_36[280];
97       break;
98     case 40:
99       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[1160];
100       break;
101     case 44:
102       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[1560];
103       break;
104     default:
105       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[0];
106   }
107 }
108 
ixheaacd_create_dft_hbe_window(FLOAT32 * win,WORD32 x_over_bin1,WORD32 x_over_bin2,WORD32 ts,WORD32 size)109 static VOID ixheaacd_create_dft_hbe_window(FLOAT32 *win, WORD32 x_over_bin1,
110                                            WORD32 x_over_bin2,
111                                            WORD32 ts, WORD32 size) {
112   const FLOAT32 *ptr_freq_domain_win = NULL;
113   WORD32 n;
114   if (ts == 12) {
115     ptr_freq_domain_win = &ixheaac_dft_hbe_window_ts_12[0];
116   } else {
117     ptr_freq_domain_win = &ixheaac_dft_hbe_window_ts_18[0];
118   }
119   for (n = 0; n < (x_over_bin1 - ts / 2); n++) {
120     win[n] = 0;
121   }
122 
123   for (n = (x_over_bin1 - ts / 2); n <= (x_over_bin1 + ts / 2); n++) {
124     win[n] = (FLOAT32)ptr_freq_domain_win[n - (x_over_bin1 - ts / 2)];
125   }
126 
127   for (n = (x_over_bin1 + ts / 2 + 1); n < (x_over_bin2 - ts / 2); n++) {
128     win[n] = (FLOAT32)1.0f;
129   }
130 
131   for (n = (x_over_bin2 - ts / 2); n <= (x_over_bin2 + ts / 2); n++) {
132     win[n] = (FLOAT32)1.0f - ptr_freq_domain_win[n - (x_over_bin2 - ts / 2)];
133   }
134 
135   for (n = (x_over_bin2 + ts / 2 + 1); n < size; n++) {
136     win[n] = 0.0f;
137   }
138 }
139 
ixheaacd_calc_anal_synth_window(WORD32 fft_size,FLOAT32 * ptr_window)140 static WORD32 ixheaacd_calc_anal_synth_window(WORD32 fft_size, FLOAT32 *ptr_window) {
141   FLOAT32 sin_pi_2_N = 0.0f;
142   FLOAT32 cos_pi_2_N = 0.0f;
143   FLOAT32 *ptr_sin_pi_n_by_N = NULL;
144   WORD32 hop_stride = 1;
145   WORD32 i, j;
146   WORD32 l_fft_stride = 512;
147   switch (fft_size) {
148     case 64:
149       hop_stride = 16;
150       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
151       sin_pi_2_N = ptr_sin_pi_n_by_N[hop_stride >> 1];
152       cos_pi_2_N = ptr_sin_pi_n_by_N[512 + (hop_stride >> 1)];
153       l_fft_stride = 512;
154       break;
155     case 128:
156       hop_stride = 8;
157       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
158       sin_pi_2_N = ptr_sin_pi_n_by_N[hop_stride >> 1];
159       cos_pi_2_N = ptr_sin_pi_n_by_N[512 + (hop_stride >> 1)];
160       l_fft_stride = 512;
161       break;
162     case 256:
163       hop_stride = 4;
164       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
165       sin_pi_2_N = ptr_sin_pi_n_by_N[hop_stride >> 1];
166       cos_pi_2_N = ptr_sin_pi_n_by_N[512 + (hop_stride >> 1)];
167       l_fft_stride = 512;
168       break;
169     case 512:
170       hop_stride = 2;
171       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
172       sin_pi_2_N = ptr_sin_pi_n_by_N[1];
173       cos_pi_2_N = ptr_sin_pi_n_by_N[512 + 1];
174       l_fft_stride = 512;
175       break;
176     case 1024:
177       hop_stride = 1;
178       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
179       sin_pi_2_N = ixheaac_sine_pi_by_2_N[0];
180       cos_pi_2_N = ixheaac_sine_pi_by_2_N[1];
181       l_fft_stride = 512;
182       break;
183     case 192:
184       hop_stride = 4;
185       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_768[0];
186       sin_pi_2_N = ptr_sin_pi_n_by_N[hop_stride >> 1];
187       cos_pi_2_N = ptr_sin_pi_n_by_N[384 + (hop_stride >> 1)];
188       l_fft_stride = 384;
189       break;
190     case 384:
191       hop_stride = 2;
192       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_768[0];
193       sin_pi_2_N = ptr_sin_pi_n_by_N[1];
194       cos_pi_2_N = ptr_sin_pi_n_by_N[384 + 1];
195       l_fft_stride = 384;
196       break;
197     case 768:
198       hop_stride = 1;
199       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_768[0];
200       sin_pi_2_N = ixheaac_sine_pi_by_2_N[8];
201       cos_pi_2_N = ixheaac_sine_pi_by_2_N[9];
202       l_fft_stride = 384;
203       break;
204     case 320:
205       hop_stride = 3;
206       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_960[0];
207       sin_pi_2_N = ixheaac_sine_pi_by_2_N[16];
208       cos_pi_2_N = ixheaac_sine_pi_by_2_N[17];
209       l_fft_stride = 480;
210       break;
211     case 960:
212       hop_stride = 1;
213       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_960[0];
214       sin_pi_2_N = ixheaac_sine_pi_by_2_N[2];
215       cos_pi_2_N = ixheaac_sine_pi_by_2_N[3];
216       l_fft_stride = 480;
217       break;
218     case 448:
219       hop_stride = 2;
220       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_896[0];
221       sin_pi_2_N = ptr_sin_pi_n_by_N[1];
222       cos_pi_2_N = ptr_sin_pi_n_by_N[448 + 1];
223       l_fft_stride = 448;
224       break;
225     case 896:
226       hop_stride = 1;
227       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_896[0];
228       sin_pi_2_N = ixheaac_sine_pi_by_2_N[4];
229       cos_pi_2_N = ixheaac_sine_pi_by_2_N[5];
230       l_fft_stride = 448;
231       break;
232     case 576:
233       hop_stride = 1;
234       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_576[0];
235       sin_pi_2_N = ixheaac_sine_pi_by_2_N[14];
236       cos_pi_2_N = ixheaac_sine_pi_by_2_N[15];
237       l_fft_stride = 288;
238       break;
239     case 640:
240       hop_stride = 1;
241       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_640[0];
242       sin_pi_2_N = ixheaac_sine_pi_by_2_N[12];
243       cos_pi_2_N = ixheaac_sine_pi_by_2_N[13];
244       l_fft_stride = 320;
245       break;
246     case 704:
247       hop_stride = 1;
248       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_704[0];
249       sin_pi_2_N = ixheaac_sine_pi_by_2_N[10];
250       cos_pi_2_N = ixheaac_sine_pi_by_2_N[11];
251       l_fft_stride = 352;
252       break;
253     case 832:
254       hop_stride = 1;
255       ptr_sin_pi_n_by_N = (FLOAT32 *)&ixheaac_sine_pi_n_by_832[0];
256       sin_pi_2_N = ixheaac_sine_pi_by_2_N[6];
257       cos_pi_2_N = ixheaac_sine_pi_by_2_N[7];
258       l_fft_stride = 416;
259       break;
260     default:
261       return -1;
262   }
263 
264   for (i = 0, j = 0; j < (fft_size >> 1); i += hop_stride, j++) {
265     FLOAT32 cos_val = ptr_sin_pi_n_by_N[i + l_fft_stride];
266     FLOAT32 sin_val = ptr_sin_pi_n_by_N[i];
267     ptr_window[j] = cos_val * sin_pi_2_N + sin_val * cos_pi_2_N;
268   }
269 
270   for (; j < fft_size; j++, i += hop_stride) {
271     FLOAT32 cos_val = ptr_sin_pi_n_by_N[i - l_fft_stride];
272     FLOAT32 sin_val = ptr_sin_pi_n_by_N[i];
273     ptr_window[j] = sin_val * cos_pi_2_N - cos_val * sin_pi_2_N;
274   }
275   return 0;
276 }
277 
ixheaacd_dft_hbe_data_reinit(ia_esbr_hbe_txposer_struct * ptr_hbe_txposer,WORD16 * p_freq_band_tab[2],WORD16 * p_num_sfb)278 WORD32 ixheaacd_dft_hbe_data_reinit(ia_esbr_hbe_txposer_struct *ptr_hbe_txposer,
279                                     WORD16 *p_freq_band_tab[2], WORD16 *p_num_sfb) {
280   WORD32 sfb;
281   WORD32 patch;
282   WORD32 i;
283   WORD32 temp_start;
284   FLOAT32 fb_ratio;
285   WORD32 stop_patch;
286   WORD32 in_hop_size_divisor = 8;
287   static const WORD32 trans_samp[2] = {12, 18};
288   WORD32 err = 0;
289 
290   ptr_hbe_txposer->start_band = p_freq_band_tab[LOW][0];
291   ptr_hbe_txposer->end_band = p_freq_band_tab[LOW][p_num_sfb[LOW]];
292   ptr_hbe_txposer->esbr_hq = 1;
293 
294   ptr_hbe_txposer->synth_size = 4 * ((ptr_hbe_txposer->start_band + 4) / 8 + 1);
295   ptr_hbe_txposer->k_start = ixheaac_start_subband2kL_tbl[ptr_hbe_txposer->start_band];
296 
297   fb_ratio = ptr_hbe_txposer->synth_size / 32.0f;
298 
299   ptr_hbe_txposer->ana_fft_size[0] = (WORD32)(fb_ratio * ptr_hbe_txposer->fft_size[0]);
300   ptr_hbe_txposer->ana_fft_size[1] = (WORD32)(fb_ratio * ptr_hbe_txposer->fft_size[1]);
301 
302   ptr_hbe_txposer->in_hop_size = ptr_hbe_txposer->ana_fft_size[0] / in_hop_size_divisor;
303 
304   ptr_hbe_txposer->synth_window = (FLOAT32 *)&ptr_hbe_txposer->synthesis_window_buf[0];
305   ptr_hbe_txposer->anal_window = (FLOAT32 *)&ptr_hbe_txposer->analysis_window_buf[0];
306 
307   err = ixheaacd_calc_anal_synth_window(ptr_hbe_txposer->ana_fft_size[0],
308                                         ptr_hbe_txposer->anal_window);
309   if (err) {
310     return err;
311   }
312 
313   memset(ptr_hbe_txposer->synth_buf, 0, 1280 * sizeof(ptr_hbe_txposer->synth_buf[0]));
314 
315   ptr_hbe_txposer->synth_wind_coeff = ixheaacd_map_prot_filter(ptr_hbe_txposer->synth_size);
316 
317   temp_start = 2 * ((ptr_hbe_txposer->start_band - 1) / 2);
318   ptr_hbe_txposer->analy_size =
319       4 * ((min(64, ptr_hbe_txposer->end_band + 1) - temp_start - 1) / 4 +
320            1);
321   ptr_hbe_txposer->a_start = temp_start - max(0, temp_start + ptr_hbe_txposer->analy_size - 64);
322 
323   fb_ratio = ptr_hbe_txposer->analy_size / 64.0f;
324 
325   ptr_hbe_txposer->syn_fft_size[0] = (WORD32)(fb_ratio * ptr_hbe_txposer->fft_size[0]);
326   ptr_hbe_txposer->syn_fft_size[1] = (WORD32)(fb_ratio * ptr_hbe_txposer->fft_size[1]);
327 
328   ptr_hbe_txposer->out_hop_size = 2 * ptr_hbe_txposer->syn_fft_size[0] / in_hop_size_divisor;
329 
330   err = ixheaacd_calc_anal_synth_window(ptr_hbe_txposer->syn_fft_size[0],
331                                         ptr_hbe_txposer->synth_window);
332   if (err) {
333     return err;
334   }
335 
336   ptr_hbe_txposer->analy_wind_coeff = ixheaacd_map_prot_filter(ptr_hbe_txposer->analy_size);
337 
338   memset(&ptr_hbe_txposer->x_over_qmf[0], 0, sizeof(ptr_hbe_txposer->x_over_qmf));
339   for (i = 0; i < MAX_STRETCH; i++) {
340     memset(&ptr_hbe_txposer->x_over_bin[i][0], 0,
341            2 * sizeof(ptr_hbe_txposer->x_over_bin[i][0]));
342   }
343   sfb = 0;
344   stop_patch = MAX_STRETCH;
345 
346   switch (ptr_hbe_txposer->synth_size) {
347     case 4:
348       ptr_hbe_txposer->synth_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_4;
349       ptr_hbe_txposer->ixheaacd_real_synth_fft = &ixheaac_real_synth_fft_p2;
350       break;
351     case 8:
352       ptr_hbe_txposer->synth_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_8;
353       ptr_hbe_txposer->ixheaacd_real_synth_fft = &ixheaac_real_synth_fft_p2;
354       break;
355     case 12:
356       ptr_hbe_txposer->synth_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_12;
357       ptr_hbe_txposer->ixheaacd_real_synth_fft = &ixheaac_real_synth_fft_p3;
358       break;
359     case 16:
360       ptr_hbe_txposer->synth_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_16;
361       ptr_hbe_txposer->ixheaacd_real_synth_fft = &ixheaac_real_synth_fft_p2;
362       break;
363     case 20:
364       ptr_hbe_txposer->synth_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_20;
365       break;
366     case 28:
367       ptr_hbe_txposer->synth_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_20;
368       break;
369     default:
370       ptr_hbe_txposer->synth_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_4;
371       ptr_hbe_txposer->ixheaacd_real_synth_fft = &ixheaac_real_synth_fft_p2;
372   }
373 
374   {
375     WORD32 l, k, L = ptr_hbe_txposer->analy_size;
376     for (k = 0; k < L; k++) {
377       for (l = 0; l < 2 * L; l++) {
378         ptr_hbe_txposer->str_dft_hbe_anal_coeff.real[k][l] =
379             (FLOAT32)cos(PI / (2 * L) *
380                          ((k + 0.5) * (2 * l - L / 64.0) - L / 64.0 *
381                           ptr_hbe_txposer->a_start));
382         ptr_hbe_txposer->str_dft_hbe_anal_coeff.imag[k][l] =
383             (FLOAT32)sin(PI / (2 * L) *
384                          ((k + 0.5) * (2 * l - L / 64.0) - L / 64.0 *
385                           ptr_hbe_txposer->a_start));
386       }
387     }
388   }
389 
390   for (patch = 1; patch <= stop_patch; patch++) {
391     while (sfb <= p_num_sfb[LOW] &&
392            p_freq_band_tab[LOW][sfb] <= patch * ptr_hbe_txposer->start_band)
393       sfb++;
394     if (sfb <= p_num_sfb[LOW]) {
395       if ((patch * ptr_hbe_txposer->start_band - p_freq_band_tab[LOW][sfb - 1]) <= 3) {
396         ptr_hbe_txposer->x_over_qmf[patch - 1] = p_freq_band_tab[LOW][sfb - 1];
397         if (patch <= MAX_STRETCH) {
398           ptr_hbe_txposer->x_over_bin[patch - 1][0] = (WORD32)(
399               ptr_hbe_txposer->fft_size[0] * p_freq_band_tab[LOW][sfb - 1] / 128 + 0.5);
400           ptr_hbe_txposer->x_over_bin[patch - 1][1] = (WORD32)(
401               ptr_hbe_txposer->fft_size[1] * p_freq_band_tab[LOW][sfb - 1] / 128 + 0.5);
402         }
403       } else {
404         WORD32 sfb = 0;
405         while (sfb <= p_num_sfb[HIGH] &&
406                p_freq_band_tab[HIGH][sfb] <= patch * ptr_hbe_txposer->start_band)
407           sfb++;
408         ptr_hbe_txposer->x_over_qmf[patch - 1] = p_freq_band_tab[HIGH][sfb - 1];
409         if (patch <= MAX_STRETCH) {
410           ptr_hbe_txposer->x_over_bin[patch - 1][0] = (WORD32)(
411               ptr_hbe_txposer->fft_size[0] * p_freq_band_tab[HIGH][sfb - 1] / 128 + 0.5);
412           ptr_hbe_txposer->x_over_bin[patch - 1][1] = (WORD32)(
413               ptr_hbe_txposer->fft_size[1] * p_freq_band_tab[HIGH][sfb - 1] / 128 + 0.5);
414         }
415       }
416     } else {
417       ptr_hbe_txposer->x_over_qmf[patch - 1] = ptr_hbe_txposer->end_band;
418       if (patch <= MAX_STRETCH) {
419         ptr_hbe_txposer->x_over_bin[patch - 1][0] =
420             (WORD32)(ptr_hbe_txposer->fft_size[0] * ptr_hbe_txposer->end_band / 128 + 0.5);
421         ptr_hbe_txposer->x_over_bin[patch - 1][1] =
422             (WORD32)(ptr_hbe_txposer->fft_size[1] * ptr_hbe_txposer->end_band / 128 + 0.5);
423       }
424       ptr_hbe_txposer->max_stretch = min(patch, MAX_STRETCH);
425       break;
426     }
427   }
428 
429   for (patch = 0; patch < ptr_hbe_txposer->max_stretch - 1; patch++) {
430     for (i = 0; i < 2; i++) {
431       ixheaacd_create_dft_hbe_window(ptr_hbe_txposer->fd_win_buf[patch][i],
432                                      ptr_hbe_txposer->x_over_bin[patch][i],
433                                      ptr_hbe_txposer->x_over_bin[patch + 1][i], trans_samp[i],
434                                      ptr_hbe_txposer->fft_size[i]);
435     }
436   }
437   return 0;
438 }
439 
ixheaacd_dft_hbe_apply_win(const FLOAT32 * inp1,const FLOAT32 * inp2,FLOAT32 * out,WORD32 n)440 static VOID ixheaacd_dft_hbe_apply_win(const FLOAT32 *inp1, const FLOAT32 *inp2, FLOAT32 *out,
441                                        WORD32 n) {
442   WORD32 i;
443   for (i = 0; i < n; i++) {
444     out[i] = inp1[i] * inp2[i];
445   }
446 }
447 
ixheaacd_dft_hbe_fft_memmove(FLOAT32 * ptr_spectrum,WORD32 size)448 VOID ixheaacd_dft_hbe_fft_memmove(FLOAT32 *ptr_spectrum, WORD32 size) {
449   WORD32 n;
450 
451   for (n = 0; n < size / 2; n++) {
452     FLOAT32 tmp = ptr_spectrum[n];
453     ptr_spectrum[n] = ptr_spectrum[n + size / 2];
454     ptr_spectrum[n + size / 2] = tmp;
455   }
456 }
457 
ixheaacd_karth2polar(FLOAT32 * spectrum,FLOAT32 * mag,FLOAT32 * phase,WORD32 fft_size)458 VOID ixheaacd_karth2polar(FLOAT32 *spectrum, FLOAT32 *mag, FLOAT32 *phase, WORD32 fft_size) {
459   WORD32 n;
460 
461   for (n = 1; n < fft_size / 2; n++) {
462     phase[n] = (FLOAT32)atan2(spectrum[2 * n + 1], spectrum[2 * n]);
463     mag[n] = (FLOAT32)sqrt(spectrum[2 * n] * spectrum[2 * n] +
464                            spectrum[2 * n + 1] * spectrum[2 * n + 1]);
465   }
466 
467   if (spectrum[0] < 0) {
468     phase[0] = (FLOAT32)acos(-1);
469     mag[0] = -spectrum[0];
470   } else {
471     phase[0] = 0;
472     mag[0] = spectrum[0];
473   }
474 
475   if (spectrum[1] < 0) {
476     phase[fft_size / 2] = (FLOAT32)acos(-1);
477     mag[fft_size / 2] = -spectrum[1];
478   } else {
479     phase[fft_size / 2] = 0;
480     mag[fft_size / 2] = spectrum[1];
481   }
482 }
483 
ixheaacd_hbe_fft_table(ia_esbr_hbe_txposer_struct * ptr_hbe_txposer)484 VOID ixheaacd_hbe_fft_table(ia_esbr_hbe_txposer_struct *ptr_hbe_txposer) {
485   WORD32 oversampling_flag = ptr_hbe_txposer->oversampling_flag;
486   WORD32 ana_fft_size = ptr_hbe_txposer->ana_fft_size[oversampling_flag];
487   WORD32 syn_fft_size = ptr_hbe_txposer->syn_fft_size[oversampling_flag];
488 
489   switch (ana_fft_size) {
490     case 576:
491       ptr_hbe_txposer->ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_576;
492       break;
493     case 384:
494       ptr_hbe_txposer->ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_384;
495       break;
496     case 512:
497       ptr_hbe_txposer->ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_512;
498       break;
499     case 768:
500       ptr_hbe_txposer->ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_768;
501       break;
502     default:
503       break;
504   }
505 
506   switch (syn_fft_size) {
507     case 448:
508       ptr_hbe_txposer->syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_448;
509       break;
510     case 512:
511       ptr_hbe_txposer->syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_512;
512       break;
513     case 768:
514       ptr_hbe_txposer->syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_768;
515       break;
516     case 672:
517       ptr_hbe_txposer->syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_672;
518       break;
519     default:
520       break;
521   }
522 }
523 
ixheaacd_hbe_fft_map(ia_esbr_hbe_txposer_struct * ptr_hbe_txposer)524 IA_ERRORCODE ixheaacd_hbe_fft_map(ia_esbr_hbe_txposer_struct *ptr_hbe_txposer) {
525   WORD32 oversampling_flag = ptr_hbe_txposer->oversampling_flag;
526   WORD32 ana_fft_size = ptr_hbe_txposer->ana_fft_size[oversampling_flag];
527   WORD32 syn_fft_size = ptr_hbe_txposer->syn_fft_size[oversampling_flag];
528 
529   switch (ana_fft_size) {
530     case 576:
531       ptr_hbe_txposer->ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_576;
532       ptr_hbe_txposer->ixheaacd_hbe_anal_fft = &ixheaacd_hbe_apply_fft_288;
533       break;
534     case 384:
535       ptr_hbe_txposer->ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_384;
536       ptr_hbe_txposer->ixheaacd_hbe_anal_fft = &ixheaacd_hbe_apply_cfftn_gen;
537       break;
538     case 512:
539       ptr_hbe_txposer->ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_512;
540       ptr_hbe_txposer->ixheaacd_hbe_anal_fft = &ixheaacd_hbe_apply_cfftn;
541       break;
542     case 768:
543       ptr_hbe_txposer->ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_768;
544       ptr_hbe_txposer->ixheaacd_hbe_anal_fft = &ixheaacd_hbe_apply_cfftn_gen;
545       break;
546     default:
547       return IA_FATAL_ERROR;
548       break;
549   }
550 
551   switch (syn_fft_size) {
552     case 448:
553       ptr_hbe_txposer->syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_448;
554       ptr_hbe_txposer->ixheaacd_hbe_synth_ifft = &ixheaacd_hbe_apply_ifft_224;
555       break;
556     case 512:
557       ptr_hbe_txposer->syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_512;
558       ptr_hbe_txposer->ixheaacd_hbe_synth_ifft = &ixheaacd_hbe_apply_cfftn;
559       break;
560     case 768:
561       ptr_hbe_txposer->syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_768;
562       ptr_hbe_txposer->ixheaacd_hbe_synth_ifft = &ixheaacd_hbe_apply_cfftn_gen;
563       break;
564     case 672:
565       ptr_hbe_txposer->syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_672;
566       ptr_hbe_txposer->ixheaacd_hbe_synth_ifft = &ixheaacd_hbe_apply_ifft_336;
567       break;
568     default:
569       return IA_FATAL_ERROR;
570       break;
571   }
572 
573   return IA_NO_ERROR;
574 }
575 
ixheaacd_dft_hbe_apply_polar_t2(WORD32 trans_fac,ia_esbr_hbe_txposer_struct * ptr_hbe_txposer,WORD32 pitch_in_bins,WORD out_transform_size)576 VOID ixheaacd_dft_hbe_apply_polar_t2(
577     WORD32 trans_fac, ia_esbr_hbe_txposer_struct *ptr_hbe_txposer,
578     WORD32 pitch_in_bins, WORD out_transform_size) {
579   WORD32 tr;
580   WORD32 ti;
581   WORD32 m_tr;
582   WORD32 p, i;
583   FLOAT32 mag_t;
584   FLOAT32 phase_t;
585   FLOAT32 m_val;
586   FLOAT32(*fd_win_buf)[3][3][1536] = &ptr_hbe_txposer->fd_win_buf;
587   FLOAT32 *phase = ptr_hbe_txposer->phase;
588   WORD32 oversampling_flag = ptr_hbe_txposer->oversampling_flag;
589   WORD32 fft_size = ptr_hbe_txposer->fft_size[oversampling_flag];
590   FLOAT32 *ptr_spectrum_tx = ptr_hbe_txposer->ptr_spectrum_tx;
591   FLOAT32 *mag = ptr_hbe_txposer->mag;
592   FLOAT32 p_flt = fft_size * pitch_in_bins / 1536.0f;
593   p = (WORD32)p_flt;
594   FLOAT32 q_thr = 4.0f;
595   m_tr = 0;
596 
597   for (i = 0; i <= out_transform_size; i++) {
598     WORD32 utk = i;
599 
600     mag_t = (*fd_win_buf)[trans_fac - 2][oversampling_flag][i] * mag[utk];
601 
602     phase_t = trans_fac * phase[utk];
603 
604     if (phase_t == 0.0) {
605       ptr_spectrum_tx[2 * i] += mag_t;
606     } else {
607       ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
608       ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
609     }
610     if (p > 0) {
611       m_val = 0;
612       for (tr = 1; tr < trans_fac; tr++) {
613         FLOAT32 temp;
614         ti = (WORD32)((2.0f * i - tr * p_flt) / trans_fac + 0.5f);
615         if ((ti < 0) || (ti + p > fft_size / 2)) continue;
616         temp = min(mag[ti], mag[ti + p]);
617         if (temp > m_val) {
618           m_val = temp;
619           m_tr = tr;
620           utk = ti;
621         }
622       }
623 
624       if (m_val > q_thr * mag[2 * i / trans_fac]) {
625         mag_t = (FLOAT32)((*fd_win_buf)[trans_fac - 2][oversampling_flag][i] *
626                          sqrt(mag[utk]) * sqrt(mag[utk + p]));
627         phase_t = (trans_fac - m_tr) * phase[utk] + m_tr * phase[utk + p];
628         ptr_spectrum_tx[2 * i] += (FLOAT32)(mag_t * cos(phase_t));
629         ptr_spectrum_tx[2 * i + 1] += (FLOAT32)(mag_t * sin(phase_t));
630       }
631     }
632   }
633 }
634 
ixheaacd_dft_hbe_apply_polar_t3(WORD32 trans_fac,ia_esbr_hbe_txposer_struct * ptr_hbe_txposer,WORD32 pitch_in_bins,WORD out_transform_size)635 VOID ixheaacd_dft_hbe_apply_polar_t3(
636     WORD32 trans_fac, ia_esbr_hbe_txposer_struct *ptr_hbe_txposer,
637     WORD32 pitch_in_bins, WORD out_transform_size) {
638   WORD32 tr;
639   WORD32 ti;
640   WORD32 m_tr = 0;
641   WORD32 p, i;
642   FLOAT32 mag_t = 0;
643   FLOAT32 phase_t;
644   FLOAT32 m_val;
645   FLOAT32(*fd_win_buf)[3][3][1536] = &ptr_hbe_txposer->fd_win_buf;
646   FLOAT32 *phase = ptr_hbe_txposer->phase;
647   WORD32 oversampling_flag = ptr_hbe_txposer->oversampling_flag;
648   WORD32 fft_size = ptr_hbe_txposer->fft_size[oversampling_flag];
649   FLOAT32 *ptr_spectrum_tx = ptr_hbe_txposer->ptr_spectrum_tx;
650   FLOAT32 *mag = ptr_hbe_txposer->mag;
651   FLOAT32 p_flt = fft_size * pitch_in_bins / 1536.0f;
652   p = (WORD32)p_flt;
653   FLOAT32 q_thr = 4.0f;
654 
655   for (i = 0; i <= out_transform_size; i++) {
656     WORD32 utk = 2 * i / trans_fac;
657     FLOAT32 ptk = (2.0f * i / trans_fac) - utk;
658     FLOAT32 k;
659 
660     if (i % 3 == 0) {
661       mag_t = (*fd_win_buf)[trans_fac - 2][oversampling_flag][i] * mag[utk];
662     } else if (i % 3 == 1) {
663       k = (FLOAT32)cbrt(mag[utk]);
664       mag_t = (*fd_win_buf)[trans_fac - 2][oversampling_flag][i] * k *
665              (FLOAT32)pow(mag[utk + 1], ptk);
666     } else if (i % 3 == 2) {
667       k = (FLOAT32)cbrt(mag[utk + 1]);
668       mag_t = (*fd_win_buf)[trans_fac - 2][oversampling_flag][i] *
669              (FLOAT32)pow(mag[utk], 1.0 - ptk) * k;
670     }
671 
672     phase_t = trans_fac * ((1 - ptk) * phase[utk] + ptk * phase[utk + 1]);
673 
674     ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
675     ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
676 
677     if (p > 0) {
678       m_val = 0;
679       for (tr = 1; tr < trans_fac; tr++) {
680         FLOAT32 temp;
681         ti = (WORD32)((2.0f * i - tr * p_flt) / trans_fac + 0.5f);
682         if ((ti < 0) || (ti + p > fft_size / 2)) continue;
683         temp = min(mag[ti], mag[ti + p]);
684         if (temp > m_val) {
685           m_val = temp;
686           m_tr = tr;
687           utk = ti;
688         }
689       }
690 
691       if (m_val > q_thr * mag[2 * i / trans_fac]) {
692         FLOAT32 r = (FLOAT32)m_tr / trans_fac;
693         if (m_tr == 1) {
694           k = (FLOAT32)(cbrt((FLOAT32)mag[utk + p]));
695           mag_t = (*fd_win_buf)[trans_fac - 2][oversampling_flag][i] *
696                  (FLOAT32)pow(mag[utk], 1.0 - r) * k;
697           phase_t = (trans_fac - m_tr) * phase[utk] + phase[utk + p];
698         } else if (m_tr == 2) {
699           k = (FLOAT32)(cbrt((FLOAT32)mag[utk]));
700           mag_t = (*fd_win_buf)[trans_fac - 2][oversampling_flag][i] * k *
701                  (FLOAT32)pow(mag[utk + p], r);
702           phase_t = phase[utk] + m_tr * phase[utk + p];
703         }
704 
705         ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
706         ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
707       }
708     }
709   }
710 }
711 
ixheaacd_dft_hbe_apply_polar_t(WORD32 trans_fac,ia_esbr_hbe_txposer_struct * ptr_hbe_txposer,WORD32 pitch_in_bins,WORD out_transform_size)712 VOID ixheaacd_dft_hbe_apply_polar_t(
713     WORD32 trans_fac, ia_esbr_hbe_txposer_struct *ptr_hbe_txposer,
714     WORD32 pitch_in_bins, WORD out_transform_size) {
715   WORD32 tr;
716   WORD32 ti;
717   WORD32 m_tr;
718   WORD32 p, i;
719   FLOAT32 mag_t;
720   FLOAT32 phase_t;
721   FLOAT32 m_val;
722   FLOAT32(*fd_win_buf)[3][3][1536] = &ptr_hbe_txposer->fd_win_buf;
723   FLOAT32 *phase = ptr_hbe_txposer->phase;
724   WORD32 oversampling_flag = ptr_hbe_txposer->oversampling_flag;
725   WORD32 fft_size = ptr_hbe_txposer->fft_size[oversampling_flag];
726   FLOAT32 *ptr_spectrum_tx = ptr_hbe_txposer->ptr_spectrum_tx;
727   FLOAT32 *mag = ptr_hbe_txposer->mag;
728   FLOAT32 p_flt = fft_size * pitch_in_bins / 1536.0f;
729   p = (WORD32)p_flt;
730   FLOAT32 q_thr = 4.0f;
731   m_tr = 0;
732 
733   for (i = 0; i <= out_transform_size; i++) {
734     WORD32 utk = 2 * i / trans_fac;
735     FLOAT32 ptk = (2.0f * i / trans_fac) - utk;
736 
737     mag_t = (*fd_win_buf)[trans_fac - 2][oversampling_flag][i] *
738             (FLOAT32)pow(mag[utk], 1.0f - ptk) * (FLOAT32)pow(mag[utk + 1], ptk);
739 
740     phase_t = trans_fac * ((1 - ptk) * phase[utk] + ptk * phase[utk + 1]);
741 
742     ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
743     ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
744 
745     if (p > 0) {
746       m_val = 0;
747       for (tr = 1; tr < trans_fac; tr++) {
748         FLOAT32 temp;
749         ti = (WORD32)((2.0f * i - tr * p_flt) / trans_fac + 0.5f);
750         if ((ti < 0) || (ti + p > fft_size / 2)) continue;
751         temp = min(mag[ti], mag[ti + p]);
752         if (temp > m_val) {
753           m_val = temp;
754           m_tr = tr;
755           utk = ti;
756         }
757       }
758 
759       if (m_val > q_thr * mag[2 * i / trans_fac]) {
760         FLOAT32 r = (FLOAT32)m_tr / trans_fac;
761         mag_t = (*fd_win_buf)[trans_fac - 2][oversampling_flag][i] *
762                 (FLOAT32)pow(mag[utk], 1.0 - r) * (FLOAT32)pow(mag[utk + p], r);
763         phase_t = (trans_fac - m_tr) * phase[utk] + m_tr * phase[utk + p];
764         ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
765         ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
766       }
767     }
768   }
769 }
770 
ixheaacd_dft_hbe_apply(ia_esbr_hbe_txposer_struct * ptr_hbe_txposer,FLOAT32 qmf_buf_real[][64],FLOAT32 qmf_buf_imag[][64],WORD32 num_columns,FLOAT32 pv_qmf_buf_real[][64],FLOAT32 pv_qmf_buf_imag[][64],WORD32 pitch_in_bins,FLOAT32 * dft_hbe_scratch_buf)771 WORD32 ixheaacd_dft_hbe_apply(ia_esbr_hbe_txposer_struct *ptr_hbe_txposer,
772                               FLOAT32 qmf_buf_real[][64], FLOAT32 qmf_buf_imag[][64],
773                               WORD32 num_columns, FLOAT32 pv_qmf_buf_real[][64],
774                               FLOAT32 pv_qmf_buf_imag[][64], WORD32 pitch_in_bins,
775                               FLOAT32 *dft_hbe_scratch_buf) {
776   WORD32 in_offset = 0;
777   WORD32 out_offset = 0;
778   WORD32 in_hop_size = ptr_hbe_txposer->in_hop_size;
779   WORD32 oversampling_flag = ptr_hbe_txposer->oversampling_flag;
780   WORD32 fft_size = ptr_hbe_txposer->fft_size[oversampling_flag];
781 
782   WORD32 out_hop_size = ptr_hbe_txposer->out_hop_size;
783   WORD32 num_in_samples = num_columns * ptr_hbe_txposer->synth_size;
784   WORD32 ana_fft_size = ptr_hbe_txposer->ana_fft_size[oversampling_flag];
785   WORD32 syn_fft_size = ptr_hbe_txposer->syn_fft_size[oversampling_flag];
786 
787   WORD32 ana_pad_size = (ana_fft_size - ptr_hbe_txposer->ana_fft_size[0]) / 2;
788   WORD32 syn_pad_size = (syn_fft_size - ptr_hbe_txposer->syn_fft_size[0]) / 2;
789 
790   FLOAT32 *ptr_input_buf = ptr_hbe_txposer->ptr_input_buf;
791   FLOAT32 *ptr_output_buf = ptr_hbe_txposer->ptr_output_buf;
792   FLOAT32 *ptr_spectrum = ptr_hbe_txposer->ptr_spectrum;
793   FLOAT32 *ptr_spectrum_tx = ptr_hbe_txposer->ptr_spectrum_tx;
794   FLOAT32 *mag = ptr_hbe_txposer->mag;
795   FLOAT32 *phase = ptr_hbe_txposer->phase;
796   WORD32 i, trans_fac;
797 
798   FLOAT32 *ptr_cos_fft;
799   FLOAT32 *ptr_cos_ifft;
800 
801   WORD32 ana_fft_offset = ptr_hbe_txposer->k_start * fft_size / 32;
802   WORD32 syn_fft_offset = ptr_hbe_txposer->a_start * fft_size / 64;
803 
804   WORD32 err_code = IA_NO_ERROR;
805 
806   memcpy(ptr_hbe_txposer->ptr_input_buf,
807          ptr_hbe_txposer->ptr_input_buf + ptr_hbe_txposer->ana_fft_size[0],
808          ptr_hbe_txposer->ana_fft_size[0] * sizeof(ptr_hbe_txposer->ptr_input_buf[0]));
809 
810   ixheaacd_real_synth_filt(ptr_hbe_txposer, num_columns, qmf_buf_real, qmf_buf_imag);
811   memcpy(ptr_output_buf, ptr_output_buf + 2 * ptr_hbe_txposer->syn_fft_size[0],
812          2 * ptr_hbe_txposer->syn_fft_size[0] * sizeof(*ptr_output_buf));
813 
814   memset(ptr_output_buf + 2 * ptr_hbe_txposer->syn_fft_size[0], 0,
815          2 * ptr_hbe_txposer->syn_fft_size[0] * sizeof(*ptr_output_buf));
816 
817   err_code = ixheaacd_hbe_fft_map(ptr_hbe_txposer);
818   if (err_code) return err_code;
819   while (in_offset < num_in_samples) {
820     memset(ptr_spectrum, 0, fft_size * sizeof(FLOAT32));
821     memset(ptr_spectrum_tx, 0, ((fft_size + 2) * sizeof(FLOAT32)));
822 
823     memset(mag, 0, (fft_size / 2 + 2) * sizeof(FLOAT32));
824     memset(phase, 0, (fft_size / 2 + 2) * sizeof(FLOAT32));
825     ixheaacd_dft_hbe_apply_win(ptr_input_buf + in_offset, ptr_hbe_txposer->anal_window,
826                                ptr_spectrum + ana_pad_size + ana_fft_offset,
827                                ptr_hbe_txposer->ana_fft_size[0]);
828     ixheaacd_dft_hbe_fft_memmove(ptr_spectrum + ana_fft_offset, ana_fft_size);
829     {
830       WORD32 len = ana_fft_size;
831       ptr_cos_fft = ptr_hbe_txposer->ana_cos_sin_tab;
832       FLOAT32 *ptr_fft_data = ptr_spectrum + ana_fft_offset;
833       FLOAT32 tmp1, tmp2, tmp3, tmp4;
834 
835       (*(ptr_hbe_txposer->ixheaacd_hbe_anal_fft))(ptr_fft_data, dft_hbe_scratch_buf,
836                                                   len / 2, -1);
837 
838       tmp1 = ptr_fft_data[0] + ptr_fft_data[1];
839       ptr_fft_data[1] = ptr_fft_data[0] - ptr_fft_data[1];
840       ptr_fft_data[0] = tmp1;
841 
842       for (i = 1; i <= (len / 4 + (len % 4) / 2); ++i) {
843         tmp1 = ptr_fft_data[2 * i] - ptr_fft_data[len - 2 * i];
844         tmp2 = ptr_fft_data[2 * i + 1] + ptr_fft_data[len - 2 * i + 1];
845 
846         tmp3 = (*(ptr_cos_fft)) * tmp1 -
847                (*(ptr_cos_fft + 1)) * tmp2;
848         tmp4 = (*(ptr_cos_fft + 1)) * tmp1 +
849                (*(ptr_cos_fft)) * tmp2;
850 
851         ptr_cos_fft = ptr_cos_fft + 2;
852 
853         tmp1 = ptr_fft_data[2 * i] + ptr_fft_data[len - 2 * i];
854         tmp2 = ptr_fft_data[2 * i + 1] - ptr_fft_data[len - 2 * i + 1];
855 
856         ptr_fft_data[2 * i + 0] = 0.5f * (tmp1 - tmp3);
857         ptr_fft_data[2 * i + 1] = 0.5f * (tmp2 - tmp4);
858         ptr_fft_data[len - 2 * i + 0] = 0.5f * (tmp1 + tmp3);
859         ptr_fft_data[len - 2 * i + 1] = -0.5f * (tmp2 + tmp4);
860       }
861     }
862     ixheaacd_karth2polar(ptr_spectrum + ana_fft_offset, mag + ana_fft_offset / 2,
863                          phase + ana_fft_offset / 2, ana_fft_size);
864 
865     for (trans_fac = 2; trans_fac <= ptr_hbe_txposer->max_stretch; trans_fac++) {
866       WORD32 out_transform_size;
867 
868       out_transform_size = (fft_size / 2);
869 
870       switch (trans_fac) {
871         case 2:
872           ixheaacd_dft_hbe_apply_polar_t2(trans_fac, ptr_hbe_txposer,
873                                           pitch_in_bins, out_transform_size);
874           break;
875         case 3:
876           ixheaacd_dft_hbe_apply_polar_t3(trans_fac, ptr_hbe_txposer,
877                                           pitch_in_bins, out_transform_size);
878           break;
879         default:
880           ixheaacd_dft_hbe_apply_polar_t(trans_fac, ptr_hbe_txposer,
881                                          pitch_in_bins, out_transform_size);
882       }
883     }
884 
885     ptr_spectrum_tx[syn_fft_offset + 1] = ptr_spectrum_tx[syn_fft_offset +
886                                                           syn_fft_size];
887 
888     {
889       WORD32 len = syn_fft_size;
890       ptr_cos_ifft = ptr_hbe_txposer->syn_cos_sin_tab;
891       FLOAT32 *ptr_fft_data = ptr_spectrum_tx + syn_fft_offset;
892       FLOAT32 tmp1, tmp2, tmp3, tmp4;
893 
894       FLOAT32 scale = 1.0f / len;
895       tmp1 = ptr_fft_data[0] + ptr_fft_data[1];
896       ptr_fft_data[1] = scale * (ptr_fft_data[0] - ptr_fft_data[1]);
897       ptr_fft_data[0] = scale * tmp1;
898 
899       for (i = 1; i <= (len / 4 + (len % 4) / 2); ++i) {
900         tmp1 = ptr_fft_data[2 * i] - ptr_fft_data[len - 2 * i];
901         tmp2 = ptr_fft_data[2 * i + 1] + ptr_fft_data[len - 2 * i + 1];
902 
903         tmp3 = (*(ptr_cos_ifft)) * tmp1 +
904                (*(ptr_cos_ifft + 1)) * tmp2;
905         tmp4 = -(*(ptr_cos_ifft + 1)) * tmp1 +
906                (*(ptr_cos_ifft)) * tmp2;
907 
908         ptr_cos_ifft = ptr_cos_ifft + 2;
909 
910         tmp1 = ptr_fft_data[2 * i] + ptr_fft_data[len - 2 * i];
911         tmp2 = ptr_fft_data[2 * i + 1] - ptr_fft_data[len - 2 * i + 1];
912 
913         ptr_fft_data[2 * i] = scale * (tmp1 - tmp3);
914         ptr_fft_data[2 * i + 1] = scale * (tmp2 - tmp4);
915         ptr_fft_data[len - 2 * i] = scale * (tmp1 + tmp3);
916         ptr_fft_data[len - 2 * i + 1] = -scale * (tmp2 + tmp4);
917       }
918 
919       (*(ptr_hbe_txposer->ixheaacd_hbe_synth_ifft))(ptr_fft_data, dft_hbe_scratch_buf,
920                                                     len / 2, 1);
921     }
922 
923     ixheaacd_dft_hbe_fft_memmove(ptr_spectrum_tx + syn_fft_offset, syn_fft_size);
924     ixheaacd_dft_hbe_apply_win(
925         ptr_spectrum_tx + syn_pad_size + syn_fft_offset, ptr_hbe_txposer->synth_window,
926         ptr_spectrum_tx + syn_pad_size + syn_fft_offset, ptr_hbe_txposer->syn_fft_size[0]);
927 
928     for (i = 0; i < ptr_hbe_txposer->syn_fft_size[0]; i++) {
929       ptr_output_buf[out_offset + i] += ptr_spectrum_tx[syn_pad_size + syn_fft_offset + i];
930     }
931 
932     in_offset += in_hop_size;
933     out_offset += out_hop_size;
934 
935   }
936 
937   err_code = ixheaacd_dft_hbe_cplx_anal_filt(ptr_hbe_txposer, pv_qmf_buf_real,
938                                              pv_qmf_buf_imag);
939 
940   return err_code;
941 }
942