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 <string.h>
22
23 #include "ixheaac_type_def.h"
24 #include "ixheaac_error_standards.h"
25 #include "ixheaace_error_codes.h"
26 #include "ixheaace_common_rom.h"
27 #include "ixheaace_sbr_def.h"
28 #include "ixheaace_resampler.h"
29 #include "ixheaace_sbr_rom.h"
30 #include "ixheaace_sbr_hybrid.h"
31
32 #include "ixheaace_aac_constants.h"
33
34 VOID ia_enhaacplus_enc_fft(complex *out, WORD32 N, ixheaace_common_tables *);
35
ixheaace_four_chan_filtering(const FLOAT32 * ptr_qmf_real,const FLOAT32 * ptr_qmf_imag,FLOAT32 ** ptr_hyb_real,FLOAT32 ** ptr_hyb_imag,WORD32 ch_offset,const FLOAT32 * ptr_p4_13,ixheaace_common_tables * pstr_common_tab)36 static VOID ixheaace_four_chan_filtering(const FLOAT32 *ptr_qmf_real, const FLOAT32 *ptr_qmf_imag,
37 FLOAT32 **ptr_hyb_real, FLOAT32 **ptr_hyb_imag,
38 WORD32 ch_offset, const FLOAT32 *ptr_p4_13,
39 ixheaace_common_tables *pstr_common_tab) {
40 WORD32 i, k, n;
41 WORD32 mid_tap = IXHEAACE_HYBRID_FILTER_DELAY;
42
43 FLOAT32 cum[8], *ptr_cum;
44 FLOAT32 tmp1, tmp2, tmp_p4;
45 FLOAT32 real, imag;
46 const FLOAT32 *ptr_re, *ptr_im;
47 FLOAT32 *ptr_hy_im, *ptr_hy_re;
48 ptr_re = &ptr_qmf_real[0];
49 ptr_im = &ptr_qmf_imag[0];
50 ptr_hy_re = &ptr_hyb_real[0][ch_offset];
51 ptr_hy_im = &ptr_hyb_imag[0][ch_offset];
52
53 for (i = IXHEAACE_QMF_TIME_SLOTS - 1; i >= 0; i--) {
54 real = imag = 0;
55 for (k = 0; k < 16; k += 4) {
56 tmp_p4 = ptr_p4_13[k];
57 tmp1 = ptr_re[k];
58 tmp2 = ptr_im[k];
59
60 tmp1 = tmp_p4 * tmp1;
61 real = real - tmp1;
62
63 tmp1 = tmp_p4 * tmp2;
64 imag = imag + tmp1;
65 }
66
67 cum[3] = imag;
68 cum[2] = real;
69 real = imag = 0;
70
71 for (k = 3; k < 15; k += 4) {
72 tmp_p4 = ptr_p4_13[k];
73 tmp1 = ptr_re[k];
74 tmp2 = ptr_im[k];
75 tmp1 = tmp_p4 * tmp1;
76 real = real + tmp1;
77 tmp1 = tmp_p4 * tmp2;
78 imag = imag + tmp1;
79 }
80
81 tmp1 = imag + real;
82 cum[7] = tmp1 * IXHEAACE_COS_PI_BY_4;
83 tmp1 = imag - real;
84 cum[6] = tmp1 * IXHEAACE_COS_PI_BY_4;
85
86 cum[1] = ptr_p4_13[mid_tap] * ptr_re[mid_tap];
87 cum[0] = ptr_p4_13[mid_tap] * ptr_im[mid_tap];
88
89 real = imag = 0;
90
91 for (k = 1; k < 13; k += 4) {
92 tmp_p4 = ptr_p4_13[k];
93 tmp1 = ptr_re[k];
94 tmp2 = ptr_im[k];
95 tmp1 = tmp_p4 * tmp1;
96 real = real + tmp1;
97 tmp1 = tmp_p4 * tmp2;
98 imag = imag + tmp1;
99 }
100
101 tmp1 = real - imag;
102 cum[5] = tmp1 * IXHEAACE_COS_PI_BY_4;
103 tmp1 = real + imag;
104 cum[4] = tmp1 * IXHEAACE_COS_PI_BY_4;
105
106 ia_enhaacplus_enc_fft((complex *)cum, 4, pstr_common_tab);
107
108 ptr_cum = &cum[0];
109
110 for (n = 3; n >= 0; n--) {
111 tmp1 = *ptr_cum++;
112 tmp2 = *ptr_cum++;
113 *ptr_hy_im++ = tmp1;
114 *ptr_hy_re++ = tmp2;
115 }
116 ptr_re++;
117 ptr_im++;
118 ptr_hy_re += IXHEAACE_QMF_TIME_SLOTS - 4;
119 ptr_hy_im += IXHEAACE_QMF_TIME_SLOTS - 4;
120 }
121 }
122
ixheaace_eight_chan_filtering(const FLOAT32 * ptr_qmf_real,const FLOAT32 * ptr_qmf_imag,FLOAT32 ** ptr_hyb_real,FLOAT32 ** ptr_hyb_imag,const FLOAT32 * ptr_p8_13,ixheaace_common_tables * pstr_common_tab)123 static VOID ixheaace_eight_chan_filtering(const FLOAT32 *ptr_qmf_real,
124 const FLOAT32 *ptr_qmf_imag, FLOAT32 **ptr_hyb_real,
125 FLOAT32 **ptr_hyb_imag, const FLOAT32 *ptr_p8_13,
126 ixheaace_common_tables *pstr_common_tab)
127
128 {
129 LOOPINDEX i, n;
130 LOOPINDEX mid_tap = IXHEAACE_HYBRID_FILTER_DELAY;
131 FLOAT32 real, imag;
132 FLOAT32 cum[16], *ptr_cum;
133 FLOAT32 tmp1, tmp2, tmp3;
134 const FLOAT32 *ptr_re, *ptr_im;
135 FLOAT32 *ptr_hy_re, *ptr_hy_im;
136 ptr_re = &ptr_qmf_real[0];
137 ptr_im = &ptr_qmf_imag[0];
138 ptr_hy_re = &ptr_hyb_real[0][0];
139 ptr_hy_im = &ptr_hyb_imag[0][0];
140
141 for (i = IXHEAACE_QMF_TIME_SLOTS - 1; i >= 0; i--) {
142 tmp1 = ptr_p8_13[4] * ptr_re[4];
143 tmp2 = ptr_p8_13[12] * ptr_re[12];
144
145 tmp3 = ptr_im[4];
146 real = tmp1 + tmp2;
147 tmp2 = ptr_im[12];
148 tmp1 = ptr_p8_13[4] * tmp3;
149 tmp2 = ptr_p8_13[12] * tmp2;
150 imag = tmp1 + tmp2;
151
152 tmp1 = imag - real;
153 cum[5] = tmp1 * IXHEAACE_COS_PI_BY_4;
154
155 tmp1 = imag + real;
156 tmp3 = ptr_re[3];
157 cum[4] = -tmp1 * IXHEAACE_COS_PI_BY_4;
158 tmp2 = ptr_re[11];
159 tmp1 = ptr_p8_13[3] * tmp3;
160 tmp2 = ptr_p8_13[11] * tmp2;
161 tmp3 = ptr_im[3];
162 real = tmp1 + tmp2;
163 tmp2 = ptr_im[11];
164 tmp1 = ptr_p8_13[3] * tmp3;
165 tmp2 = ptr_p8_13[11] * tmp2;
166 imag = tmp1 + tmp2;
167
168 tmp1 = imag * IXHEAACE_COS_PI_BY_8;
169 tmp2 = real * IXHEAACE_SIN_PI_BY_8;
170 cum[13] = tmp1 - tmp2;
171
172 tmp1 = imag * IXHEAACE_SIN_PI_BY_8;
173 tmp2 = real * IXHEAACE_COS_PI_BY_8;
174 tmp3 = ptr_re[2];
175 cum[12] = -tmp1 - tmp2;
176 tmp2 = ptr_re[10];
177 tmp1 = ptr_p8_13[2] * tmp3;
178 tmp2 = ptr_p8_13[10] * tmp2;
179 tmp3 = ptr_im[2];
180 cum[2] = -tmp1 - tmp2;
181 tmp2 = ptr_im[10];
182 tmp1 = ptr_p8_13[2] * tmp3;
183 tmp2 = ptr_p8_13[10] * tmp2;
184 cum[3] = tmp1 + tmp2;
185
186 tmp1 = ptr_p8_13[1] * ptr_re[1];
187 tmp2 = ptr_p8_13[9] * ptr_re[9];
188 real = tmp1 + tmp2;
189
190 tmp1 = ptr_p8_13[1] * ptr_im[1];
191 tmp2 = ptr_p8_13[9] * ptr_im[9];
192 imag = tmp1 + tmp2;
193
194 tmp1 = imag * IXHEAACE_COS_PI_BY_8;
195 tmp2 = real * IXHEAACE_SIN_PI_BY_8;
196 cum[11] = tmp1 + tmp2;
197
198 tmp1 = imag * IXHEAACE_SIN_PI_BY_8;
199 tmp2 = real * IXHEAACE_COS_PI_BY_8;
200 cum[10] = tmp1 - tmp2;
201
202 tmp1 = ptr_p8_13[0] * ptr_re[0];
203 tmp2 = ptr_p8_13[8] * ptr_re[8];
204 real = tmp1 + tmp2;
205
206 tmp1 = ptr_p8_13[0] * ptr_im[0];
207 tmp2 = ptr_p8_13[8] * ptr_im[8];
208 imag = tmp1 + tmp2;
209
210 tmp1 = imag + real;
211 cum[7] = tmp1 * IXHEAACE_COS_PI_BY_4;
212
213 tmp1 = imag - real;
214 cum[6] = tmp1 * IXHEAACE_COS_PI_BY_4;
215
216 real = ptr_p8_13[7] * ptr_re[7];
217 imag = ptr_p8_13[7] * ptr_im[7];
218
219 tmp1 = imag * IXHEAACE_SIN_PI_BY_8;
220 tmp2 = real * IXHEAACE_COS_PI_BY_8;
221 cum[15] = tmp1 + tmp2;
222
223 tmp1 = imag * IXHEAACE_COS_PI_BY_8;
224 tmp2 = real * IXHEAACE_SIN_PI_BY_8;
225 cum[14] = tmp1 - tmp2;
226
227 cum[1] = ptr_p8_13[mid_tap] * ptr_re[mid_tap];
228 cum[0] = ptr_p8_13[mid_tap] * ptr_im[mid_tap];
229
230 real = ptr_p8_13[5] * ptr_re[5];
231 imag = ptr_p8_13[5] * ptr_im[5];
232
233 tmp1 = real * IXHEAACE_COS_PI_BY_8;
234 tmp2 = imag * IXHEAACE_SIN_PI_BY_8;
235 cum[9] = tmp1 - tmp2;
236
237 tmp1 = real * IXHEAACE_SIN_PI_BY_8;
238 tmp2 = imag * IXHEAACE_COS_PI_BY_8;
239 cum[8] = tmp1 + tmp2;
240
241 ia_enhaacplus_enc_fft((complex *)cum, 8, pstr_common_tab);
242
243 ptr_cum = &cum[0];
244
245 for (n = 7; n >= 0; n--) {
246 tmp1 = *ptr_cum++;
247 tmp2 = *ptr_cum++;
248 *ptr_hy_im++ = tmp1;
249 *ptr_hy_re++ = tmp2;
250 }
251 ptr_re++;
252 ptr_im++;
253 ptr_hy_re += IXHEAACE_QMF_TIME_SLOTS - 8;
254 ptr_hy_im += IXHEAACE_QMF_TIME_SLOTS - 8;
255 }
256 }
257
ixheaace_hybrid_analysis(const FLOAT32 ** ptr_qmf_real_in,const FLOAT32 ** ptr_qmf_imag_in,FLOAT32 ** ptr_hyb_real_in,FLOAT32 ** ptr_hyb_imag_in,ixheaace_pstr_hybrid pstr_hybrid,ixheaace_str_ps_tab * pstr_ps_tab,ixheaace_common_tables * pstr_common_tab)258 IA_ERRORCODE ixheaace_hybrid_analysis(const FLOAT32 **ptr_qmf_real_in,
259 const FLOAT32 **ptr_qmf_imag_in, FLOAT32 **ptr_hyb_real_in,
260 FLOAT32 **ptr_hyb_imag_in, ixheaace_pstr_hybrid pstr_hybrid,
261 ixheaace_str_ps_tab *pstr_ps_tab,
262 ixheaace_common_tables *pstr_common_tab) {
263 WORD32 band, i;
264 ixheaace_hybrid_res hybrid_res;
265 WORD32 ch_offset = 0;
266
267 FLOAT32 *ptr_re, *ptr_im;
268 const FLOAT32 *ptr_qmf_real, *ptr_qmf_imag;
269 FLOAT32 tmp1, tmp2;
270
271 for (band = 0; band < IXHEAACE_NUM_QMF_BANDS_IN_HYBRID; band++) {
272 hybrid_res = (ixheaace_hybrid_res)pstr_ps_tab->a_hyb_res[band];
273
274 memcpy(pstr_hybrid->ptr_work_real, pstr_hybrid->ptr_qmf_buf_real[band],
275 IXHEAACE_QMF_BUFFER_MOVE * sizeof(FLOAT32));
276 memcpy(pstr_hybrid->ptr_work_imag, pstr_hybrid->ptr_qmf_buf_imag[band],
277 IXHEAACE_QMF_BUFFER_MOVE * sizeof(FLOAT32));
278 ptr_re = &pstr_hybrid->ptr_work_real[IXHEAACE_QMF_BUFFER_MOVE];
279 ptr_im = &pstr_hybrid->ptr_work_imag[IXHEAACE_QMF_BUFFER_MOVE];
280 ptr_qmf_real = &ptr_qmf_real_in[0][band];
281 ptr_qmf_imag = &ptr_qmf_imag_in[0][band];
282
283 for (i = IXHEAACE_QMF_TIME_SLOTS - 1; i >= 0; i--) {
284 tmp1 = *ptr_qmf_real;
285 tmp2 = *ptr_qmf_imag;
286
287 ptr_qmf_real += IXHEAACE_QMF_CHANNELS;
288 ptr_qmf_imag += IXHEAACE_QMF_CHANNELS;
289
290 *ptr_im++ = tmp2;
291 *ptr_re++ = tmp1;
292 }
293
294 ptr_re = &pstr_hybrid->ptr_qmf_buf_real[band][0];
295 ptr_im = &pstr_hybrid->ptr_qmf_buf_imag[band][0];
296
297 ptr_qmf_real = &ptr_qmf_real_in[IXHEAACE_QMF_TIME_SLOTS - IXHEAACE_QMF_BUFFER_MOVE][band];
298 ptr_qmf_imag = &ptr_qmf_imag_in[IXHEAACE_QMF_TIME_SLOTS - IXHEAACE_QMF_BUFFER_MOVE][band];
299
300 for (i = 0; i < IXHEAACE_QMF_BUFFER_MOVE; i++) {
301 tmp1 = *ptr_qmf_real;
302 ptr_qmf_real += IXHEAACE_QMF_CHANNELS;
303 tmp2 = *ptr_qmf_imag;
304 ptr_qmf_imag += IXHEAACE_QMF_CHANNELS;
305 *ptr_re++ = tmp1;
306 *ptr_im++ = tmp2;
307 }
308
309 switch (hybrid_res) {
310 case IXHEAACE_HYBRID_4_CPLX:
311 ixheaace_four_chan_filtering(pstr_hybrid->ptr_work_real, pstr_hybrid->ptr_work_imag,
312 ptr_hyb_real_in, ptr_hyb_imag_in, ch_offset,
313 pstr_ps_tab->p4_13, pstr_common_tab);
314 break;
315 case IXHEAACE_HYBRID_8_CPLX:
316 ixheaace_eight_chan_filtering(pstr_hybrid->ptr_work_real, pstr_hybrid->ptr_work_imag,
317 ptr_hyb_real_in, ptr_hyb_imag_in, pstr_ps_tab->p8_13,
318 pstr_common_tab);
319 break;
320 default:
321 return IA_EXHEAACE_EXE_FATAL_PS_INVALID_HYBRID_RES_VAL;
322 break;
323 }
324 ch_offset += hybrid_res;
325 }
326 return IA_NO_ERROR;
327 }
328
ixheaace_hybrid_synthesis(const FLOAT32 ** ptr_hybrid_real_flt,const FLOAT32 ** ptr_hybrid_imag_flt,FLOAT32 ** ptr_qmf_real_flt,FLOAT32 ** ptr_qmf_imag_flt,const WORD32 * ptr_hyb_res)329 VOID ixheaace_hybrid_synthesis(const FLOAT32 **ptr_hybrid_real_flt,
330 const FLOAT32 **ptr_hybrid_imag_flt, FLOAT32 **ptr_qmf_real_flt,
331 FLOAT32 **ptr_qmf_imag_flt, const WORD32 *ptr_hyb_res) {
332 WORD32 k, n, band;
333 ixheaace_hybrid_res hybrid_res;
334 WORD32 ch_offset = 0;
335
336 FLOAT32 temp1, temp2;
337 FLOAT32 *ptr_qmf_real;
338 FLOAT32 *ptr_qmf_imag;
339
340 for (band = 0; band < IXHEAACE_NUM_QMF_BANDS_IN_HYBRID; band++) {
341 const FLOAT32 *ptr_hybrid_real = &ptr_hybrid_real_flt[0][ch_offset];
342 const FLOAT32 *ptr_hybrid_imag = &ptr_hybrid_imag_flt[0][ch_offset];
343
344 hybrid_res = (ixheaace_hybrid_res)ptr_hyb_res[band];
345
346 ptr_qmf_real = &ptr_qmf_real_flt[0][band];
347 ptr_qmf_imag = &ptr_qmf_imag_flt[0][band];
348
349 for (n = 0; n < IXHEAACE_QMF_TIME_SLOTS; n++) {
350 FLOAT32 temo_real = 0, temo_imag = 0;
351
352 for (k = hybrid_res - 1; k >= 0; k--) {
353 temp1 = *ptr_hybrid_real++;
354 temp2 = *ptr_hybrid_imag++;
355 temo_real += temp1;
356 temo_imag += temp2;
357 }
358
359 ptr_hybrid_real += IXHEAACE_QMF_TIME_SLOTS - hybrid_res;
360 ptr_hybrid_imag += IXHEAACE_QMF_TIME_SLOTS - hybrid_res;
361
362 *ptr_qmf_real = temo_real;
363 ptr_qmf_real += IXHEAACE_QMF_CHANNELS;
364
365 *ptr_qmf_imag = temo_imag;
366 ptr_qmf_imag += IXHEAACE_QMF_CHANNELS;
367 }
368 ch_offset += hybrid_res;
369 }
370 }
371