/src/libxaac/decoder/ixheaacd_aac_tns.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 "ixheaacd_sbr_common.h" |
21 | | #include "ixheaac_type_def.h" |
22 | | |
23 | | #include "ixheaac_constants.h" |
24 | | #include "ixheaac_basic_ops32.h" |
25 | | #include "ixheaac_basic_ops16.h" |
26 | | #include "ixheaac_basic_ops40.h" |
27 | | #include "ixheaac_basic_ops.h" |
28 | | |
29 | | #include "ixheaacd_defines.h" |
30 | | #include "ixheaacd_bitbuffer.h" |
31 | | |
32 | | #include "ixheaacd_error_codes.h" |
33 | | #include "ixheaacd_aac_rom.h" |
34 | | #include "ixheaacd_pulsedata.h" |
35 | | |
36 | | #include "ixheaacd_pns.h" |
37 | | #include "ixheaacd_drc_data_struct.h" |
38 | | |
39 | | #include "ixheaacd_lt_predict.h" |
40 | | |
41 | | #include "ixheaacd_cnst.h" |
42 | | #include "ixheaacd_ec_defines.h" |
43 | | #include "ixheaacd_ec_struct_def.h" |
44 | | #include "ixheaacd_channelinfo.h" |
45 | | #include "ixheaacd_drc_dec.h" |
46 | | #include "ixheaacd_sbrdecoder.h" |
47 | | #include "ixheaacd_tns.h" |
48 | | #include "ixheaacd_intrinsics.h" |
49 | | |
50 | | #include "ixheaacd_common_rom.h" |
51 | | #include "ixheaacd_block.h" |
52 | | #include "ixheaacd_channel.h" |
53 | | #include "ixheaacd_audioobjtypes.h" |
54 | | #include "ixheaacd_latmdemux.h" |
55 | | |
56 | | #include "ixheaacd_aacdec.h" |
57 | | |
58 | | static PLATFORM_INLINE WORD32 ixheaacd_mac32_tns_sat(WORD32 a, WORD32 b, |
59 | 31.6M | WORD32 c) { |
60 | 31.6M | WORD32 result; |
61 | 31.6M | WORD64 temp_result; |
62 | | |
63 | 31.6M | temp_result = (WORD64)a * (WORD64)b; |
64 | 31.6M | result = (WORD32)(temp_result >> 32); |
65 | 31.6M | result = ixheaac_add32_sat(c, result); |
66 | 31.6M | return (result); |
67 | 31.6M | } |
68 | | |
69 | | VOID ixheaacd_tns_decode_coefficients( |
70 | | const ia_filter_info_struct *filter, WORD32 *a, |
71 | 34.0k | ia_aac_dec_tables_struct *ptr_aac_tables) { |
72 | 34.0k | WORD32 i; |
73 | 34.0k | WORD32 tmp; |
74 | 34.0k | WORD32 *aptr = a; |
75 | 34.0k | WORD32 *tns_coeff_ptr; |
76 | 34.0k | WORD8 ixheaacd_drc_offset; |
77 | | |
78 | 34.0k | tmp = filter->resolution; |
79 | 34.0k | if (tmp == 0) { |
80 | 30.8k | tns_coeff_ptr = ptr_aac_tables->pstr_block_tables->tns_coeff3; |
81 | 30.8k | ixheaacd_drc_offset = 4; |
82 | | |
83 | 30.8k | } else { |
84 | 3.24k | tns_coeff_ptr = ptr_aac_tables->pstr_block_tables->tns_coeff4; |
85 | 3.24k | ixheaacd_drc_offset = 8; |
86 | 3.24k | } |
87 | | |
88 | 360k | for (i = 0; i < filter->order; i++) { |
89 | 326k | *aptr++ = tns_coeff_ptr[filter->coef[i] + ixheaacd_drc_offset]; |
90 | 326k | } |
91 | 34.0k | } |
92 | | |
93 | | VOID ixheaacd_tns_parcor_to_lpc(WORD32 *parcor, WORD32 *lpc, WORD16 *scale, |
94 | | WORD32 order) |
95 | | |
96 | 28.5k | { |
97 | 28.5k | WORD i, j, status; |
98 | 28.5k | WORD32 z1; |
99 | 28.5k | WORD32 z[MAX_ORDER + 1]; |
100 | 28.5k | WORD32 w[MAX_ORDER + 1]; |
101 | 28.5k | WORD32 accu1, accu2; |
102 | | |
103 | 28.5k | status = 1; |
104 | 28.5k | *scale = 1; |
105 | | |
106 | 88.4k | while (status) { |
107 | 59.8k | status = 0; |
108 | | |
109 | 1.97M | for (i = MAX_ORDER; i >= 0; i--) { |
110 | 1.91M | z[i] = 0; |
111 | 1.91M | w[i] = 0; |
112 | 1.91M | } |
113 | | |
114 | 59.8k | accu1 = (0x40000000 >> (*scale - 1)); |
115 | | |
116 | 781k | for (i = 0; i <= order; i++) { |
117 | 721k | z1 = accu1; |
118 | | |
119 | 8.93M | for (j = 0; j < order; j++) { |
120 | 8.21M | w[j] = (accu1); |
121 | | |
122 | 8.21M | accu1 = ixheaac_add32_sat(accu1, |
123 | 8.21M | ixheaac_mult32_shl_sat(parcor[j], (z[j]))); |
124 | 8.21M | if (ixheaac_abs32_sat(accu1) == 0x7fffffff) status = 1; |
125 | 8.21M | } |
126 | 8.93M | for (j = (order - 1); j >= 0; j--) { |
127 | 8.21M | accu2 = (z[j]); |
128 | 8.21M | accu2 = ixheaac_add32_sat(accu2, |
129 | 8.21M | ixheaac_mult32_shl_sat(parcor[j], (w[j]))); |
130 | 8.21M | z[j + 1] = (accu2); |
131 | 8.21M | if (ixheaac_abs32_sat(accu2) == 0x7fffffff) status = 1; |
132 | 8.21M | } |
133 | | |
134 | 721k | z[0] = (z1); |
135 | 721k | lpc[i] = (accu1); |
136 | 721k | accu1 = 0; |
137 | 721k | } |
138 | | |
139 | 59.8k | accu1 = (status - 1); |
140 | | |
141 | 59.8k | if (accu1 == 0) { |
142 | 31.2k | *scale = *scale + 1; |
143 | 31.2k | } |
144 | 59.8k | } |
145 | 28.5k | } |
146 | | |
147 | | VOID ixheaacd_tns_parcor_lpc_convert_dec(WORD16 *parcor, WORD16 *lpc, |
148 | | WORD16 *scale, WORD order) |
149 | | |
150 | 38.8k | { |
151 | 38.8k | WORD i, j, status; |
152 | 38.8k | WORD32 accu; |
153 | 38.8k | WORD16 temp_buf1[MAX_ORDER + 1]; |
154 | 38.8k | WORD16 temp_buf2[MAX_ORDER + 1]; |
155 | 38.8k | WORD32 accu1, accu2; |
156 | | |
157 | 38.8k | status = 1; |
158 | 38.8k | *scale = 0; |
159 | | |
160 | 118k | while (status) { |
161 | 79.2k | status = 0; |
162 | | |
163 | 2.61M | for (i = MAX_ORDER; i >= 0; i--) { |
164 | 2.53M | temp_buf1[i] = 0; |
165 | 2.53M | temp_buf2[i] = 0; |
166 | 2.53M | } |
167 | | |
168 | 79.2k | accu1 = (0x7fffffff >> *scale); |
169 | | |
170 | 637k | for (i = 0; i <= order; i++) { |
171 | 558k | accu = accu1; |
172 | | |
173 | 4.28M | for (j = 0; j < order; j++) { |
174 | 3.72M | temp_buf2[j] = ixheaac_round16(accu1); |
175 | 3.72M | accu1 = ixheaac_mac16x16in32_shl_sat(accu1, parcor[j], temp_buf1[j]); |
176 | | |
177 | 3.72M | if (ixheaac_abs32_sat(accu1) == 0x7fffffff) { |
178 | 278k | status = 1; |
179 | 278k | } |
180 | 3.72M | } |
181 | | |
182 | 4.28M | for (j = (order - 1); j >= 0; j--) { |
183 | 3.72M | accu2 = ixheaac_deposit16h_in32(temp_buf1[j]); |
184 | 3.72M | accu2 = ixheaac_mac16x16in32_shl_sat(accu2, parcor[j], temp_buf2[j]); |
185 | 3.72M | temp_buf1[j + 1] = ixheaac_round16(accu2); |
186 | 3.72M | if (ixheaac_abs32_sat(accu2) == 0x7fffffff) { |
187 | 42.6k | status = 1; |
188 | 42.6k | } |
189 | 3.72M | } |
190 | | |
191 | 558k | temp_buf1[0] = ixheaac_round16(accu); |
192 | 558k | lpc[i] = ixheaac_round16(accu1); |
193 | 558k | accu1 = 0; |
194 | 558k | } |
195 | | |
196 | 79.2k | accu1 = (status - 1); |
197 | | |
198 | 79.2k | if (accu1 == 0) { |
199 | 40.3k | *scale = *scale + 1; |
200 | 40.3k | } |
201 | 79.2k | } |
202 | 38.8k | } |
203 | | |
204 | | VOID ixheaacd_tns_ar_filter_fixed_dec(WORD32 *spectrum, WORD32 size, WORD32 inc, |
205 | | WORD32 *lpc, WORD32 order, |
206 | | WORD32 shift_value, WORD scale_spec) |
207 | | |
208 | 14.5k | { |
209 | 14.5k | WORD32 i, j; |
210 | 14.5k | WORD32 y, state[MAX_ORDER + 1]; |
211 | 14.5k | WORD32 acc; |
212 | | |
213 | 14.5k | if ((order & 3) != 0) { |
214 | 11.2k | for (i = order + 1; i < ((WORD32)(order & 0xfffffffc) + 4); i++) { |
215 | 5.07k | lpc[i] = 0; |
216 | 5.07k | } |
217 | 6.14k | lpc[i] = 0; |
218 | 6.14k | order = ((order & 0xfffffffc) + 4); |
219 | 6.14k | order = order & 31; |
220 | 6.14k | } |
221 | 14.5k | { |
222 | 174k | for (i = 0; i < order; i++) { |
223 | 160k | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
224 | 160k | acc = 0; |
225 | | |
226 | 996k | for (j = i; j > 0; j--) { |
227 | 836k | acc = ixheaacd_mac32_tns_sat(state[j - 1], lpc[j], acc); |
228 | 836k | state[j] = state[j - 1]; |
229 | 836k | } |
230 | 160k | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
231 | 160k | state[0] = ixheaac_shl32_sat(y, shift_value); |
232 | | |
233 | 160k | *spectrum = y >> scale_spec; |
234 | 160k | spectrum += inc; |
235 | 160k | } |
236 | 2.73M | for (i = order; i < size; i++) { |
237 | 2.72M | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
238 | 2.72M | acc = 0; |
239 | 33.4M | for (j = order; j > 0; j--) { |
240 | 30.7M | acc = ixheaacd_mac32_tns_sat(state[j - 1], lpc[j], acc); |
241 | 30.7M | state[j] = state[j - 1]; |
242 | 30.7M | } |
243 | 2.72M | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
244 | 2.72M | state[0] = ixheaac_shl32_sat(y, shift_value); |
245 | | |
246 | 2.72M | *spectrum = y >> scale_spec; |
247 | 2.72M | spectrum += inc; |
248 | 2.72M | } |
249 | 14.5k | } |
250 | 14.5k | } |
251 | | |
252 | | VOID ixheaacd_tns_ar_filter_fixed_non_neon_armv7(WORD32 *spectrum, WORD32 size, |
253 | | WORD32 inc, WORD32 *lpc, |
254 | | WORD32 order, |
255 | | WORD32 shift_value, |
256 | 0 | WORD scale_spec) { |
257 | 0 | WORD32 i, j; |
258 | 0 | WORD32 y, state[MAX_ORDER + 1]; |
259 | 0 | WORD32 acc; |
260 | |
|
261 | 0 | if ((order & 3) != 0) { |
262 | 0 | for (i = order + 1; i < ((WORD32)(order & 0xfffffffc) + 4); i++) { |
263 | 0 | lpc[i] = 0; |
264 | 0 | } |
265 | 0 | lpc[i] = 0; |
266 | 0 | order = ((order & 0xfffffffc) + 4); |
267 | 0 | } |
268 | 0 | { |
269 | 0 | for (i = 0; i < order; i++) { |
270 | 0 | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
271 | 0 | acc = 0; |
272 | |
|
273 | 0 | for (j = i; j > 0; j--) { |
274 | 0 | acc = ixheaacd_mac32_tns_sat(state[j - 1], lpc[j], acc); |
275 | 0 | state[j] = state[j - 1]; |
276 | 0 | } |
277 | 0 | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
278 | 0 | state[0] = ixheaac_shl32_sat(y, shift_value); |
279 | |
|
280 | 0 | *spectrum = y >> scale_spec; |
281 | 0 | spectrum += inc; |
282 | 0 | } |
283 | 0 | for (i = order; i < size; i++) { |
284 | 0 | WORD64 acc = 0; |
285 | 0 | WORD32 acc1; |
286 | 0 | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
287 | 0 | for (j = order; j > 0; j--) { |
288 | 0 | acc = ixheaac_mac32x32in64_dual(state[j - 1], lpc[j], acc); |
289 | 0 | state[j] = state[j - 1]; |
290 | 0 | } |
291 | 0 | acc1 = (WORD32)(acc >> 32); |
292 | |
|
293 | 0 | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc1, 1)); |
294 | 0 | state[0] = ixheaac_shl32_sat(y, shift_value); |
295 | |
|
296 | 0 | *spectrum = y >> scale_spec; |
297 | 0 | spectrum += inc; |
298 | 0 | } |
299 | 0 | } |
300 | 0 | } |
301 | | |
302 | | VOID ixheaacd_tns_ar_filter_fixed_armv8(WORD32 *spectrum, WORD32 size, |
303 | | WORD32 inc, WORD32 *lpc, WORD32 order, |
304 | 0 | WORD32 shift_value, WORD scale_spec) { |
305 | 0 | WORD32 i, j; |
306 | 0 | WORD32 y, state[MAX_ORDER + 1]; |
307 | 0 | WORD32 acc; |
308 | |
|
309 | 0 | if ((order & 3) != 0) { |
310 | 0 | for (i = order + 1; i < ((WORD32)(order & 0xfffffffc) + 4); i++) { |
311 | 0 | lpc[i] = 0; |
312 | 0 | } |
313 | 0 | lpc[i] = 0; |
314 | 0 | order = ((order & 0xfffffffc) + 4); |
315 | 0 | } |
316 | 0 | { |
317 | 0 | for (i = 0; i < order; i++) { |
318 | 0 | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
319 | 0 | acc = 0; |
320 | |
|
321 | 0 | for (j = i; j > 0; j--) { |
322 | 0 | acc = ixheaacd_mac32_tns_sat(state[j - 1], lpc[j], acc); |
323 | 0 | state[j] = state[j - 1]; |
324 | 0 | } |
325 | 0 | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
326 | 0 | state[0] = ixheaac_shl32_sat(y, shift_value); |
327 | |
|
328 | 0 | *spectrum = y >> scale_spec; |
329 | 0 | spectrum += inc; |
330 | 0 | } |
331 | 0 | for (i = order; i < size; i++) { |
332 | 0 | WORD64 acc = 0; |
333 | 0 | WORD32 acc1; |
334 | 0 | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
335 | 0 | for (j = order; j > 0; j--) { |
336 | 0 | acc = ixheaac_mac32x32in64_dual(state[j - 1], lpc[j], acc); |
337 | 0 | state[j] = state[j - 1]; |
338 | 0 | } |
339 | 0 | acc1 = (WORD32)(acc >> 32); |
340 | |
|
341 | 0 | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc1, 1)); |
342 | 0 | state[0] = ixheaac_shl32_sat(y, shift_value); |
343 | |
|
344 | 0 | *spectrum = y >> scale_spec; |
345 | 0 | spectrum += inc; |
346 | 0 | } |
347 | 0 | } |
348 | 0 | } |
349 | | |
350 | | void ixheaacd_tns_ma_filter_fixed_ld(WORD32 *spectrum, WORD32 size, WORD32 inc, |
351 | | WORD32 *lpc, WORD32 order, |
352 | 14.0k | WORD16 shift_value) { |
353 | 14.0k | WORD32 i, j; |
354 | 14.0k | WORD32 y, state[MAX_ORDER]; |
355 | | |
356 | 159k | for (i = 0; i < order; i++) state[i] = 0; |
357 | | |
358 | 2.82M | for (i = 0; i < size; i++) { |
359 | 2.81M | y = *spectrum; |
360 | | |
361 | 33.3M | for (j = 0; j < order; j++) y += ixheaac_mult32_shl(state[j], lpc[j + 1]); |
362 | | |
363 | 30.5M | for (j = order - 1; j > 0; j--) state[j] = state[j - 1]; |
364 | | |
365 | 2.81M | state[0] = ixheaac_shl32_dir_sat(*spectrum, shift_value); |
366 | 2.81M | *spectrum = y; |
367 | 2.81M | spectrum += inc; |
368 | 2.81M | } |
369 | 14.0k | } |
370 | | |
371 | | VOID ixheaacd_tns_ar_filter_dec(WORD32 *spectrum, WORD32 size, WORD32 inc, |
372 | | WORD16 *lpc, WORD32 order, WORD32 shift_value, |
373 | 36.2k | WORD scale_spec, WORD32 *ptr_filter_state) { |
374 | 36.2k | WORD32 i, j; |
375 | 36.2k | WORD32 y; |
376 | 36.2k | WORD32 acc; |
377 | | |
378 | 36.2k | if ((order & 3) != 0) { |
379 | 40.5k | for (i = order + 1; i < ((WORD32)(order & (~3)) + 4); i++) { |
380 | 9.19k | lpc[i] = 0; |
381 | 9.19k | } |
382 | 31.3k | if (i < (MAX_ORDER + 1)) { |
383 | 31.3k | lpc[i] = 0; |
384 | 31.3k | order = ((order & (~3)) + 4); |
385 | 31.3k | } else { |
386 | 0 | order = MAX_ORDER; |
387 | 0 | } |
388 | 31.3k | } |
389 | | |
390 | 291k | for (i = 0; i < order; i++) { |
391 | 255k | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
392 | 255k | acc = 0; |
393 | | |
394 | 1.09M | for (j = i; j > 0; j--) { |
395 | 835k | acc = ixheaac_add32_sat( |
396 | 835k | acc, ixheaac_mult32x16in32(ptr_filter_state[j - 1], lpc[j])); |
397 | 835k | ptr_filter_state[j] = ptr_filter_state[j - 1]; |
398 | 835k | } |
399 | | |
400 | 255k | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
401 | 255k | ptr_filter_state[0] = ixheaac_shl32_sat(y, shift_value); |
402 | 255k | *spectrum = y >> scale_spec; |
403 | 255k | spectrum += inc; |
404 | 255k | } |
405 | | |
406 | 2.35M | for (i = order; i < size; i++) { |
407 | 2.31M | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
408 | 2.31M | acc = 0; |
409 | 16.2M | for (j = order; j > 0; j--) { |
410 | 13.9M | acc = ixheaac_add32_sat( |
411 | 13.9M | acc, ixheaac_mult32x16in32(ptr_filter_state[j - 1], lpc[j])); |
412 | 13.9M | ptr_filter_state[j] = ptr_filter_state[j - 1]; |
413 | 13.9M | } |
414 | | |
415 | 2.31M | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
416 | 2.31M | ptr_filter_state[0] = ixheaac_shl32_sat(y, shift_value); |
417 | 2.31M | *spectrum = y >> scale_spec; |
418 | 2.31M | spectrum += inc; |
419 | 2.31M | } |
420 | 36.2k | } |
421 | | |
422 | 448k | WORD32 ixheaacd_calc_max_spectral_line_dec(WORD32 *ptr_tmp, WORD32 size) { |
423 | 448k | WORD32 max_spec_line = 0, i; |
424 | 448k | WORD unroll_cnt, rem; |
425 | | |
426 | 448k | unroll_cnt = size >> 3; |
427 | 34.4M | for (i = unroll_cnt; i--;) { |
428 | 33.9M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
429 | 33.9M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
430 | 33.9M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
431 | 33.9M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
432 | | |
433 | 33.9M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
434 | 33.9M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
435 | 33.9M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
436 | 33.9M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
437 | 33.9M | } |
438 | | |
439 | 448k | rem = size - (unroll_cnt << 3); |
440 | | |
441 | 448k | if (rem) { |
442 | 285k | for (i = rem; i--;) { |
443 | 228k | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
444 | 228k | } |
445 | 57.0k | } |
446 | | |
447 | 448k | return ixheaac_norm32(max_spec_line); |
448 | 448k | } |