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