/src/libxaac/decoder/ixheaacd_tns.c
Line | Count | Source (jump to first uncovered line) |
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 <math.h> |
21 | | #include <stdio.h> |
22 | | |
23 | | #include "ixheaac_type_def.h" |
24 | | #include "ixheaacd_bitbuffer.h" |
25 | | |
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_sbrdecsettings.h" |
34 | | #include "ixheaacd_info.h" |
35 | | #include "ixheaacd_sbr_common.h" |
36 | | #include "ixheaacd_drc_data_struct.h" |
37 | | #include "ixheaacd_drc_dec.h" |
38 | | #include "ixheaacd_sbrdecoder.h" |
39 | | #include "ixheaacd_mps_polyphase.h" |
40 | | #include "ixheaac_sbr_const.h" |
41 | | |
42 | | #include "ixheaacd_ec_defines.h" |
43 | | #include "ixheaacd_ec_struct_def.h" |
44 | | #include "ixheaacd_main.h" |
45 | | #include "ixheaacd_arith_dec.h" |
46 | | #include "ixheaacd_function_selector.h" |
47 | | #include "ixheaac_constants.h" |
48 | | #include "ixheaac_basic_ops32.h" |
49 | | #include "ixheaac_basic_ops40.h" |
50 | | |
51 | 234k | #define sfb_offset(x) (((x) > 0) ? sfb_top[(x)-1] : 0) |
52 | | |
53 | | static VOID ixheaacd_tns_dec_coef_usac(ia_usac_data_struct *usac_data, |
54 | | ia_tns_filter_struct *filter, |
55 | 117k | WORD32 coef_res, WORD32 *par_coeff) { |
56 | 117k | WORD32 resolution; |
57 | 117k | WORD32 *ptr_par_coeff = par_coeff; |
58 | 117k | const WORD32 *tns_coeff_ptr; |
59 | 117k | WORD32 ixheaacd_drc_offset = 4; |
60 | 117k | WORD16 *ptr_coeff = filter->coef; |
61 | 117k | WORD32 order; |
62 | | |
63 | 117k | resolution = coef_res - 3; |
64 | 117k | tns_coeff_ptr = usac_data->tns_coeff3_32; |
65 | 117k | if (resolution) { |
66 | 90.5k | tns_coeff_ptr = usac_data->tns_coeff4_32; |
67 | 90.5k | ixheaacd_drc_offset = ixheaacd_drc_offset << 1; |
68 | 90.5k | } |
69 | 117k | order = filter->order; |
70 | | |
71 | 450k | do { |
72 | 450k | WORD16 temp = *ptr_coeff++; |
73 | 450k | *ptr_par_coeff++ = tns_coeff_ptr[temp + ixheaacd_drc_offset]; |
74 | 450k | order--; |
75 | 450k | } while (order != 0); |
76 | 117k | } |
77 | | |
78 | | static VOID ixheaacd_tns_parcor_lpc_convert_usac(WORD32 *parcor, |
79 | | WORD32 *lpc_coeff, |
80 | | WORD32 *scale, WORD order) |
81 | | |
82 | 117k | { |
83 | 117k | WORD i, j, status; |
84 | 117k | WORD32 accu; |
85 | 117k | WORD32 temp_buf1[TNS_MAX_ORDER + 1]; |
86 | 117k | WORD32 temp_buf2[TNS_MAX_ORDER + 1]; |
87 | 117k | WORD32 accu1, accu2; |
88 | | |
89 | 117k | status = 1; |
90 | 117k | *scale = 1; |
91 | | |
92 | 314k | while (status) { |
93 | 197k | status = 0; |
94 | | |
95 | 6.51M | for (i = TNS_MAX_ORDER; i >= 0; i--) { |
96 | 6.32M | temp_buf1[i] = 0; |
97 | 6.32M | temp_buf2[i] = 0; |
98 | 6.32M | } |
99 | | |
100 | 197k | accu1 = (0x40000000 >> (*scale - 1)); |
101 | | |
102 | 1.29M | for (i = 0; i <= order; i++) { |
103 | 1.10M | accu = accu1; |
104 | | |
105 | 7.58M | for (j = 0; j < order; j++) { |
106 | 6.48M | temp_buf2[j] = (accu1); |
107 | | |
108 | 6.48M | accu1 = ixheaac_add32_sat( |
109 | 6.48M | accu1, ixheaac_mult32_shl_sat(parcor[j], temp_buf1[j])); |
110 | 6.48M | if (ixheaac_abs32_sat(accu1) == 0x7fffffff) status = 1; |
111 | 6.48M | } |
112 | | |
113 | 7.58M | for (j = (order - 1); j >= 0; j--) { |
114 | 6.48M | accu2 = (temp_buf1[j]); |
115 | 6.48M | accu2 = ixheaac_add32_sat( |
116 | 6.48M | accu2, ixheaac_mult32_shl_sat(parcor[j], temp_buf2[j])); |
117 | 6.48M | temp_buf1[j + 1] = (accu2); |
118 | | |
119 | 6.48M | if (ixheaac_abs32_sat(accu2) == 0x7fffffff) status = 1; |
120 | 6.48M | } |
121 | | |
122 | 1.10M | temp_buf1[0] = (accu); |
123 | 1.10M | lpc_coeff[i] = (accu1); |
124 | 1.10M | accu1 = 0; |
125 | 1.10M | } |
126 | | |
127 | 197k | accu1 = (status - 1); |
128 | | |
129 | 197k | if (accu1 == 0) { |
130 | 80.1k | *scale = *scale + 1; |
131 | 80.1k | } |
132 | 197k | } |
133 | 117k | } |
134 | | |
135 | | static VOID ixheaacd_tns_ar_filter_usac(WORD32 *spectrum, WORD32 size, |
136 | | WORD32 inc, WORD32 *lpc_coeff, |
137 | | WORD32 order, WORD32 shift_value, |
138 | 38.2k | WORD32 *ptr_filter_state) { |
139 | 38.2k | WORD32 i, j; |
140 | 38.2k | WORD32 y; |
141 | 38.2k | WORD64 acc; |
142 | | |
143 | 38.2k | if ((order & 3) != 0) { |
144 | 73.1k | for (i = order + 1; i < ((WORD32)(order & 0xfffffffc) + 4); i++) { |
145 | 37.7k | lpc_coeff[i] = 0; |
146 | 37.7k | } |
147 | 35.4k | lpc_coeff[i] = 0; |
148 | 35.4k | order = ((order & 0xfffffffc) + 4); |
149 | 35.4k | } |
150 | | |
151 | 345k | for (i = 0; i < order; i++) { |
152 | 306k | y = *spectrum; |
153 | 306k | acc = 0; |
154 | | |
155 | 1.52M | for (j = i; j > 0; j--) { |
156 | 1.21M | acc = ixheaac_add64_sat( |
157 | 1.21M | acc, ixheaac_mult64(ptr_filter_state[j - 1], lpc_coeff[j])); |
158 | 1.21M | ptr_filter_state[j] = ptr_filter_state[j - 1]; |
159 | 1.21M | } |
160 | | |
161 | 306k | y = ixheaac_sub32_sat(y, (WORD32)(acc >> 31)); |
162 | 306k | ptr_filter_state[0] = ixheaac_shl32(y, shift_value); |
163 | 306k | *spectrum = y; |
164 | 306k | spectrum += inc; |
165 | 306k | } |
166 | | |
167 | 3.96M | for (i = order; i < size; i++) { |
168 | 3.93M | y = *spectrum; |
169 | 3.93M | acc = 0; |
170 | 35.1M | for (j = order; j > 0; j--) { |
171 | 31.2M | acc = ixheaac_add64_sat( |
172 | 31.2M | acc, ixheaac_mult64(ptr_filter_state[j - 1], lpc_coeff[j])); |
173 | 31.2M | ; |
174 | 31.2M | ptr_filter_state[j] = ptr_filter_state[j - 1]; |
175 | 31.2M | } |
176 | 3.93M | y = ixheaac_sub32_sat(y, (WORD32)(acc >> 31)); |
177 | 3.93M | ptr_filter_state[0] = ixheaac_shl32(y, shift_value); |
178 | 3.93M | *spectrum = y; |
179 | 3.93M | spectrum += inc; |
180 | 3.93M | } |
181 | 38.2k | } |
182 | | |
183 | | IA_ERRORCODE ixheaacd_tns_apply(ia_usac_data_struct *usac_data, WORD32 *spec, |
184 | | WORD32 nbands, |
185 | | ia_sfb_info_struct *pstr_sfb_info, |
186 | 322k | ia_tns_frame_info_struct *pstr_tns) { |
187 | 322k | WORD32 f, start, stop, size, inc; |
188 | 322k | WORD32 n_filt, coef_res, order, direction; |
189 | 322k | WORD32 *ptr_spec; |
190 | 322k | WORD32 scale_spec; |
191 | 322k | WORD32 scale_lpc; |
192 | 322k | WORD32 guard_band; |
193 | 322k | WORD32 shift; |
194 | 322k | WORD32 lpc_coeff[TNS_MAX_ORDER + 1]; |
195 | 322k | WORD32 par_coeff[TNS_MAX_ORDER + 1]; |
196 | 322k | ia_tns_filter_struct *filt; |
197 | | |
198 | 322k | const WORD16 *sfb_top; |
199 | | |
200 | 322k | WORD32 nbins = (pstr_sfb_info->islong) ? 1024 : 128; |
201 | 322k | WORD32 i, j, idx; |
202 | | |
203 | 322k | idx = (pstr_sfb_info->islong) ? 0 : 1; |
204 | | |
205 | 322k | ptr_spec = &usac_data->scratch_buffer[0]; |
206 | | |
207 | 1.18M | for (j = 0; j < pstr_tns->n_subblocks; j++) { |
208 | 865k | sfb_top = pstr_sfb_info->ptr_sfb_tbl; |
209 | | |
210 | 331M | for (i = 0; i < nbins; i++) { |
211 | 330M | ptr_spec[i] = spec[i]; |
212 | 330M | } |
213 | | |
214 | 865k | if (pstr_tns->str_tns_info[j].n_filt) { |
215 | 111k | n_filt = pstr_tns->str_tns_info[j].n_filt; |
216 | | |
217 | 236k | for (f = 0; f < n_filt; f++) { |
218 | 124k | WORD32 tmp; |
219 | | |
220 | 124k | coef_res = pstr_tns->str_tns_info[j].coef_res; |
221 | 124k | filt = &pstr_tns->str_tns_info[j].str_filter[f]; |
222 | 124k | order = filt->order; |
223 | 124k | direction = filt->direction; |
224 | 124k | start = filt->start_band; |
225 | 124k | stop = filt->stop_band; |
226 | | |
227 | 124k | if (!order) continue; |
228 | | |
229 | 117k | ixheaacd_tns_dec_coef_usac(usac_data, filt, coef_res, |
230 | 117k | (WORD32 *)par_coeff); |
231 | | |
232 | 117k | ixheaacd_tns_parcor_lpc_convert_usac(par_coeff, lpc_coeff, &scale_lpc, |
233 | 117k | filt->order); |
234 | | |
235 | 117k | tmp = (*usac_data->tns_max_bands_tbl_usac)[usac_data->sampling_rate_idx] |
236 | 117k | [idx]; |
237 | | |
238 | 117k | start = ixheaac_min32(start, tmp); |
239 | | |
240 | 117k | start = ixheaac_min32(start, nbands); |
241 | 117k | if (start > pstr_sfb_info->sfb_per_sbk) return -1; |
242 | 117k | start = sfb_offset(start); |
243 | | |
244 | 117k | stop = ixheaac_min32(stop, tmp); |
245 | 117k | stop = ixheaac_min32(stop, nbands); |
246 | 117k | if (stop > pstr_sfb_info->sfb_per_sbk) return -1; |
247 | 117k | stop = sfb_offset(stop); |
248 | | |
249 | 117k | guard_band = 31 - ixheaac_norm32(filt->order); |
250 | | |
251 | 117k | if ((size = stop - start) <= 0) continue; |
252 | | |
253 | 38.2k | if (direction) { |
254 | 15.5k | inc = -1; |
255 | 15.5k | shift = stop - 1; |
256 | 15.5k | } |
257 | | |
258 | 22.7k | else { |
259 | 22.7k | inc = 1; |
260 | 22.7k | shift = start; |
261 | 22.7k | } |
262 | | |
263 | 38.2k | { |
264 | 38.2k | WORD32 *ptr_temp = ptr_spec + start; |
265 | 38.2k | scale_spec = (*ixheaacd_calc_max_spectral_line)(ptr_temp, size); |
266 | 38.2k | } |
267 | | |
268 | 38.2k | scale_spec = ((scale_spec - guard_band) - scale_lpc); |
269 | | |
270 | 38.2k | if (scale_spec > 0) { |
271 | 21.0k | ixheaacd_tns_ar_filter_usac(&ptr_spec[shift], size, inc, lpc_coeff, |
272 | 21.0k | filt->order, scale_lpc, |
273 | 21.0k | usac_data->x_ac_dec); |
274 | 21.0k | } |
275 | | |
276 | 17.2k | else { |
277 | 17.2k | WORD32 *ptr_temp = ptr_spec + start; |
278 | | |
279 | 17.2k | scale_spec = -scale_spec; |
280 | 17.2k | scale_spec = ixheaac_min32(scale_spec, 31); |
281 | | |
282 | 1.74M | for (i = size; i != 0; i--) { |
283 | 1.72M | *ptr_temp = *ptr_temp >> scale_spec; |
284 | 1.72M | ptr_temp++; |
285 | 1.72M | } |
286 | | |
287 | 17.2k | { |
288 | 17.2k | ixheaacd_tns_ar_filter_usac(&ptr_spec[shift], size, inc, lpc_coeff, |
289 | 17.2k | filt->order, scale_lpc, |
290 | 17.2k | usac_data->x_ac_dec); |
291 | 17.2k | } |
292 | | |
293 | 17.2k | { |
294 | 17.2k | ptr_temp = ptr_spec + start; |
295 | 17.2k | i = size; |
296 | | |
297 | 1.72M | do { |
298 | 1.72M | *ptr_temp = *ptr_temp << scale_spec; |
299 | 1.72M | ptr_temp++; |
300 | 1.72M | i--; |
301 | 1.72M | } while (i != 0); |
302 | 17.2k | } |
303 | 17.2k | } |
304 | | |
305 | 4.27M | for (i = start; i <= stop - 1; i++) { |
306 | 4.23M | spec[i] = ptr_spec[i]; |
307 | 4.23M | } |
308 | 38.2k | } |
309 | 111k | } |
310 | | |
311 | 865k | spec += pstr_sfb_info->bins_per_sbk; |
312 | 865k | } |
313 | 322k | return 0; |
314 | 322k | } |