/src/libxaac/decoder/ixheaacd_acelp_mdct.c
Line | Count | Source |
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 | | |
65 | | static PLATFORM_INLINE WORD32 ixheaacd_mul_sub64_sat_32(WORD32 a, WORD32 b, |
66 | 52.9M | WORD32 c, WORD32 d) { |
67 | 52.9M | WORD64 diff; |
68 | 52.9M | WORD64 temp_result1; |
69 | 52.9M | WORD64 temp_result2; |
70 | | |
71 | 52.9M | temp_result1 = (WORD64)a * (WORD64)c; |
72 | 52.9M | temp_result2 = (WORD64)b * (WORD64)d; |
73 | | |
74 | 52.9M | diff = (temp_result1 - temp_result2) >> 32; |
75 | | |
76 | 52.9M | if (diff >= 2147483647) |
77 | 0 | diff = 2147483647; |
78 | 52.9M | else if (diff <= -2147483647 - 1) |
79 | 0 | diff = -2147483647 - 1; |
80 | | |
81 | 52.9M | return ((WORD32)diff); |
82 | 52.9M | } |
83 | | |
84 | | static PLATFORM_INLINE WORD32 ixheaacd_mul_add64_sat_32(WORD32 a, WORD32 b, |
85 | 52.9M | WORD32 c, WORD32 d) { |
86 | 52.9M | WORD64 sum; |
87 | 52.9M | WORD64 temp_result1; |
88 | 52.9M | WORD64 temp_result2; |
89 | | |
90 | 52.9M | temp_result1 = (WORD64)a * (WORD64)c; |
91 | 52.9M | temp_result2 = (WORD64)b * (WORD64)d; |
92 | | |
93 | 52.9M | sum = (temp_result1 + temp_result2) >> 32; |
94 | | |
95 | 52.9M | if (sum >= 2147483647) |
96 | 0 | sum = 2147483647; |
97 | 52.9M | else if (sum <= -2147483647 - 1) |
98 | 0 | sum = -2147483647 - 1; |
99 | | |
100 | 52.9M | return ((WORD32)sum); |
101 | 52.9M | } |
102 | | |
103 | | static void ixheaacd_pre_twid(WORD32 *in, WORD32 *r_ptr, WORD32 *i_ptr, |
104 | 296k | WORD32 nlength, const WORD32 *ptr_pre_cos_sin) { |
105 | 296k | WORD32 i; |
106 | | |
107 | 296k | const WORD32 *cos_ptr = &ptr_pre_cos_sin[0]; |
108 | 296k | const WORD32 *sin_ptr = &ptr_pre_cos_sin[nlength]; |
109 | | |
110 | 6.92M | for (i = 0; i < nlength; i += 4) { |
111 | 6.62M | *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i], in[nlength + i], cos_ptr[i], |
112 | 6.62M | sin_ptr[i]); |
113 | 6.62M | *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i], in[nlength + i], sin_ptr[i], |
114 | 6.62M | cos_ptr[i]); |
115 | | |
116 | 6.62M | *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 1], in[nlength + i + 1], |
117 | 6.62M | cos_ptr[i + 1], sin_ptr[i + 1]); |
118 | 6.62M | *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 1], in[nlength + i + 1], |
119 | 6.62M | sin_ptr[i + 1], cos_ptr[i + 1]); |
120 | | |
121 | 6.62M | *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 2], in[nlength + i + 2], |
122 | 6.62M | cos_ptr[i + 2], sin_ptr[i + 2]); |
123 | 6.62M | *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 2], in[nlength + i + 2], |
124 | 6.62M | sin_ptr[i + 2], cos_ptr[i + 2]); |
125 | | |
126 | 6.62M | *r_ptr++ = ixheaacd_mul_sub64_sat_32(in[i + 3], in[nlength + i + 3], |
127 | 6.62M | cos_ptr[i + 3], sin_ptr[i + 3]); |
128 | 6.62M | *i_ptr++ = ixheaacd_mul_add64_sat_32(in[i + 3], in[nlength + i + 3], |
129 | 6.62M | sin_ptr[i + 3], cos_ptr[i + 3]); |
130 | 6.62M | } |
131 | 296k | } |
132 | | |
133 | | static void ixheaacd_post_twid(WORD32 *data_re, WORD32 *data_im, WORD32 *out, |
134 | 296k | WORD32 nlength, const WORD32 *ptr_post_cos_sin) { |
135 | 296k | WORD32 i; |
136 | | |
137 | 296k | const WORD32 *cos_ptr = &ptr_post_cos_sin[nlength * 2]; |
138 | 296k | const WORD32 *sin_ptr = &ptr_post_cos_sin[nlength * 3]; |
139 | | |
140 | 296k | WORD32 *out_ptr = &out[2 * nlength - 1]; |
141 | 6.92M | for (i = 0; i < nlength; i += 4) { |
142 | 6.62M | out[0] = ixheaacd_mul_sub64_sat_32(data_re[i], data_im[i], cos_ptr[i], |
143 | 6.62M | sin_ptr[i]); |
144 | 6.62M | out_ptr[0] = -ixheaacd_mul_add64_sat_32(data_re[i], data_im[i], sin_ptr[i], |
145 | 6.62M | cos_ptr[i]); |
146 | | |
147 | 6.62M | out[2] = ixheaacd_mul_sub64_sat_32(data_re[i + 1], data_im[i + 1], |
148 | 6.62M | cos_ptr[i + 1], sin_ptr[i + 1]); |
149 | 6.62M | out_ptr[-2] = -ixheaacd_mul_add64_sat_32(data_re[i + 1], data_im[i + 1], |
150 | 6.62M | sin_ptr[i + 1], cos_ptr[i + 1]); |
151 | | |
152 | 6.62M | out[4] = ixheaacd_mul_sub64_sat_32(data_re[i + 2], data_im[i + 2], |
153 | 6.62M | cos_ptr[i + 2], sin_ptr[i + 2]); |
154 | 6.62M | out_ptr[-4] = -ixheaacd_mul_add64_sat_32(data_re[i + 2], data_im[i + 2], |
155 | 6.62M | sin_ptr[i + 2], cos_ptr[i + 2]); |
156 | | |
157 | 6.62M | out[6] = ixheaacd_mul_sub64_sat_32(data_re[i + 3], data_im[i + 3], |
158 | 6.62M | cos_ptr[i + 3], sin_ptr[i + 3]); |
159 | 6.62M | out_ptr[-6] = -ixheaacd_mul_add64_sat_32(data_re[i + 3], data_im[i + 3], |
160 | 6.62M | sin_ptr[i + 3], cos_ptr[i + 3]); |
161 | 6.62M | out += 8; |
162 | 6.62M | out_ptr -= 8; |
163 | 6.62M | } |
164 | 296k | } |
165 | | |
166 | | VOID ixheaacd_acelp_mdct(WORD32 *ptr_in, WORD32 *ptr_out, WORD32 *preshift, WORD32 length, |
167 | 296k | WORD32 *ptr_scratch) { |
168 | 296k | WORD32 *ptr_data_r = ptr_scratch; |
169 | 296k | WORD32 *ptr_data_i = ptr_scratch + 512; |
170 | 296k | const WORD32 *ptr_pre_post_twid; |
171 | | |
172 | 296k | switch (length) { |
173 | 218 | case 1024: |
174 | 218 | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_512[0][0]; |
175 | 218 | break; |
176 | 142 | case 768: |
177 | 142 | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_384[0][0]; |
178 | 142 | break; |
179 | 16.4k | case 512: |
180 | 16.4k | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_256[0][0]; |
181 | 16.4k | break; |
182 | 10.8k | case 384: |
183 | 10.8k | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_192[0][0]; |
184 | 10.8k | break; |
185 | 47.0k | case 256: |
186 | 47.0k | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_128[0][0]; |
187 | 47.0k | break; |
188 | 21.8k | case 192: |
189 | 21.8k | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_96[0][0]; |
190 | 21.8k | break; |
191 | 151k | case 128: |
192 | 151k | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_64[0][0]; |
193 | 151k | break; |
194 | 42.3k | case 96: |
195 | 42.3k | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_48[0][0]; |
196 | 42.3k | break; |
197 | 5.96k | case 64: |
198 | 5.96k | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_32[0][0]; |
199 | 5.96k | break; |
200 | 562 | case 48: |
201 | 562 | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_24[0][0]; |
202 | 562 | break; |
203 | 0 | default: |
204 | 0 | ptr_pre_post_twid = &ixheaacd_pre_post_twid_cos_sin_24[0][0]; |
205 | 0 | break; |
206 | 296k | } |
207 | | |
208 | 296k | ixheaacd_pre_twid(ptr_in, ptr_data_r, ptr_data_i, length / 2, |
209 | 296k | ptr_pre_post_twid); |
210 | | |
211 | 296k | ixheaacd_complex_fft(ptr_data_r, ptr_data_i, length / 2, -1, preshift); |
212 | 296k | *preshift += 1; |
213 | | |
214 | 296k | ixheaacd_post_twid(ptr_data_r, ptr_data_i, ptr_out, length / 2, |
215 | 296k | ptr_pre_post_twid); |
216 | 296k | *preshift += 1; |
217 | 296k | return; |
218 | 296k | } |
219 | | |
220 | | VOID ixheaacd_acelp_mdct_main(ia_usac_data_struct *usac_data, WORD32 *in, WORD32 *out, WORD32 l, |
221 | 96.5k | WORD32 m, WORD32 *preshift) { |
222 | 96.5k | WORD32 i; |
223 | 96.5k | WORD32 *ptr_scratch = &usac_data->scratch_buffer[0]; |
224 | 96.5k | WORD32 *output_buffer = &usac_data->x_ac_dec[0]; |
225 | | |
226 | 96.5k | ixheaacd_acelp_mdct(in, output_buffer, preshift, l + m, ptr_scratch); |
227 | | |
228 | 3.36M | for (i = 0; i < m / 2; i++) { |
229 | 3.26M | out[l + m / 2 - 1 - i] = -output_buffer[m / 2 + l / 2 + i]; |
230 | 3.26M | } |
231 | 11.4M | for (i = 0; i < l / 2; i++) { |
232 | 11.3M | out[i] = output_buffer[m + l / 2 + i]; |
233 | 11.3M | out[l - 1 - i] = -output_buffer[m + l / 2 + i]; |
234 | 11.3M | } |
235 | 3.36M | for (i = 0; i < m / 2; i++) { |
236 | 3.26M | out[l + m / 2 + i] = -output_buffer[m / 2 + l / 2 - 1 - i]; |
237 | 3.26M | } |
238 | 11.4M | for (i = 0; i < l / 2; i++) { |
239 | 11.3M | out[l + m + i] = -output_buffer[l / 2 - 1 - i]; |
240 | 11.3M | out[2 * l + m - 1 - i] = -output_buffer[l / 2 - 1 - i]; |
241 | 11.3M | } |
242 | 96.5k | return; |
243 | 96.5k | } |