xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_hybrid.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 <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