/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 | 29.0M | WORD32 c) { |
60 | 29.0M | WORD32 result; |
61 | 29.0M | WORD64 temp_result; |
62 | | |
63 | 29.0M | temp_result = (WORD64)a * (WORD64)b; |
64 | 29.0M | result = (WORD32)(temp_result >> 32); |
65 | 29.0M | result = ixheaac_add32_sat(c, result); |
66 | 29.0M | return (result); |
67 | 29.0M | } |
68 | | |
69 | | VOID ixheaacd_tns_decode_coefficients( |
70 | | const ia_filter_info_struct *filter, WORD32 *a, |
71 | 34.5k | ia_aac_dec_tables_struct *ptr_aac_tables) { |
72 | 34.5k | WORD32 i; |
73 | 34.5k | WORD32 tmp; |
74 | 34.5k | WORD32 *aptr = a; |
75 | 34.5k | WORD32 *tns_coeff_ptr; |
76 | 34.5k | WORD8 ixheaacd_drc_offset; |
77 | | |
78 | 34.5k | tmp = filter->resolution; |
79 | 34.5k | if (tmp == 0) { |
80 | 31.4k | tns_coeff_ptr = ptr_aac_tables->pstr_block_tables->tns_coeff3; |
81 | 31.4k | ixheaacd_drc_offset = 4; |
82 | | |
83 | 31.4k | } else { |
84 | 3.09k | tns_coeff_ptr = ptr_aac_tables->pstr_block_tables->tns_coeff4; |
85 | 3.09k | ixheaacd_drc_offset = 8; |
86 | 3.09k | } |
87 | | |
88 | 345k | for (i = 0; i < filter->order; i++) { |
89 | 311k | *aptr++ = tns_coeff_ptr[filter->coef[i] + ixheaacd_drc_offset]; |
90 | 311k | } |
91 | 34.5k | } |
92 | | |
93 | | VOID ixheaacd_tns_parcor_to_lpc(WORD32 *parcor, WORD32 *lpc, WORD16 *scale, |
94 | | WORD32 order) |
95 | | |
96 | 27.1k | { |
97 | 27.1k | WORD i, j, status; |
98 | 27.1k | WORD32 z1; |
99 | 27.1k | WORD32 z[MAX_ORDER + 1]; |
100 | 27.1k | WORD32 w[MAX_ORDER + 1]; |
101 | 27.1k | WORD32 accu1, accu2; |
102 | | |
103 | 27.1k | status = 1; |
104 | 27.1k | *scale = 1; |
105 | | |
106 | 80.9k | while (status) { |
107 | 53.7k | status = 0; |
108 | | |
109 | 1.77M | for (i = MAX_ORDER; i >= 0; i--) { |
110 | 1.71M | z[i] = 0; |
111 | 1.71M | w[i] = 0; |
112 | 1.71M | } |
113 | | |
114 | 53.7k | accu1 = (0x40000000 >> (*scale - 1)); |
115 | | |
116 | 688k | for (i = 0; i <= order; i++) { |
117 | 634k | z1 = accu1; |
118 | | |
119 | 7.78M | for (j = 0; j < order; j++) { |
120 | 7.14M | w[j] = (accu1); |
121 | | |
122 | 7.14M | accu1 = ixheaac_add32_sat(accu1, |
123 | 7.14M | ixheaac_mult32_shl_sat(parcor[j], (z[j]))); |
124 | 7.14M | if (ixheaac_abs32_sat(accu1) == 0x7fffffff) status = 1; |
125 | 7.14M | } |
126 | 7.78M | for (j = (order - 1); j >= 0; j--) { |
127 | 7.14M | accu2 = (z[j]); |
128 | 7.14M | accu2 = ixheaac_add32_sat(accu2, |
129 | 7.14M | ixheaac_mult32_shl_sat(parcor[j], (w[j]))); |
130 | 7.14M | z[j + 1] = (accu2); |
131 | 7.14M | if (ixheaac_abs32_sat(accu2) == 0x7fffffff) status = 1; |
132 | 7.14M | } |
133 | | |
134 | 634k | z[0] = (z1); |
135 | 634k | lpc[i] = (accu1); |
136 | 634k | accu1 = 0; |
137 | 634k | } |
138 | | |
139 | 53.7k | accu1 = (status - 1); |
140 | | |
141 | 53.7k | if (accu1 == 0) { |
142 | 26.5k | *scale = *scale + 1; |
143 | 26.5k | } |
144 | 53.7k | } |
145 | 27.1k | } |
146 | | |
147 | | VOID ixheaacd_tns_parcor_lpc_convert_dec(WORD16 *parcor, WORD16 *lpc, |
148 | | WORD16 *scale, WORD order) |
149 | | |
150 | 43.9k | { |
151 | 43.9k | WORD i, j, status; |
152 | 43.9k | WORD32 accu; |
153 | 43.9k | WORD16 temp_buf1[MAX_ORDER + 1]; |
154 | 43.9k | WORD16 temp_buf2[MAX_ORDER + 1]; |
155 | 43.9k | WORD32 accu1, accu2; |
156 | | |
157 | 43.9k | status = 1; |
158 | 43.9k | *scale = 0; |
159 | | |
160 | 133k | while (status) { |
161 | 89.2k | status = 0; |
162 | | |
163 | 2.94M | for (i = MAX_ORDER; i >= 0; i--) { |
164 | 2.85M | temp_buf1[i] = 0; |
165 | 2.85M | temp_buf2[i] = 0; |
166 | 2.85M | } |
167 | | |
168 | 89.2k | accu1 = (0x7fffffff >> *scale); |
169 | | |
170 | 743k | for (i = 0; i <= order; i++) { |
171 | 653k | accu = accu1; |
172 | | |
173 | 5.09M | for (j = 0; j < order; j++) { |
174 | 4.43M | temp_buf2[j] = ixheaac_round16(accu1); |
175 | 4.43M | accu1 = ixheaac_mac16x16in32_shl_sat(accu1, parcor[j], temp_buf1[j]); |
176 | | |
177 | 4.43M | if (ixheaac_abs32_sat(accu1) == 0x7fffffff) { |
178 | 316k | status = 1; |
179 | 316k | } |
180 | 4.43M | } |
181 | | |
182 | 5.09M | for (j = (order - 1); j >= 0; j--) { |
183 | 4.43M | accu2 = ixheaac_deposit16h_in32(temp_buf1[j]); |
184 | 4.43M | accu2 = ixheaac_mac16x16in32_shl_sat(accu2, parcor[j], temp_buf2[j]); |
185 | 4.43M | temp_buf1[j + 1] = ixheaac_round16(accu2); |
186 | 4.43M | if (ixheaac_abs32_sat(accu2) == 0x7fffffff) { |
187 | 37.3k | status = 1; |
188 | 37.3k | } |
189 | 4.43M | } |
190 | | |
191 | 653k | temp_buf1[0] = ixheaac_round16(accu); |
192 | 653k | lpc[i] = ixheaac_round16(accu1); |
193 | 653k | accu1 = 0; |
194 | 653k | } |
195 | | |
196 | 89.2k | accu1 = (status - 1); |
197 | | |
198 | 89.2k | if (accu1 == 0) { |
199 | 45.3k | *scale = *scale + 1; |
200 | 45.3k | } |
201 | 89.2k | } |
202 | 43.9k | } |
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 | 13.7k | { |
209 | 13.7k | WORD32 i, j; |
210 | 13.7k | WORD32 y, state[MAX_ORDER + 1]; |
211 | 13.7k | WORD32 acc; |
212 | | |
213 | 13.7k | if ((order & 3) != 0) { |
214 | 11.0k | for (i = order + 1; i < ((WORD32)(order & 0xfffffffc) + 4); i++) { |
215 | 5.26k | lpc[i] = 0; |
216 | 5.26k | } |
217 | 5.81k | lpc[i] = 0; |
218 | 5.81k | order = ((order & 0xfffffffc) + 4); |
219 | 5.81k | order = order & 31; |
220 | 5.81k | } |
221 | 13.7k | { |
222 | 160k | for (i = 0; i < order; i++) { |
223 | 146k | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
224 | 146k | acc = 0; |
225 | | |
226 | 899k | for (j = i; j > 0; j--) { |
227 | 752k | acc = ixheaacd_mac32_tns_sat(state[j - 1], lpc[j], acc); |
228 | 752k | state[j] = state[j - 1]; |
229 | 752k | } |
230 | 146k | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
231 | 146k | state[0] = ixheaac_shl32_sat(y, shift_value); |
232 | | |
233 | 146k | *spectrum = y >> scale_spec; |
234 | 146k | spectrum += inc; |
235 | 146k | } |
236 | 2.56M | for (i = order; i < size; i++) { |
237 | 2.55M | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
238 | 2.55M | acc = 0; |
239 | 30.8M | for (j = order; j > 0; j--) { |
240 | 28.3M | acc = ixheaacd_mac32_tns_sat(state[j - 1], lpc[j], acc); |
241 | 28.3M | state[j] = state[j - 1]; |
242 | 28.3M | } |
243 | 2.55M | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
244 | 2.55M | state[0] = ixheaac_shl32_sat(y, shift_value); |
245 | | |
246 | 2.55M | *spectrum = y >> scale_spec; |
247 | 2.55M | spectrum += inc; |
248 | 2.55M | } |
249 | 13.7k | } |
250 | 13.7k | } |
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 | 13.3k | WORD16 shift_value) { |
353 | 13.3k | WORD32 i, j; |
354 | 13.3k | WORD32 y, state[MAX_ORDER]; |
355 | | |
356 | 146k | for (i = 0; i < order; i++) state[i] = 0; |
357 | | |
358 | 2.65M | for (i = 0; i < size; i++) { |
359 | 2.64M | y = *spectrum; |
360 | | |
361 | 30.5M | for (j = 0; j < order; j++) y += ixheaac_mult32_shl(state[j], lpc[j + 1]); |
362 | | |
363 | 27.9M | for (j = order - 1; j > 0; j--) state[j] = state[j - 1]; |
364 | | |
365 | 2.64M | state[0] = ixheaac_shl32_dir_sat(*spectrum, shift_value); |
366 | 2.64M | *spectrum = y; |
367 | 2.64M | spectrum += inc; |
368 | 2.64M | } |
369 | 13.3k | } |
370 | | |
371 | | VOID ixheaacd_tns_ar_filter_dec(WORD32 *spectrum, WORD32 size, WORD32 inc, |
372 | | WORD16 *lpc, WORD32 order, WORD32 shift_value, |
373 | 40.4k | WORD scale_spec, WORD32 *ptr_filter_state) { |
374 | 40.4k | WORD32 i, j; |
375 | 40.4k | WORD32 y; |
376 | 40.4k | WORD32 acc; |
377 | | |
378 | 40.4k | if ((order & 3) != 0) { |
379 | 43.3k | for (i = order + 1; i < ((WORD32)(order & (~3)) + 4); i++) { |
380 | 7.28k | lpc[i] = 0; |
381 | 7.28k | } |
382 | 36.0k | if (i < (MAX_ORDER + 1)) { |
383 | 36.0k | lpc[i] = 0; |
384 | 36.0k | order = ((order & (~3)) + 4); |
385 | 36.0k | } else { |
386 | 0 | order = MAX_ORDER; |
387 | 0 | } |
388 | 36.0k | } |
389 | | |
390 | 336k | for (i = 0; i < order; i++) { |
391 | 295k | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
392 | 295k | acc = 0; |
393 | | |
394 | 1.28M | for (j = i; j > 0; j--) { |
395 | 988k | acc = ixheaac_add32_sat( |
396 | 988k | acc, ixheaac_mult32x16in32(ptr_filter_state[j - 1], lpc[j])); |
397 | 988k | ptr_filter_state[j] = ptr_filter_state[j - 1]; |
398 | 988k | } |
399 | | |
400 | 295k | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
401 | 295k | ptr_filter_state[0] = ixheaac_shl32_sat(y, shift_value); |
402 | 295k | *spectrum = y >> scale_spec; |
403 | 295k | spectrum += inc; |
404 | 295k | } |
405 | | |
406 | 2.14M | for (i = order; i < size; i++) { |
407 | 2.10M | y = ixheaac_shl32_sat((*spectrum), scale_spec); |
408 | 2.10M | acc = 0; |
409 | 15.7M | for (j = order; j > 0; j--) { |
410 | 13.6M | acc = ixheaac_add32_sat( |
411 | 13.6M | acc, ixheaac_mult32x16in32(ptr_filter_state[j - 1], lpc[j])); |
412 | 13.6M | ptr_filter_state[j] = ptr_filter_state[j - 1]; |
413 | 13.6M | } |
414 | | |
415 | 2.10M | y = ixheaac_sub32_sat(y, ixheaac_shl32_sat(acc, 1)); |
416 | 2.10M | ptr_filter_state[0] = ixheaac_shl32_sat(y, shift_value); |
417 | 2.10M | *spectrum = y >> scale_spec; |
418 | 2.10M | spectrum += inc; |
419 | 2.10M | } |
420 | 40.4k | } |
421 | | |
422 | 426k | WORD32 ixheaacd_calc_max_spectral_line_dec(WORD32 *ptr_tmp, WORD32 size) { |
423 | 426k | WORD32 max_spec_line = 0, i; |
424 | 426k | WORD unroll_cnt, rem; |
425 | | |
426 | 426k | unroll_cnt = size >> 3; |
427 | 32.5M | for (i = unroll_cnt; i--;) { |
428 | 32.1M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
429 | 32.1M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
430 | 32.1M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
431 | 32.1M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
432 | | |
433 | 32.1M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
434 | 32.1M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
435 | 32.1M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
436 | 32.1M | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
437 | 32.1M | } |
438 | | |
439 | 426k | rem = size - (unroll_cnt << 3); |
440 | | |
441 | 426k | if (rem) { |
442 | 309k | for (i = rem; i--;) { |
443 | 247k | max_spec_line = ixheaac_abs32_nrm(*ptr_tmp++) | max_spec_line; |
444 | 247k | } |
445 | 61.8k | } |
446 | | |
447 | 426k | return ixheaac_norm32(max_spec_line); |
448 | 426k | } |