xref: /aosp_15_r20/external/libxaac/decoder/ixheaacd_acelp_mdct.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1 /******************************************************************************
2  *                                                                            *
3  * Copyright (C) 2018 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 #include <stdlib.h>
21 #include <math.h>
22 
23 #include "ixheaac_type_def.h"
24 
25 #include "ixheaacd_bitbuffer.h"
26 #include "ixheaacd_interface.h"
27 
28 #include "ixheaacd_tns_usac.h"
29 #include "ixheaacd_cnst.h"
30 
31 #include "ixheaacd_acelp_info.h"
32 
33 #include "ixheaacd_td_mdct.h"
34 
35 #include "ixheaacd_sbrdecsettings.h"
36 #include "ixheaacd_info.h"
37 #include "ixheaacd_sbr_common.h"
38 #include "ixheaacd_drc_data_struct.h"
39 #include "ixheaacd_drc_dec.h"
40 #include "ixheaacd_sbrdecoder.h"
41 #include "ixheaacd_mps_polyphase.h"
42 #include "ixheaac_sbr_const.h"
43 
44 #include "ixheaacd_ec_defines.h"
45 #include "ixheaacd_ec_struct_def.h"
46 #include "ixheaacd_main.h"
47 #include "ixheaacd_arith_dec.h"
48 
49 #include "ixheaacd_func_def.h"
50 #include "ixheaac_constants.h"
51 #include "ixheaac_basic_ops32.h"
52 #include "ixheaac_basic_ops40.h"
53 
54 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_512[4][512];
55 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_384[4][384];
56 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_256[4][256];
57 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_192[4][192];
58 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_128[4][128];
59 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_96[4][96];
60 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_64[4][64];
61 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_48[4][48];
62 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_32[4][32];
63 extern const WORD32 ixheaacd_pre_post_twid_cos_sin_24[4][24];
64 
ixheaacd_mul_sub64_sat_32(WORD32 a,WORD32 b,WORD32 c,WORD32 d)65 static PLATFORM_INLINE WORD32 ixheaacd_mul_sub64_sat_32(WORD32 a, WORD32 b,
66                                                         WORD32 c, WORD32 d) {
67   WORD64 diff;
68   WORD64 temp_result1;
69   WORD64 temp_result2;
70 
71   temp_result1 = (WORD64)a * (WORD64)c;
72   temp_result2 = (WORD64)b * (WORD64)d;
73 
74   diff = (temp_result1 - temp_result2) >> 32;
75 
76   if (diff >= 2147483647)
77     diff = 2147483647;
78   else if (diff <= -2147483647 - 1)
79     diff = -2147483647 - 1;
80 
81   return ((WORD32)diff);
82 }
83 
ixheaacd_mul_add64_sat_32(WORD32 a,WORD32 b,WORD32 c,WORD32 d)84 static PLATFORM_INLINE WORD32 ixheaacd_mul_add64_sat_32(WORD32 a, WORD32 b,
85                                                         WORD32 c, WORD32 d) {
86   WORD64 sum;
87   WORD64 temp_result1;
88   WORD64 temp_result2;
89 
90   temp_result1 = (WORD64)a * (WORD64)c;
91   temp_result2 = (WORD64)b * (WORD64)d;
92 
93   sum = (temp_result1 + temp_result2) >> 32;
94 
95   if (sum >= 2147483647)
96     sum = 2147483647;
97   else if (sum <= -2147483647 - 1)
98     sum = -2147483647 - 1;
99 
100   return ((WORD32)sum);
101 }
102 
ixheaacd_pre_twid(WORD32 * in,WORD32 * r_ptr,WORD32 * i_ptr,WORD32 nlength,const WORD32 * ptr_pre_cos_sin)103 static void ixheaacd_pre_twid(WORD32 *in, WORD32 *r_ptr, WORD32 *i_ptr,
104                               WORD32 nlength, const WORD32 *ptr_pre_cos_sin) {
105   WORD32 i;
106 
107   const WORD32 *cos_ptr = &ptr_pre_cos_sin[0];
108   const WORD32 *sin_ptr = &ptr_pre_cos_sin[nlength];
109 
110   for (i = 0; i < nlength; i += 4) {
111     *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i], in[nlength + i], cos_ptr[i],
112                                          sin_ptr[i]);
113     *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i], in[nlength + i], sin_ptr[i],
114                                          cos_ptr[i]);
115 
116     *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 1], in[nlength + i + 1],
117                                          cos_ptr[i + 1], sin_ptr[i + 1]);
118     *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 1], in[nlength + i + 1],
119                                          sin_ptr[i + 1], cos_ptr[i + 1]);
120 
121     *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 2], in[nlength + i + 2],
122                                          cos_ptr[i + 2], sin_ptr[i + 2]);
123     *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 2], in[nlength + i + 2],
124                                          sin_ptr[i + 2], cos_ptr[i + 2]);
125 
126     *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 3], in[nlength + i + 3],
127                                          cos_ptr[i + 3], sin_ptr[i + 3]);
128     *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 3], in[nlength + i + 3],
129                                          sin_ptr[i + 3], cos_ptr[i + 3]);
130   }
131 }
132 
ixheaacd_post_twid(WORD32 * data_re,WORD32 * data_im,WORD32 * out,WORD32 nlength,const WORD32 * ptr_post_cos_sin)133 static void ixheaacd_post_twid(WORD32 *data_re, WORD32 *data_im, WORD32 *out,
134                                WORD32 nlength, const WORD32 *ptr_post_cos_sin) {
135   WORD32 i;
136 
137   const WORD32 *cos_ptr = &ptr_post_cos_sin[nlength * 2];
138   const WORD32 *sin_ptr = &ptr_post_cos_sin[nlength * 3];
139 
140   WORD32 *out_ptr = &out[2 * nlength - 1];
141   for (i = 0; i < nlength; i += 4) {
142     out[0] = ixheaacd_mul_sub64_sat_32(data_re[i], data_im[i], cos_ptr[i],
143                                        sin_ptr[i]);
144     out_ptr[0] = -ixheaacd_mul_add64_sat_32(data_re[i], data_im[i], sin_ptr[i],
145                                             cos_ptr[i]);
146 
147     out[2] = ixheaacd_mul_sub64_sat_32(data_re[i + 1], data_im[i + 1],
148                                        cos_ptr[i + 1], sin_ptr[i + 1]);
149     out_ptr[-2] = -ixheaacd_mul_add64_sat_32(data_re[i + 1], data_im[i + 1],
150                                              sin_ptr[i + 1], cos_ptr[i + 1]);
151 
152     out[4] = ixheaacd_mul_sub64_sat_32(data_re[i + 2], data_im[i + 2],
153                                        cos_ptr[i + 2], sin_ptr[i + 2]);
154     out_ptr[-4] = -ixheaacd_mul_add64_sat_32(data_re[i + 2], data_im[i + 2],
155                                              sin_ptr[i + 2], cos_ptr[i + 2]);
156 
157     out[6] = ixheaacd_mul_sub64_sat_32(data_re[i + 3], data_im[i + 3],
158                                        cos_ptr[i + 3], sin_ptr[i + 3]);
159     out_ptr[-6] = -ixheaacd_mul_add64_sat_32(data_re[i + 3], data_im[i + 3],
160                                              sin_ptr[i + 3], cos_ptr[i + 3]);
161     out += 8;
162     out_ptr -= 8;
163   }
164 }
165 
ixheaacd_acelp_mdct(WORD32 * ptr_in,WORD32 * ptr_out,WORD32 * preshift,WORD32 length,WORD32 * ptr_scratch)166 VOID ixheaacd_acelp_mdct(WORD32 *ptr_in, WORD32 *ptr_out, WORD32 *preshift, WORD32 length,
167                          WORD32 *ptr_scratch) {
168   WORD32 *ptr_data_r = ptr_scratch;
169   WORD32 *ptr_data_i = ptr_scratch + 512;
170   const WORD32 *ptr_pre_post_twid;
171 
172   switch (length) {
173     case 1024:
174       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_512[0][0];
175       break;
176     case 768:
177       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_384[0][0];
178       break;
179     case 512:
180       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_256[0][0];
181       break;
182     case 384:
183       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_192[0][0];
184       break;
185     case 256:
186       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_128[0][0];
187       break;
188     case 192:
189       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_96[0][0];
190       break;
191     case 128:
192       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_64[0][0];
193       break;
194     case 96:
195       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_48[0][0];
196       break;
197     case 64:
198       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_32[0][0];
199       break;
200     case 48:
201       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_24[0][0];
202       break;
203     default:
204       ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_24[0][0];
205       break;
206   }
207 
208   ixheaacd_pre_twid(ptr_in, ptr_data_r, ptr_data_i, length / 2,
209                     ptr_pre_post_twid);
210 
211   ixheaacd_complex_fft(ptr_data_r, ptr_data_i, length / 2, -1, preshift);
212   *preshift += 1;
213 
214   ixheaacd_post_twid(ptr_data_r, ptr_data_i, ptr_out, length / 2,
215                      ptr_pre_post_twid);
216   *preshift += 1;
217   return;
218 }
219 
ixheaacd_acelp_mdct_main(ia_usac_data_struct * usac_data,WORD32 * in,WORD32 * out,WORD32 l,WORD32 m,WORD32 * preshift)220 VOID ixheaacd_acelp_mdct_main(ia_usac_data_struct *usac_data, WORD32 *in, WORD32 *out, WORD32 l,
221                               WORD32 m, WORD32 *preshift) {
222   WORD32 i;
223   WORD32 *ptr_scratch = &usac_data->scratch_buffer[0];
224   WORD32 *output_buffer = &usac_data->x_ac_dec[0];
225 
226   ixheaacd_acelp_mdct(in, output_buffer, preshift, l + m, ptr_scratch);
227 
228   for (i = 0; i < m / 2; i++) {
229     out[l + m / 2 - 1 - i] = -output_buffer[m / 2 + l / 2 + i];
230   }
231   for (i = 0; i < l / 2; i++) {
232     out[i] = output_buffer[m + l / 2 + i];
233     out[l - 1 - i] = -output_buffer[m + l / 2 + i];
234   }
235   for (i = 0; i < m / 2; i++) {
236     out[l + m / 2 + i] = -output_buffer[m / 2 + l / 2 - 1 - i];
237   }
238   for (i = 0; i < l / 2; i++) {
239     out[l + m + i] = -output_buffer[l / 2 - 1 - i];
240     out[2 * l + m - 1 - i] = -output_buffer[l / 2 - 1 - i];
241   }
242   return;
243 }
244