xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_sbr_hbe_dft_trans.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1 /******************************************************************************
2  *                                                                            *
3  * Copyright (C) 2023 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 
21 #include <math.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "ixheaac_type_def.h"
26 #include "ixheaace_bitbuffer.h"
27 #include "iusace_tns_usac.h"
28 #include "iusace_cnst.h"
29 #include "ixheaace_sbr_def.h"
30 #include "ixheaace_resampler.h"
31 #include "ixheaace_sbr_hbe.h"
32 #include "ixheaace_sbr_hbe_fft.h"
33 #include "ixheaace_error_codes.h"
34 #include "ixheaace_common_rom.h"
35 #include "ixheaac_error_standards.h"
36 #include "ixheaac_constants.h"
37 #include "ixheaac_esbr_rom.h"
38 
ixheaace_map_prot_filter(WORD32 filt_length)39 static FLOAT32 *ixheaace_map_prot_filter(WORD32 filt_length) {
40   switch (filt_length) {
41     case 4:
42       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[0];
43       break;
44     case 8:
45       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[40];
46       break;
47     case 12:
48       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[120];
49       break;
50     case 16:
51       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[240];
52       break;
53     case 20:
54       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[400];
55       break;
56     case 24:
57       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[600];
58       break;
59     case 28:
60       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff_28_36[0];
61       break;
62     case 32:
63       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[840];
64       break;
65     case 36:
66       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff_28_36[280];
67       break;
68     case 40:
69       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[1160];
70       break;
71     case 44:
72       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[1560];
73       break;
74     default:
75       return (FLOAT32 *)&ixheaac_sub_samp_qmf_window_coeff[0];
76   }
77 }
78 
79 /**
80  * Calculate frequency domain window according to 23003-3:2012, 7.5.3.1 eSBR - Tool description
81  */
ixheaace_create_dft_hbe_window(FLOAT32 * ptr_win,WORD32 x_over_bin1,WORD32 x_over_bin2,WORD32 ts,WORD32 size)82 static VOID ixheaace_create_dft_hbe_window(FLOAT32 *ptr_win, WORD32 x_over_bin1,
83                                            WORD32 x_over_bin2, WORD32 ts, WORD32 size) {
84   const FLOAT32 *ptr_freq_domain_win = NULL;
85   WORD32 n;
86   if (ts == 12) {
87     ptr_freq_domain_win = &ixheaac_dft_hbe_window_ts_12[0];
88   } else {
89     ptr_freq_domain_win = &ixheaac_dft_hbe_window_ts_18[0];
90   }
91   for (n = 0; n < (x_over_bin1 - ts / 2); n++) {
92     ptr_win[n] = 0;
93   }
94 
95   for (n = (x_over_bin1 - ts / 2); n <= (x_over_bin1 + ts / 2); n++) {
96     ptr_win[n] = (FLOAT32)ptr_freq_domain_win[n - (x_over_bin1 - ts / 2)];
97   }
98 
99   for (n = (x_over_bin1 + ts / 2 + 1); n < (x_over_bin2 - ts / 2); n++) {
100     ptr_win[n] = (FLOAT32)1.0f;
101   }
102 
103   for (n = (x_over_bin2 - ts / 2); n <= (x_over_bin2 + ts / 2); n++) {
104     ptr_win[n] = (FLOAT32)1.0f - ptr_freq_domain_win[n - (x_over_bin2 - ts / 2)];
105   }
106 
107   for (n = (x_over_bin2 + ts / 2 + 1); n < size; n++) {
108     ptr_win[n] = 0.0f;
109   }
110 }
111 
ixheaace_calc_anal_synth_window(WORD32 fft_size,FLOAT32 * ptr_window)112 static IA_ERRORCODE ixheaace_calc_anal_synth_window(WORD32 fft_size, FLOAT32 *ptr_window) {
113   FLOAT32 sin_pi_2_n = 0.0f;
114   FLOAT32 cos_pi_2_n = 0.0f;
115   FLOAT32 *ptr_sin_pi_n_by_n = NULL;
116   WORD32 hop_stride = 1;
117   WORD32 i, j;
118   WORD32 l_fft_stride = 512;
119   switch (fft_size) {
120     case 64:
121       hop_stride = 16;
122       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
123       sin_pi_2_n = ptr_sin_pi_n_by_n[hop_stride >> 1];
124       cos_pi_2_n = ptr_sin_pi_n_by_n[512 + (hop_stride >> 1)];
125       l_fft_stride = 512;
126       break;
127     case 128:
128       hop_stride = 8;
129       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
130       sin_pi_2_n = ptr_sin_pi_n_by_n[hop_stride >> 1];
131       cos_pi_2_n = ptr_sin_pi_n_by_n[512 + (hop_stride >> 1)];
132       l_fft_stride = 512;
133       break;
134     case 256:
135       hop_stride = 4;
136       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
137       sin_pi_2_n = ptr_sin_pi_n_by_n[hop_stride >> 1];
138       cos_pi_2_n = ptr_sin_pi_n_by_n[512 + (hop_stride >> 1)];
139       l_fft_stride = 512;
140       break;
141     case 512:
142       hop_stride = 2;
143       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
144       sin_pi_2_n = ptr_sin_pi_n_by_n[1];
145       cos_pi_2_n = ptr_sin_pi_n_by_n[512 + 1];
146       l_fft_stride = 512;
147       break;
148     case 1024:
149       hop_stride = 1;
150       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_1024[0];
151       sin_pi_2_n = ixheaac_sine_pi_by_2_N[0];
152       cos_pi_2_n = ixheaac_sine_pi_by_2_N[1];
153       l_fft_stride = 512;
154       break;
155     case 192:
156       hop_stride = 4;
157       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_768[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[384 + (hop_stride >> 1)];
160       l_fft_stride = 384;
161       break;
162     case 384:
163       hop_stride = 2;
164       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_768[0];
165       sin_pi_2_n = ptr_sin_pi_n_by_n[1];
166       cos_pi_2_n = ptr_sin_pi_n_by_n[384 + 1];
167       l_fft_stride = 384;
168       break;
169     case 768:
170       hop_stride = 1;
171       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_768[0];
172       sin_pi_2_n = ixheaac_sine_pi_by_2_N[8];
173       cos_pi_2_n = ixheaac_sine_pi_by_2_N[9];
174       l_fft_stride = 384;
175       break;
176     case 320:
177       hop_stride = 3;
178       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_960[0];
179       sin_pi_2_n = ixheaac_sine_pi_by_2_N[16];
180       cos_pi_2_n = ixheaac_sine_pi_by_2_N[17];
181       l_fft_stride = 480;
182       break;
183     case 960:
184       hop_stride = 1;
185       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_960[0];
186       sin_pi_2_n = ixheaac_sine_pi_by_2_N[2];
187       cos_pi_2_n = ixheaac_sine_pi_by_2_N[3];
188       l_fft_stride = 480;
189       break;
190     case 448:
191       hop_stride = 2;
192       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_896[0];
193       sin_pi_2_n = ptr_sin_pi_n_by_n[1];
194       cos_pi_2_n = ptr_sin_pi_n_by_n[448 + 1];
195       l_fft_stride = 448;
196       break;
197     case 896:
198       hop_stride = 1;
199       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_896[0];
200       sin_pi_2_n = ixheaac_sine_pi_by_2_N[4];
201       cos_pi_2_n = ixheaac_sine_pi_by_2_N[5];
202       l_fft_stride = 448;
203       break;
204     case 576:
205       hop_stride = 1;
206       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_576[0];
207       sin_pi_2_n = ixheaac_sine_pi_by_2_N[14];
208       cos_pi_2_n = ixheaac_sine_pi_by_2_N[15];
209       l_fft_stride = 288;
210       break;
211     case 640:
212       hop_stride = 1;
213       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_640[0];
214       sin_pi_2_n = ixheaac_sine_pi_by_2_N[12];
215       cos_pi_2_n = ixheaac_sine_pi_by_2_N[13];
216       l_fft_stride = 320;
217       break;
218     case 704:
219       hop_stride = 1;
220       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_704[0];
221       sin_pi_2_n = ixheaac_sine_pi_by_2_N[10];
222       cos_pi_2_n = ixheaac_sine_pi_by_2_N[11];
223       l_fft_stride = 352;
224       break;
225     case 832:
226       hop_stride = 1;
227       ptr_sin_pi_n_by_n = (FLOAT32 *)&ixheaac_sine_pi_n_by_832[0];
228       sin_pi_2_n = ixheaac_sine_pi_by_2_N[6];
229       cos_pi_2_n = ixheaac_sine_pi_by_2_N[7];
230       l_fft_stride = 416;
231       break;
232     default:
233       return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_MAPPING;
234   }
235 
236   /*calculate Window*/
237   for (i = 0, j = 0; j < (fft_size >> 1); i += hop_stride, j++) {
238     FLOAT32 cos_val = ptr_sin_pi_n_by_n[i + l_fft_stride];
239     FLOAT32 sin_val = ptr_sin_pi_n_by_n[i];
240     ptr_window[j] = cos_val * sin_pi_2_n + sin_val * cos_pi_2_n;
241   }
242 
243   for (; j < fft_size; j++, i += hop_stride) {
244     FLOAT32 cos_val = ptr_sin_pi_n_by_n[i - l_fft_stride];
245     FLOAT32 sin_val = ptr_sin_pi_n_by_n[i];
246     ptr_window[j] = sin_val * cos_pi_2_n - cos_val * sin_pi_2_n;
247   }
248   return IA_NO_ERROR;
249 }
250 
ixheaace_esbr_hbe_data_init(ixheaace_str_esbr_hbe_txposer * pstr_esbr_hbe_txposer,const WORD32 num_aac_samples,WORD32 samp_fac_4_flag,const WORD32 num_out_samples,VOID * ptr_persistent_hbe_mem,WORD32 * ptr_total_persistant)251 VOID ixheaace_esbr_hbe_data_init(ixheaace_str_esbr_hbe_txposer *pstr_esbr_hbe_txposer,
252                                  const WORD32 num_aac_samples, WORD32 samp_fac_4_flag,
253                                  const WORD32 num_out_samples, VOID *ptr_persistent_hbe_mem,
254                                  WORD32 *ptr_total_persistant) {
255   WORD32 used_persistent = 0;
256 
257   if (pstr_esbr_hbe_txposer) {
258     memset(pstr_esbr_hbe_txposer, 0, sizeof(ixheaace_str_esbr_hbe_txposer));
259 
260     pstr_esbr_hbe_txposer->core_frame_length = num_aac_samples;
261 
262     pstr_esbr_hbe_txposer->no_bins = num_out_samples / IXHEAACE_NUM_QMF_SYNTH_CHANNELS;
263 
264     pstr_esbr_hbe_txposer->hbe_qmf_in_len = pstr_esbr_hbe_txposer->no_bins;
265 
266     pstr_esbr_hbe_txposer->hbe_qmf_out_len = 2 * pstr_esbr_hbe_txposer->hbe_qmf_in_len;
267 
268     pstr_esbr_hbe_txposer->ptr_input_buf = (FLOAT32 *)ptr_persistent_hbe_mem;
269     used_persistent += (num_aac_samples + IXHEAACE_NUM_QMF_SYNTH_CHANNELS) *
270                        sizeof(pstr_esbr_hbe_txposer->ptr_input_buf[0]);
271 
272     pstr_esbr_hbe_txposer->upsamp_4_flag = samp_fac_4_flag;
273 
274     if (pstr_esbr_hbe_txposer) {
275       pstr_esbr_hbe_txposer->fft_size[0] = num_aac_samples;
276       pstr_esbr_hbe_txposer->fft_size[1] = (int)(IXHEAACE_FD_OVERSAMPLING_FAC * num_aac_samples);
277 
278       /*
279         Worst Case Memory requirements for DFT based HBE.
280         analysis ptr_win = num_aac_samples * sizeof(float)          = 1024 * sizeof(FLOAT32)
281         synthesis ptr_win = num_aac_samples * sizeof(float)         = 1024 * sizeof(FLOAT32)
282         ptr_spectrum = num_aac_samples * sizeof(float) * 1.5        = 1536 * sizeof(FLOAT32)
283         spectrumTransposed = num_aac_samples * sizeof(float)    = 1536 * sizeof(FLOAT32)
284         ptr_mag                                                     = 1536 * sizeof(FLOAT32)
285         ptr_phase                                                   = 1536 * sizeof(FLOAT32)
286         pstr_esbr_hbe_txposer->inBuf                            = 2048 * sizeof(FLOAT32)
287         pstr_esbr_hbe_txposer->outBuf                           = 4096 * sizeof(FLOAT32)
288         fd_win_buf                                                   = 2560 * 3 * sizeof(FLOAT32)
289         Total ~ (1024 * 2 + 1536 * 4 + 2048 * 1 + 4096 * 1 + 2560 * 3) * sizeof(FLOAT32)
290         = 22016 * sizeof(FLOAT32)
291        */
292 
293       pstr_esbr_hbe_txposer->ptr_spectrum = &pstr_esbr_hbe_txposer->spectrum_buf[0];
294       pstr_esbr_hbe_txposer->ptr_spectrum_tx = &pstr_esbr_hbe_txposer->spectrum_transposed_buf[0];
295       pstr_esbr_hbe_txposer->ptr_mag = &pstr_esbr_hbe_txposer->mag_buf[0];
296       pstr_esbr_hbe_txposer->ptr_phase = &pstr_esbr_hbe_txposer->phase_buf[0];
297       pstr_esbr_hbe_txposer->ptr_output_buf = &pstr_esbr_hbe_txposer->output_buf[0];
298     }
299   }
300   *ptr_total_persistant = used_persistent;
301 }
302 
ixheaace_dft_hbe_data_reinit(ixheaace_str_esbr_hbe_txposer * pstr_hbe_txposer)303 IA_ERRORCODE ixheaace_dft_hbe_data_reinit(ixheaace_str_esbr_hbe_txposer *pstr_hbe_txposer) {
304   WORD32 sfb;
305   WORD32 patch;
306   WORD32 i;
307   WORD32 temp_start;
308   FLOAT32 fb_ratio;
309   WORD32 stop_patch;
310   WORD32 in_hop_size_divisor = 8;
311   static const WORD32 trans_samp[2] = {12, 18}; /* FD transition samples */
312   WORD32 err = IA_NO_ERROR;
313 
314   pstr_hbe_txposer->start_band = pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_LOW][0];
315   pstr_hbe_txposer->end_band =
316       pstr_hbe_txposer
317           ->ptr_freq_band_tab[IXHEAACE_LOW][pstr_hbe_txposer->num_sf_bands[IXHEAACE_LOW]];
318   pstr_hbe_txposer->esbr_hq = 1;
319 
320   pstr_hbe_txposer->synth_size = 4 * ((pstr_hbe_txposer->start_band + 4) / 8 + 1);
321   pstr_hbe_txposer->k_start = ixheaac_start_subband2kL_tbl[pstr_hbe_txposer->start_band];
322 
323   fb_ratio = pstr_hbe_txposer->synth_size / 32.0f;
324 
325   pstr_hbe_txposer->ana_fft_size[0] = (WORD32)(fb_ratio * pstr_hbe_txposer->fft_size[0]);
326   pstr_hbe_txposer->ana_fft_size[1] = (WORD32)(fb_ratio * pstr_hbe_txposer->fft_size[1]);
327 
328   pstr_hbe_txposer->in_hop_size = pstr_hbe_txposer->ana_fft_size[0] / in_hop_size_divisor;
329 
330   pstr_hbe_txposer->ptr_syn_win = (FLOAT32 *)&pstr_hbe_txposer->synthesis_window_buf[0];
331   pstr_hbe_txposer->ptr_ana_win = (FLOAT32 *)&pstr_hbe_txposer->analysis_window_buf[0];
332 
333   err = ixheaace_calc_anal_synth_window(pstr_hbe_txposer->ana_fft_size[0],
334                                         pstr_hbe_txposer->ptr_ana_win);
335   if (err) {
336     return err;
337   }
338 
339   memset(pstr_hbe_txposer->synth_buf, 0, sizeof(pstr_hbe_txposer->synth_buf));
340 
341   pstr_hbe_txposer->ptr_syn_win_coeff = ixheaace_map_prot_filter(pstr_hbe_txposer->synth_size);
342 
343   temp_start = 2 * ((pstr_hbe_txposer->start_band - 1) / 2); /* Largest start band */
344   pstr_hbe_txposer->analy_size =
345       4 * ((min(64, pstr_hbe_txposer->end_band + 1) - temp_start - 1) / 4 +
346            1); /* Quantize in steps of 4 */
347   pstr_hbe_txposer->a_start = temp_start - max(0, temp_start + pstr_hbe_txposer->analy_size - 64);
348 
349   fb_ratio = pstr_hbe_txposer->analy_size / 64.0f;
350 
351   pstr_hbe_txposer->syn_fft_size[0] = (WORD32)(fb_ratio * pstr_hbe_txposer->fft_size[0]);
352   pstr_hbe_txposer->syn_fft_size[1] = (WORD32)(fb_ratio * pstr_hbe_txposer->fft_size[1]);
353 
354   pstr_hbe_txposer->out_hop_size = 2 * pstr_hbe_txposer->syn_fft_size[0] / in_hop_size_divisor;
355 
356   err = ixheaace_calc_anal_synth_window(pstr_hbe_txposer->syn_fft_size[0],
357                                         pstr_hbe_txposer->ptr_syn_win);
358   if (err) {
359     return err;
360   }
361 
362   pstr_hbe_txposer->ptr_ana_win_coeff = ixheaace_map_prot_filter(pstr_hbe_txposer->analy_size);
363 
364   /* calculation of x_over_bin array and x_over_qmf array */
365 
366   memset(&pstr_hbe_txposer->x_over_qmf[0], 0, sizeof(pstr_hbe_txposer->x_over_qmf));
367 
368   for (i = 0; i < IXHEAACE_MAX_STRETCH; i++) {
369     memset(&pstr_hbe_txposer->x_over_bin[i][0], 0,
370            2 * sizeof(pstr_hbe_txposer->x_over_bin[i][0]));
371   }
372   sfb = 0;
373   stop_patch = IXHEAACE_MAX_STRETCH;
374 
375   switch (pstr_hbe_txposer->synth_size) {
376     case 4:
377       pstr_hbe_txposer->ptr_syn_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_4;
378       pstr_hbe_txposer->ixheaace_real_synth_fft = &ixheaac_real_synth_fft_p2;
379       break;
380     case 8:
381       pstr_hbe_txposer->ptr_syn_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_8;
382       pstr_hbe_txposer->ixheaace_real_synth_fft = &ixheaac_real_synth_fft_p2;
383       break;
384     case 12:
385       pstr_hbe_txposer->ptr_syn_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_12;
386       pstr_hbe_txposer->ixheaace_real_synth_fft = &ixheaac_real_synth_fft_p3;
387       break;
388     case 16:
389       pstr_hbe_txposer->ptr_syn_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_16;
390       pstr_hbe_txposer->ixheaace_real_synth_fft = &ixheaac_real_synth_fft_p2;
391       break;
392     case 20:
393       pstr_hbe_txposer->ptr_syn_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_20;
394       break;
395     case 28:
396       pstr_hbe_txposer->ptr_syn_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_20;
397       break;
398     default:
399       pstr_hbe_txposer->ptr_syn_cos_tab = (FLOAT32 *)ixheaac_synth_cos_table_kl_4;
400       pstr_hbe_txposer->ixheaace_real_synth_fft = &ixheaac_real_synth_fft_p2;
401   }
402 
403   {
404     WORD32 l, k, L = pstr_hbe_txposer->analy_size;
405     for (k = 0; k < L; k++) {
406       for (l = 0; l < 2 * L; l++) {
407         pstr_hbe_txposer->str_dft_hbe_anal_coeff.real[k][l] =
408             (FLOAT32)cos(PI / (2 * L) *
409                          ((k + 0.5) * (2 * l - L / 64.0) - L / 64.0 * pstr_hbe_txposer->a_start));
410         pstr_hbe_txposer->str_dft_hbe_anal_coeff.imag[k][l] =
411             (FLOAT32)sin(PI / (2 * L) *
412                          ((k + 0.5) * (2 * l - L / 64.0) - L / 64.0 * pstr_hbe_txposer->a_start));
413       }
414     }
415   }
416 
417   for (patch = 1; patch <= stop_patch; patch++) {
418     while (sfb <= pstr_hbe_txposer->num_sf_bands[IXHEAACE_LOW] &&
419            pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_LOW][sfb] <=
420                patch * pstr_hbe_txposer->start_band)
421       sfb++;
422     if (sfb <= pstr_hbe_txposer->num_sf_bands[IXHEAACE_LOW]) {
423       /* If the distance is larger than three QMF bands - try aligning to high resolution
424        * frequency bands instead. */
425       if ((patch * pstr_hbe_txposer->start_band -
426            pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_LOW][sfb - 1]) <= 3) {
427         pstr_hbe_txposer->x_over_qmf[patch - 1] =
428             pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_LOW][sfb - 1];
429         if (patch <= IXHEAACE_MAX_STRETCH) {
430           pstr_hbe_txposer->x_over_bin[patch - 1][0] =
431               (WORD32)(pstr_hbe_txposer->fft_size[0] *
432                            pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_LOW][sfb - 1] / 128 +
433                        0.5);
434           pstr_hbe_txposer->x_over_bin[patch - 1][1] =
435               (WORD32)(pstr_hbe_txposer->fft_size[1] *
436                            pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_LOW][sfb - 1] / 128 +
437                        0.5);
438         }
439       } else {
440         WORD32 sfb_idx = 0;
441         while (sfb_idx <= pstr_hbe_txposer->num_sf_bands[IXHEAACE_HIGH] &&
442                pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_HIGH][sfb_idx] <=
443                    patch * pstr_hbe_txposer->start_band)
444           sfb_idx++;
445         pstr_hbe_txposer->x_over_qmf[patch - 1] =
446             pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_HIGH][sfb_idx - 1];
447         if (patch <= IXHEAACE_MAX_STRETCH) {
448           pstr_hbe_txposer->x_over_bin[patch - 1][0] =
449               (WORD32)(pstr_hbe_txposer->fft_size[0] *
450                            pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_HIGH][sfb_idx - 1] / 128 +
451                        0.5);
452           pstr_hbe_txposer->x_over_bin[patch - 1][1] =
453               (WORD32)(pstr_hbe_txposer->fft_size[1] *
454                            pstr_hbe_txposer->ptr_freq_band_tab[IXHEAACE_HIGH][sfb_idx - 1] / 128 +
455                        0.5);
456         }
457       }
458     } else {
459       pstr_hbe_txposer->x_over_qmf[patch - 1] = pstr_hbe_txposer->end_band;
460       if (patch <= IXHEAACE_MAX_STRETCH) {
461         pstr_hbe_txposer->x_over_bin[patch - 1][0] =
462             (WORD32)(pstr_hbe_txposer->fft_size[0] * pstr_hbe_txposer->end_band / 128 + 0.5);
463         pstr_hbe_txposer->x_over_bin[patch - 1][1] =
464             (WORD32)(pstr_hbe_txposer->fft_size[1] * pstr_hbe_txposer->end_band / 128 + 0.5);
465       }
466       pstr_hbe_txposer->max_stretch = min(patch, IXHEAACE_MAX_STRETCH);
467       break;
468     }
469   }
470 
471   /* calculation of frequency domain windows */
472   for (patch = 0; patch < pstr_hbe_txposer->max_stretch - 1; patch++) {
473     for (i = 0; i < 2; i++) {
474       ixheaace_create_dft_hbe_window(pstr_hbe_txposer->fd_win_buf[patch][i],
475                                      pstr_hbe_txposer->x_over_bin[patch][i],
476                                      pstr_hbe_txposer->x_over_bin[patch + 1][i], trans_samp[i],
477                                      pstr_hbe_txposer->fft_size[i]);
478     }
479   }
480   return err;
481 }
482 
ixheaace_dft_hbe_apply_win(const FLOAT32 * ptr_x,const FLOAT32 * ptr_y,FLOAT32 * ptr_z,WORD32 n)483 static VOID ixheaace_dft_hbe_apply_win(const FLOAT32 *ptr_x, const FLOAT32 *ptr_y, FLOAT32 *ptr_z,
484                                        WORD32 n) {
485   WORD32 i;
486   for (i = 0; i < n; i++) {
487     ptr_z[i] = ptr_x[i] * ptr_y[i];
488   }
489 }
490 
ixheaace_dft_hbe_fft_memmove(FLOAT32 * ptr_spectrum,WORD32 size)491 VOID ixheaace_dft_hbe_fft_memmove(FLOAT32 *ptr_spectrum, WORD32 size) {
492   WORD32 n = 0;
493 
494   while (n < size / 2) {
495     FLOAT32 tmp = ptr_spectrum[n];
496     ptr_spectrum[n] = ptr_spectrum[n + size / 2];
497     ptr_spectrum[n + size / 2] = tmp;
498     n++;
499   }
500 }
ixheaace_karth2polar(FLOAT32 * ptr_spectrum,FLOAT32 * ptr_mag,FLOAT32 * ptr_phase,WORD32 fft_size)501 VOID ixheaace_karth2polar(FLOAT32 *ptr_spectrum, FLOAT32 *ptr_mag, FLOAT32 *ptr_phase,
502                           WORD32 fft_size) {
503   WORD32 n;
504 
505   for (n = 1; n < fft_size / 2; n++) {
506     ptr_phase[n] = (FLOAT32)atan2(ptr_spectrum[2 * n + 1], ptr_spectrum[2 * n]);
507     ptr_mag[n] = (FLOAT32)sqrt(ptr_spectrum[2 * n] * ptr_spectrum[2 * n] +
508                                ptr_spectrum[2 * n + 1] * ptr_spectrum[2 * n + 1]);
509   }
510 
511   if (ptr_spectrum[0] < 0) {
512     ptr_phase[0] = (FLOAT32)acos(-1);
513     ptr_mag[0] = -ptr_spectrum[0];
514   } else {
515     ptr_phase[0] = 0;
516     ptr_mag[0] = ptr_spectrum[0];
517   }
518 
519   if (ptr_spectrum[1] < 0) {
520     ptr_phase[fft_size / 2] = (FLOAT32)acos(-1);
521     ptr_mag[fft_size / 2] = -ptr_spectrum[1];
522   } else {
523     ptr_phase[fft_size / 2] = 0;
524     ptr_mag[fft_size / 2] = ptr_spectrum[1];
525   }
526 }
ixheaace_hbe_fft_tab(ixheaace_str_esbr_hbe_txposer * pstr_hbe_txposer)527 VOID ixheaace_hbe_fft_tab(ixheaace_str_esbr_hbe_txposer *pstr_hbe_txposer) {
528   WORD32 oversampling_flag = pstr_hbe_txposer->oversampling_flag;
529   WORD32 ana_fft_size = pstr_hbe_txposer->ana_fft_size[oversampling_flag];
530   WORD32 syn_fft_size = pstr_hbe_txposer->syn_fft_size[oversampling_flag];
531 
532   switch (ana_fft_size) {
533     case 576:
534       pstr_hbe_txposer->ptr_ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_576;
535       break;
536     case 384:
537       pstr_hbe_txposer->ptr_ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_384;
538       break;
539     case 512:
540       pstr_hbe_txposer->ptr_ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_512;
541       break;
542     case 768:
543       pstr_hbe_txposer->ptr_ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_768;
544       break;
545     default:
546       break;
547   }
548 
549   switch (syn_fft_size) {
550     case 448:
551       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_448;
552       break;
553     case 512:
554       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_512;
555       break;
556     case 768:
557       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_768;
558       break;
559     case 672:
560       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_672;
561       break;
562     default:
563       break;
564   }
565 }
566 
ixheaace_hbe_fft_map(ixheaace_str_esbr_hbe_txposer * pstr_hbe_txposer)567 IA_ERRORCODE ixheaace_hbe_fft_map(ixheaace_str_esbr_hbe_txposer *pstr_hbe_txposer) {
568   WORD32 oversampling_flag = pstr_hbe_txposer->oversampling_flag;
569   WORD32 ana_fft_size = pstr_hbe_txposer->ana_fft_size[oversampling_flag];
570   WORD32 syn_fft_size = pstr_hbe_txposer->syn_fft_size[oversampling_flag];
571 
572   switch (ana_fft_size) {
573     case 576:
574       pstr_hbe_txposer->ptr_ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_576;
575       pstr_hbe_txposer->ixheaace_hbe_anal_fft = &ixheaace_hbe_apply_fft_288;
576       break;
577     case 384:
578       pstr_hbe_txposer->ptr_ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_384;
579       pstr_hbe_txposer->ixheaace_hbe_anal_fft = &ixheaace_hbe_apply_cfftn_gen;
580       break;
581     case 512:
582       pstr_hbe_txposer->ptr_ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_512;
583       pstr_hbe_txposer->ixheaace_hbe_anal_fft = &ixheaace_hbe_apply_cfftn;
584       break;
585     case 768:
586       pstr_hbe_txposer->ptr_ana_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_768;
587       pstr_hbe_txposer->ixheaace_hbe_anal_fft = &ixheaace_hbe_apply_cfftn_gen;
588       break;
589     default:
590       return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_MAPPING;
591       break;
592   }
593 
594   switch (syn_fft_size) {
595     case 448:
596       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_448;
597       pstr_hbe_txposer->ixheaace_hbe_synth_ifft = &ixheaace_hbe_apply_ifft_224;
598       break;
599     case 512:
600       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_512;
601       pstr_hbe_txposer->ixheaace_hbe_synth_ifft = &ixheaace_hbe_apply_cfftn;
602       break;
603     case 576:
604       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_576;
605       pstr_hbe_txposer->ixheaace_hbe_synth_ifft = &ixheaace_hbe_apply_fft_288;
606       break;
607     case 768:
608       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_768;
609       pstr_hbe_txposer->ixheaace_hbe_synth_ifft = &ixheaace_hbe_apply_cfftn_gen;
610       break;
611     case 672:
612       pstr_hbe_txposer->ptr_syn_cos_sin_tab = (FLOAT32 *)ixheaac_sin_cos_672;
613       pstr_hbe_txposer->ixheaace_hbe_synth_ifft = &ixheaace_hbe_apply_ifft_336;
614       break;
615     default:
616       return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_MAPPING;
617       break;
618   }
619 
620   return IA_NO_ERROR;
621 }
622 
ia_dft_hbe_apply_polar_t2(WORD32 T,ixheaace_str_esbr_hbe_txposer * pstr_hbe_txposer,WORD32 pitch_in_bins,WORD out_transform_size)623 VOID ia_dft_hbe_apply_polar_t2(WORD32 T, ixheaace_str_esbr_hbe_txposer *pstr_hbe_txposer,
624                                WORD32 pitch_in_bins, WORD out_transform_size) {
625   WORD32 tr;
626   WORD32 ti;
627   WORD32 m_tr = 0;
628   WORD32 p, i;
629   FLOAT32 mag_t;
630   FLOAT32 phase_t;
631   FLOAT32 m_val;
632   FLOAT32(*fd_win_buf)[3][3][1536] = &pstr_hbe_txposer->fd_win_buf;
633   FLOAT32 *ptr_phase = pstr_hbe_txposer->ptr_phase;
634   WORD32 oversampling_flag = pstr_hbe_txposer->oversampling_flag;
635   WORD32 fft_size = pstr_hbe_txposer->fft_size[oversampling_flag];
636   FLOAT32 *ptr_spectrum_tx = pstr_hbe_txposer->ptr_spectrum_tx;
637   FLOAT32 *ptr_mag = pstr_hbe_txposer->ptr_mag;
638   /* pitch_in_bins is given with the resolution of a 1536 point FFT */
639   FLOAT32 p_flt = fft_size * pitch_in_bins / 1536.0f;
640   p = (WORD32)p_flt;
641   FLOAT32 q_thr = 4.0f;
642 
643   if (T < 2) {
644     // To avoid invalid access by fd_win_buf
645     T = 2;
646   }
647   i = 0;
648   while (i <= out_transform_size) {
649     WORD32 utk = i;
650 
651     mag_t = (*fd_win_buf)[T - 2][oversampling_flag][i] * ptr_mag[utk];
652 
653     phase_t = T * ptr_phase[utk];
654 
655     if (phase_t == 0.0) {
656       ptr_spectrum_tx[2 * i] += mag_t;
657     } else {
658       ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
659       ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
660     }
661     if (p > 0) {
662       m_val = 0;
663       for (tr = 1; tr < T; tr++) {
664         FLOAT32 temp;
665         ti = (WORD32)((2.0f * i - tr * p_flt) / T + 0.5f);
666         if ((ti < 0) || (ti + p > fft_size / 2)) continue;
667         temp = min(ptr_mag[ti], ptr_mag[ti + p]);
668         if (temp > m_val) {
669           m_val = temp;
670           m_tr = tr;
671           utk = ti;
672         }
673       } /* for tr */
674 
675       if (m_val > q_thr * ptr_mag[2 * i / T]) {
676         mag_t = (*fd_win_buf)[T - 2][oversampling_flag][i] * ((FLOAT32)sqrt(ptr_mag[utk])) *
677                 ((FLOAT32)sqrt(ptr_mag[utk + p]));
678         phase_t = ((FLOAT32)(T - m_tr)) * ptr_phase[utk] + ((FLOAT32)m_tr) * ptr_phase[utk + p];
679         ptr_spectrum_tx[2 * i] += mag_t * ((FLOAT32)cos(phase_t));
680         ptr_spectrum_tx[2 * i + 1] += mag_t * ((FLOAT32)sin(phase_t));
681       }
682     }
683     i++;
684   }
685 }
686 
ia_dft_hbe_apply_polar_t_3(WORD32 T,ixheaace_str_esbr_hbe_txposer * pstr_hbe_txposer,WORD32 pitch_in_bins,WORD out_transform_size)687 VOID ia_dft_hbe_apply_polar_t_3(WORD32 T, ixheaace_str_esbr_hbe_txposer *pstr_hbe_txposer,
688                                 WORD32 pitch_in_bins, WORD out_transform_size) {
689   WORD32 tr;
690   WORD32 ti;
691   WORD32 m_tr = 0;
692   WORD32 p, i;
693   FLOAT32 mag_t = 0.0f;
694   FLOAT32 phase_t;
695   FLOAT32 m_val;
696   FLOAT32(*fd_win_buf)[3][3][1536] = &pstr_hbe_txposer->fd_win_buf;
697   FLOAT32 *ptr_phase = pstr_hbe_txposer->ptr_phase;
698   WORD32 oversampling_flag = pstr_hbe_txposer->oversampling_flag;
699   WORD32 fft_size = pstr_hbe_txposer->fft_size[oversampling_flag];
700   FLOAT32 *ptr_spectrum_tx = pstr_hbe_txposer->ptr_spectrum_tx;
701   FLOAT32 *ptr_mag = pstr_hbe_txposer->ptr_mag;
702   /* pitch_in_bins is given with the resolution of a 1536 point FFT */
703   FLOAT32 p_flt = fft_size * pitch_in_bins / 1536.0f;
704   p = (WORD32)p_flt;
705   FLOAT32 q_thr = 4.0f;
706 
707   if (T < 3) {
708     // To avoid invalid access by fd_win_buf
709     T = 3;
710   }
711 
712   i = 0;
713   while (i <= out_transform_size) {
714     WORD32 utk = 2 * i / T;
715     FLOAT32 ptk = (2.0f * i / T) - utk;
716     FLOAT32 k;
717 
718     if (i % 3 == 0) {
719       mag_t = (*fd_win_buf)[T - 2][oversampling_flag][i] * ptr_mag[utk];
720     } else if (i % 3 == 1) {
721       k = (FLOAT32)cbrt(ptr_mag[utk]);
722       mag_t =
723           (*fd_win_buf)[T - 2][oversampling_flag][i] * k * (FLOAT32)pow(ptr_mag[utk + 1], ptk);
724     } else if (i % 3 == 2) {
725       k = (FLOAT32)cbrt(ptr_mag[utk + 1]);
726       mag_t =
727           (*fd_win_buf)[T - 2][oversampling_flag][i] * (FLOAT32)pow(ptr_mag[utk], 1.0 - ptk) * k;
728     }
729 
730     phase_t = T * ((1 - ptk) * ptr_phase[utk] + ptk * ptr_phase[utk + 1]);
731 
732     ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
733     ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
734 
735     if (p > 0) {
736       m_val = 0;
737       for (tr = 1; tr < T; tr++) {
738         FLOAT32 temp;
739         ti = (WORD32)((2.0f * i - tr * p_flt) / T + 0.5f);
740         if ((ti < 0) || (ti + p > fft_size / 2)) continue;
741         temp = min(ptr_mag[ti], ptr_mag[ti + p]);
742         if (temp > m_val) {
743           m_val = temp;
744           m_tr = tr;
745           utk = ti;
746         }
747       } /* for tr */
748 
749       if (m_val > q_thr * ptr_mag[2 * i / T]) {
750         FLOAT32 r = (FLOAT32)m_tr / T;
751         switch (m_tr) {
752           case 1:
753             k = (FLOAT32)(cbrt((FLOAT32)ptr_mag[utk + p]));
754             mag_t = (*fd_win_buf)[T - 2][oversampling_flag][i] *
755                     (FLOAT32)pow(ptr_mag[utk], 1.0 - r) * k;
756             phase_t = (T - m_tr) * ptr_phase[utk] + ptr_phase[utk + p];
757             break;
758 
759           case 2:
760             k = (FLOAT32)(cbrt((FLOAT32)ptr_mag[utk]));
761             mag_t = (*fd_win_buf)[T - 2][oversampling_flag][i] * k *
762                     (FLOAT32)pow(ptr_mag[utk + p], r);
763             phase_t = ptr_phase[utk] + m_tr * ptr_phase[utk + p];
764             break;
765         }
766 
767         ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
768         ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
769       }
770     }
771     i++;
772   }
773 }
774 
ia_dft_hbe_apply_polar_t(WORD32 T,ixheaace_str_esbr_hbe_txposer * pstr_hbe_txposer,WORD32 pitch_in_bins,WORD out_transform_size)775 VOID ia_dft_hbe_apply_polar_t(WORD32 T, ixheaace_str_esbr_hbe_txposer *pstr_hbe_txposer,
776                               WORD32 pitch_in_bins, WORD out_transform_size) {
777   WORD32 tr;
778   WORD32 ti;
779   WORD32 m_tr = 0;
780   WORD32 p, i;
781   FLOAT32 mag_t;
782   FLOAT32 phase_t;
783   FLOAT32 m_val;
784   FLOAT32(*fd_win_buf)[3][3][1536] = &pstr_hbe_txposer->fd_win_buf;
785   FLOAT32 *ptr_phase = pstr_hbe_txposer->ptr_phase;
786   WORD32 oversampling_flag = pstr_hbe_txposer->oversampling_flag;
787   WORD32 fft_size = pstr_hbe_txposer->fft_size[oversampling_flag];
788   FLOAT32 *ptr_spectrum_tx = pstr_hbe_txposer->ptr_spectrum_tx;
789   FLOAT32 *ptr_mag = pstr_hbe_txposer->ptr_mag;
790   /* pitch_in_bins is given with the resolution of a 1536 point FFT */
791   FLOAT32 p_flt = fft_size * pitch_in_bins / 1536.0f;
792   p = (WORD32)p_flt;
793   FLOAT32 q_thr = 4.0f;
794 
795   if (T < 2) {
796     // To avoid invalid access by fd_win_buf
797     T = 2;
798   }
799   for (i = 0; i <= out_transform_size; i++) {
800     WORD32 utk = 2 * i / T;
801     FLOAT32 ptk = (2.0f * i / T) - utk;
802 
803     mag_t = (*fd_win_buf)[T - 2][oversampling_flag][i] * (FLOAT32)pow(ptr_mag[utk], 1.0f - ptk) *
804             (FLOAT32)pow(ptr_mag[utk + 1], ptk);
805 
806     phase_t = T * ((1 - ptk) * ptr_phase[utk] + ptk * ptr_phase[utk + 1]);
807 
808     ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
809     ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
810 
811     if (p > 0) {
812       m_val = 0;
813       for (tr = 1; tr < T; tr++) {
814         FLOAT32 temp;
815         ti = (WORD32)((2.0f * i - tr * p_flt) / T + 0.5f);
816         if ((ti < 0) || (ti + p > fft_size / 2)) continue;
817         temp = min(ptr_mag[ti], ptr_mag[ti + p]);
818         if (temp > m_val) {
819           m_val = temp;
820           m_tr = tr;
821           utk = ti;
822         }
823       } /* for tr */
824 
825       if (m_val > q_thr * ptr_mag[2 * i / T]) {
826         FLOAT32 r = (FLOAT32)m_tr / T;
827         mag_t = (*fd_win_buf)[T - 2][oversampling_flag][i] * (FLOAT32)pow(ptr_mag[utk], 1.0 - r) *
828                 (FLOAT32)pow(ptr_mag[utk + p], r);
829         phase_t = (T - m_tr) * ptr_phase[utk] + m_tr * ptr_phase[utk + p];
830         ptr_spectrum_tx[2 * i] += mag_t * (FLOAT32)cos(phase_t);
831         ptr_spectrum_tx[2 * i + 1] += mag_t * (FLOAT32)sin(phase_t);
832       }
833     }
834   }
835 }
836 
ixheaace_dft_hbe_apply(ixheaace_str_esbr_hbe_txposer * pstr_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 * ptr_dft_hbe_scratch_buf)837 IA_ERRORCODE ixheaace_dft_hbe_apply(ixheaace_str_esbr_hbe_txposer *pstr_hbe_txposer,
838                                     FLOAT32 qmf_buf_real[][64], FLOAT32 qmf_buf_imag[][64],
839                                     WORD32 num_columns, FLOAT32 pv_qmf_buf_real[][64],
840                                     FLOAT32 pv_qmf_buf_imag[][64], WORD32 pitch_in_bins,
841                                     FLOAT32 *ptr_dft_hbe_scratch_buf) {
842   WORD32 in_offset = 0;
843   WORD32 out_offset = 0;
844   WORD32 in_hop_size = pstr_hbe_txposer->in_hop_size;
845   WORD32 oversampling_flag = pstr_hbe_txposer->oversampling_flag;
846   WORD32 fft_size = pstr_hbe_txposer->fft_size[oversampling_flag];
847 
848   WORD32 out_hop_size = pstr_hbe_txposer->out_hop_size;
849   WORD32 num_in_samples = num_columns * pstr_hbe_txposer->synth_size;
850   WORD32 ana_fft_size = pstr_hbe_txposer->ana_fft_size[oversampling_flag];
851   WORD32 syn_fft_size = pstr_hbe_txposer->syn_fft_size[oversampling_flag];
852 
853   WORD32 ana_pad_size = (ana_fft_size - pstr_hbe_txposer->ana_fft_size[0]) / 2;
854   WORD32 syn_pad_size = (syn_fft_size - pstr_hbe_txposer->syn_fft_size[0]) / 2;
855 
856   FLOAT32 *ptr_input_buf = pstr_hbe_txposer->ptr_input_buf;
857   FLOAT32 *ptr_output_buf = pstr_hbe_txposer->ptr_output_buf;
858   FLOAT32 *ptr_spectrum = pstr_hbe_txposer->ptr_spectrum;
859   FLOAT32 *ptr_spectrum_tx = pstr_hbe_txposer->ptr_spectrum_tx;
860   FLOAT32 *ptr_mag = pstr_hbe_txposer->ptr_mag;
861   FLOAT32 *ptr_phase = pstr_hbe_txposer->ptr_phase;
862   WORD32 i, T;
863   FLOAT32 *ptr_cos_fft;
864   FLOAT32 *ptr_cos_ifft;
865 
866   WORD32 ana_fft_offset = pstr_hbe_txposer->k_start * fft_size / 32;
867   WORD32 syn_fft_offset = pstr_hbe_txposer->a_start * fft_size / 64;
868   /* pitch_in_bins is given with the resolution of a 1536 point FFT */
869   WORD32 err_code = IA_NO_ERROR;
870 
871   memcpy(pstr_hbe_txposer->ptr_input_buf,
872          pstr_hbe_txposer->ptr_input_buf + pstr_hbe_txposer->ana_fft_size[0],
873          pstr_hbe_txposer->ana_fft_size[0] * sizeof(pstr_hbe_txposer->ptr_input_buf[0]));
874 
875   err_code = ixheaace_real_synth_filt(pstr_hbe_txposer, num_columns, qmf_buf_real, qmf_buf_imag);
876   if (err_code) {
877     return err_code;
878   }
879 
880   memcpy(ptr_output_buf, ptr_output_buf + 2 * pstr_hbe_txposer->syn_fft_size[0],
881          2 * pstr_hbe_txposer->syn_fft_size[0] * sizeof(ptr_output_buf[0]));
882 
883   memset(ptr_output_buf + 2 * pstr_hbe_txposer->syn_fft_size[0], 0,
884          2 * pstr_hbe_txposer->syn_fft_size[0] * sizeof(ptr_output_buf[0]));
885 
886   err_code = ixheaace_hbe_fft_map(pstr_hbe_txposer);
887   if (err_code) {
888     return err_code;
889   }
890 
891   while (in_offset < num_in_samples) {
892     memset(ptr_spectrum, 0, fft_size * sizeof(ptr_spectrum[0]));
893     memset(ptr_spectrum_tx, 0, ((fft_size + 2) * sizeof(ptr_spectrum_tx[0])));
894 
895     memset(ptr_mag, 0, (fft_size / 2 + 2) * sizeof(ptr_mag[0]));
896     memset(ptr_phase, 0, (fft_size / 2 + 2) * sizeof(ptr_phase[0]));
897     ixheaace_dft_hbe_apply_win(ptr_input_buf + in_offset, pstr_hbe_txposer->ptr_ana_win,
898                                ptr_spectrum + ana_pad_size + ana_fft_offset,
899                                pstr_hbe_txposer->ana_fft_size[0]);
900     ixheaace_dft_hbe_fft_memmove(ptr_spectrum + ana_fft_offset, ana_fft_size);
901     {
902       WORD32 len = ana_fft_size;
903       ptr_cos_fft = pstr_hbe_txposer->ptr_ana_cos_sin_tab;
904       FLOAT32 *ptr_fft_data = ptr_spectrum + ana_fft_offset;
905       FLOAT32 tmp1, tmp2, tmp3, tmp4;
906       (*(pstr_hbe_txposer->ixheaace_hbe_anal_fft))(ptr_fft_data, ptr_dft_hbe_scratch_buf, len / 2,
907                                                    -1);
908       tmp1 = ptr_fft_data[0] + ptr_fft_data[1];
909       ptr_fft_data[1] = ptr_fft_data[0] - ptr_fft_data[1];
910       ptr_fft_data[0] = tmp1;
911 
912       i = 1;
913       while (i <= (len / 4 + (len % 4) / 2)) {
914         tmp1 = ptr_fft_data[2 * i] - ptr_fft_data[len - 2 * i];
915         tmp2 = ptr_fft_data[2 * i + 1] + ptr_fft_data[len - 2 * i + 1];
916 
917         tmp3 = (*(ptr_cos_fft)) * tmp1 - (*(ptr_cos_fft + 1)) * tmp2;
918         tmp4 = (*(ptr_cos_fft + 1)) * tmp1 + (*(ptr_cos_fft)) * tmp2;
919 
920         ptr_cos_fft = ptr_cos_fft + 2;
921 
922         tmp1 = ptr_fft_data[2 * i] + ptr_fft_data[len - 2 * i];
923         tmp2 = ptr_fft_data[2 * i + 1] - ptr_fft_data[len - 2 * i + 1];
924 
925         ptr_fft_data[2 * i + 0] = 0.5f * (tmp1 - tmp3);
926         ptr_fft_data[2 * i + 1] = 0.5f * (tmp2 - tmp4);
927         ptr_fft_data[len - 2 * i + 0] = 0.5f * (tmp1 + tmp3);
928         ptr_fft_data[len - 2 * i + 1] = -0.5f * (tmp2 + tmp4);
929         ++i;
930       }
931     }
932     ixheaace_karth2polar(ptr_spectrum + ana_fft_offset, ptr_mag + ana_fft_offset / 2,
933                          ptr_phase + ana_fft_offset / 2, ana_fft_size);
934 
935     for (T = 2; T <= pstr_hbe_txposer->max_stretch; T++) {
936       /* max_stretch cannot be greater than 4. So, T can be 2 to 4*/
937 
938       WORD32 out_transform_size;
939 
940       /* 0<i<fft_size/2 */
941       out_transform_size = (fft_size / 2);
942       switch (T) {
943         case 2:
944           ia_dft_hbe_apply_polar_t2(T, pstr_hbe_txposer, pitch_in_bins, out_transform_size);
945           break;
946         case 3:
947           ia_dft_hbe_apply_polar_t_3(T, pstr_hbe_txposer, pitch_in_bins, out_transform_size);
948           break;
949         default:
950           ia_dft_hbe_apply_polar_t(T, pstr_hbe_txposer, pitch_in_bins, out_transform_size);
951       }
952     } /* for T */
953 
954     ptr_spectrum_tx[syn_fft_offset + 1] =
955         ptr_spectrum_tx[syn_fft_offset + syn_fft_size]; /* Move Nyquist bin to bin 1 for RFFTN */
956 
957     {
958       WORD32 len = syn_fft_size;
959       ptr_cos_ifft = pstr_hbe_txposer->ptr_syn_cos_sin_tab;
960       FLOAT32 *ptr_fft_data = ptr_spectrum_tx + syn_fft_offset;
961       FLOAT32 tmp1, tmp2, tmp3, tmp4;
962 
963       FLOAT32 scale = 1.0f / len;
964       tmp1 = ptr_fft_data[0] + ptr_fft_data[1];
965       ptr_fft_data[1] = scale * (ptr_fft_data[0] - ptr_fft_data[1]);
966       ptr_fft_data[0] = scale * tmp1;
967 
968       for (i = 1; i <= (len / 4 + (len % 4) / 2); ++i) {
969         tmp1 = ptr_fft_data[2 * i] - ptr_fft_data[len - 2 * i];
970         tmp2 = ptr_fft_data[2 * i + 1] + ptr_fft_data[len - 2 * i + 1];
971 
972         tmp3 = (*(ptr_cos_ifft)) * tmp1 + (*(ptr_cos_ifft + 1)) * tmp2;
973         tmp4 = -(*(ptr_cos_ifft + 1)) * tmp1 + (*(ptr_cos_ifft)) * tmp2;
974 
975         ptr_cos_ifft = ptr_cos_ifft + 2;
976 
977         tmp1 = ptr_fft_data[2 * i] + ptr_fft_data[len - 2 * i];
978         tmp2 = ptr_fft_data[2 * i + 1] - ptr_fft_data[len - 2 * i + 1];
979 
980         ptr_fft_data[2 * i] = scale * (tmp1 - tmp3);
981         ptr_fft_data[2 * i + 1] = scale * (tmp2 - tmp4);
982         ptr_fft_data[len - 2 * i] = scale * (tmp1 + tmp3);
983         ptr_fft_data[len - 2 * i + 1] = -scale * (tmp2 + tmp4);
984       }
985 
986       (*(pstr_hbe_txposer->ixheaace_hbe_synth_ifft))(ptr_fft_data, ptr_dft_hbe_scratch_buf,
987                                                      len / 2, 1);
988     }
989 
990     ixheaace_dft_hbe_fft_memmove(ptr_spectrum_tx + syn_fft_offset, syn_fft_size);
991     ixheaace_dft_hbe_apply_win(
992         ptr_spectrum_tx + syn_pad_size + syn_fft_offset, pstr_hbe_txposer->ptr_syn_win,
993         ptr_spectrum_tx + syn_pad_size + syn_fft_offset, pstr_hbe_txposer->syn_fft_size[0]);
994 
995     for (i = 0; i < pstr_hbe_txposer->syn_fft_size[0]; i++) {
996       ptr_output_buf[out_offset + i] += ptr_spectrum_tx[syn_pad_size + syn_fft_offset + i];
997     }
998 
999     in_offset += in_hop_size;
1000     out_offset += out_hop_size;
1001 
1002   } /* while(in_offset<num_in_samples) */
1003 
1004   ixheaace_dft_hbe_cplx_anal_filt(pstr_hbe_txposer, pv_qmf_buf_real, pv_qmf_buf_imag);
1005 
1006   return err_code;
1007 }
1008