/src/libxaac/decoder/ixheaacd_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 <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 | 204k | #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 | 102k | WORD32 coef_res, WORD32 *par_coeff) { |
56 | 102k | WORD32 resolution; |
57 | 102k | WORD32 *ptr_par_coeff = par_coeff; |
58 | 102k | const WORD32 *tns_coeff_ptr; |
59 | 102k | WORD32 ixheaacd_drc_offset = 4; |
60 | 102k | WORD16 *ptr_coeff = filter->coef; |
61 | 102k | WORD32 order; |
62 | | |
63 | 102k | resolution = coef_res - 3; |
64 | 102k | tns_coeff_ptr = usac_data->tns_coeff3_32; |
65 | 102k | if (resolution) { |
66 | 79.9k | tns_coeff_ptr = usac_data->tns_coeff4_32; |
67 | 79.9k | ixheaacd_drc_offset = ixheaacd_drc_offset << 1; |
68 | 79.9k | } |
69 | 102k | order = filter->order; |
70 | | |
71 | 400k | do { |
72 | 400k | WORD16 temp = *ptr_coeff++; |
73 | 400k | *ptr_par_coeff++ = tns_coeff_ptr[temp + ixheaacd_drc_offset]; |
74 | 400k | order--; |
75 | 400k | } while (order != 0); |
76 | 102k | } |
77 | | |
78 | | static VOID ixheaacd_tns_parcor_lpc_convert_usac(WORD32 *parcor, |
79 | | WORD32 *lpc_coeff, |
80 | | WORD32 *scale, WORD order) |
81 | | |
82 | 102k | { |
83 | 102k | WORD i, j, status; |
84 | 102k | WORD32 accu; |
85 | 102k | WORD32 temp_buf1[TNS_MAX_ORDER + 1]; |
86 | 102k | WORD32 temp_buf2[TNS_MAX_ORDER + 1]; |
87 | 102k | WORD32 accu1, accu2; |
88 | | |
89 | 102k | status = 1; |
90 | 102k | *scale = 1; |
91 | | |
92 | 259k | while (status) { |
93 | 157k | status = 0; |
94 | | |
95 | 5.19M | for (i = TNS_MAX_ORDER; i >= 0; i--) { |
96 | 5.03M | temp_buf1[i] = 0; |
97 | 5.03M | temp_buf2[i] = 0; |
98 | 5.03M | } |
99 | | |
100 | 157k | accu1 = (0x40000000 >> (*scale - 1)); |
101 | | |
102 | 1.03M | for (i = 0; i <= order; i++) { |
103 | 874k | accu = accu1; |
104 | | |
105 | 6.01M | for (j = 0; j < order; j++) { |
106 | 5.14M | temp_buf2[j] = (accu1); |
107 | | |
108 | 5.14M | accu1 = ixheaac_add32_sat( |
109 | 5.14M | accu1, ixheaac_mult32_shl_sat(parcor[j], temp_buf1[j])); |
110 | 5.14M | if (ixheaac_abs32_sat(accu1) == 0x7fffffff) status = 1; |
111 | 5.14M | } |
112 | | |
113 | 6.01M | for (j = (order - 1); j >= 0; j--) { |
114 | 5.14M | accu2 = (temp_buf1[j]); |
115 | 5.14M | accu2 = ixheaac_add32_sat( |
116 | 5.14M | accu2, ixheaac_mult32_shl_sat(parcor[j], temp_buf2[j])); |
117 | 5.14M | temp_buf1[j + 1] = (accu2); |
118 | | |
119 | 5.14M | if (ixheaac_abs32_sat(accu2) == 0x7fffffff) status = 1; |
120 | 5.14M | } |
121 | | |
122 | 874k | temp_buf1[0] = (accu); |
123 | 874k | lpc_coeff[i] = (accu1); |
124 | 874k | accu1 = 0; |
125 | 874k | } |
126 | | |
127 | 157k | accu1 = (status - 1); |
128 | | |
129 | 157k | if (accu1 == 0) { |
130 | 54.8k | *scale = *scale + 1; |
131 | 54.8k | } |
132 | 157k | } |
133 | 102k | } |
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.6k | WORD32 *ptr_filter_state) { |
139 | 38.6k | WORD32 i, j; |
140 | 38.6k | WORD32 y; |
141 | 38.6k | WORD64 acc; |
142 | | |
143 | 38.6k | if ((order & 3) != 0) { |
144 | 67.4k | for (i = order + 1; i < ((WORD32)(order & 0xfffffffc) + 4); i++) { |
145 | 34.0k | lpc_coeff[i] = 0; |
146 | 34.0k | } |
147 | 33.4k | lpc_coeff[i] = 0; |
148 | 33.4k | order = ((order & 0xfffffffc) + 4); |
149 | 33.4k | } |
150 | | |
151 | 332k | for (i = 0; i < order; i++) { |
152 | 293k | y = *spectrum; |
153 | 293k | acc = 0; |
154 | | |
155 | 1.42M | for (j = i; j > 0; j--) { |
156 | 1.13M | acc = ixheaac_add64_sat( |
157 | 1.13M | acc, ixheaac_mult64(ptr_filter_state[j - 1], lpc_coeff[j])); |
158 | 1.13M | ptr_filter_state[j] = ptr_filter_state[j - 1]; |
159 | 1.13M | } |
160 | | |
161 | 293k | y = ixheaac_sub32_sat(y, (WORD32)(acc >> 31)); |
162 | 293k | ptr_filter_state[0] = ixheaac_shl32(y, shift_value); |
163 | 293k | *spectrum = y; |
164 | 293k | spectrum += inc; |
165 | 293k | } |
166 | | |
167 | 3.42M | for (i = order; i < size; i++) { |
168 | 3.38M | y = *spectrum; |
169 | 3.38M | acc = 0; |
170 | 27.0M | for (j = order; j > 0; j--) { |
171 | 23.6M | acc = ixheaac_add64_sat( |
172 | 23.6M | acc, ixheaac_mult64(ptr_filter_state[j - 1], lpc_coeff[j])); |
173 | 23.6M | ; |
174 | 23.6M | ptr_filter_state[j] = ptr_filter_state[j - 1]; |
175 | 23.6M | } |
176 | 3.38M | y = ixheaac_sub32_sat(y, (WORD32)(acc >> 31)); |
177 | 3.38M | ptr_filter_state[0] = ixheaac_shl32(y, shift_value); |
178 | 3.38M | *spectrum = y; |
179 | 3.38M | spectrum += inc; |
180 | 3.38M | } |
181 | 38.6k | } |
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 | 227k | ia_tns_frame_info_struct *pstr_tns) { |
187 | 227k | WORD32 f, start, stop, size, inc; |
188 | 227k | WORD32 n_filt, coef_res, order, direction; |
189 | 227k | WORD32 *ptr_spec; |
190 | 227k | WORD32 scale_spec; |
191 | 227k | WORD32 scale_lpc; |
192 | 227k | WORD32 guard_band; |
193 | 227k | WORD32 shift; |
194 | 227k | WORD32 lpc_coeff[TNS_MAX_ORDER + 1]; |
195 | 227k | WORD32 par_coeff[TNS_MAX_ORDER + 1]; |
196 | 227k | ia_tns_filter_struct *filt; |
197 | | |
198 | 227k | const WORD16 *sfb_top; |
199 | | |
200 | 227k | WORD32 nbins = (pstr_sfb_info->islong) ? 1024 : 128; |
201 | 227k | WORD32 i, j, idx; |
202 | | |
203 | 227k | idx = (pstr_sfb_info->islong) ? 0 : 1; |
204 | | |
205 | 227k | ptr_spec = &usac_data->scratch_buffer[0]; |
206 | | |
207 | 1.02M | for (j = 0; j < pstr_tns->n_subblocks; j++) { |
208 | 799k | sfb_top = pstr_sfb_info->ptr_sfb_tbl; |
209 | | |
210 | 233M | for (i = 0; i < nbins; i++) { |
211 | 232M | ptr_spec[i] = spec[i]; |
212 | 232M | } |
213 | | |
214 | 799k | if (pstr_tns->str_tns_info[j].n_filt) { |
215 | 99.9k | n_filt = pstr_tns->str_tns_info[j].n_filt; |
216 | | |
217 | 208k | for (f = 0; f < n_filt; f++) { |
218 | 108k | WORD32 tmp; |
219 | | |
220 | 108k | coef_res = pstr_tns->str_tns_info[j].coef_res; |
221 | 108k | filt = &pstr_tns->str_tns_info[j].str_filter[f]; |
222 | 108k | order = filt->order; |
223 | 108k | direction = filt->direction; |
224 | 108k | start = filt->start_band; |
225 | 108k | stop = filt->stop_band; |
226 | | |
227 | 108k | if (!order) continue; |
228 | | |
229 | 102k | ixheaacd_tns_dec_coef_usac(usac_data, filt, coef_res, |
230 | 102k | (WORD32 *)par_coeff); |
231 | | |
232 | 102k | ixheaacd_tns_parcor_lpc_convert_usac(par_coeff, lpc_coeff, &scale_lpc, |
233 | 102k | filt->order); |
234 | | |
235 | 102k | tmp = (*usac_data->tns_max_bands_tbl_usac)[usac_data->sampling_rate_idx] |
236 | 102k | [idx]; |
237 | | |
238 | 102k | start = ixheaac_min32(start, tmp); |
239 | | |
240 | 102k | start = ixheaac_min32(start, nbands); |
241 | 102k | if (start > pstr_sfb_info->sfb_per_sbk) return -1; |
242 | 102k | start = sfb_offset(start); |
243 | | |
244 | 102k | stop = ixheaac_min32(stop, tmp); |
245 | 102k | stop = ixheaac_min32(stop, nbands); |
246 | 102k | if (stop > pstr_sfb_info->sfb_per_sbk) return -1; |
247 | 102k | stop = sfb_offset(stop); |
248 | | |
249 | 102k | guard_band = 31 - ixheaac_norm32(filt->order); |
250 | | |
251 | 102k | if ((size = stop - start) <= 0) continue; |
252 | | |
253 | 38.6k | if (direction) { |
254 | 16.9k | inc = -1; |
255 | 16.9k | shift = stop - 1; |
256 | 16.9k | } |
257 | | |
258 | 21.6k | else { |
259 | 21.6k | inc = 1; |
260 | 21.6k | shift = start; |
261 | 21.6k | } |
262 | | |
263 | 38.6k | { |
264 | 38.6k | WORD32 *ptr_temp = ptr_spec + start; |
265 | 38.6k | scale_spec = (*ixheaacd_calc_max_spectral_line)(ptr_temp, size); |
266 | 38.6k | } |
267 | | |
268 | 38.6k | scale_spec = ((scale_spec - guard_band) - scale_lpc); |
269 | | |
270 | 38.6k | if (scale_spec > 0) { |
271 | 19.5k | ixheaacd_tns_ar_filter_usac(&ptr_spec[shift], size, inc, lpc_coeff, |
272 | 19.5k | filt->order, scale_lpc, |
273 | 19.5k | usac_data->x_ac_dec); |
274 | 19.5k | } |
275 | | |
276 | 19.1k | else { |
277 | 19.1k | WORD32 *ptr_temp = ptr_spec + start; |
278 | | |
279 | 19.1k | scale_spec = -scale_spec; |
280 | 19.1k | scale_spec = ixheaac_min32(scale_spec, 31); |
281 | | |
282 | 2.09M | for (i = size; i != 0; i--) { |
283 | 2.07M | *ptr_temp = *ptr_temp >> scale_spec; |
284 | 2.07M | ptr_temp++; |
285 | 2.07M | } |
286 | | |
287 | 19.1k | { |
288 | 19.1k | ixheaacd_tns_ar_filter_usac(&ptr_spec[shift], size, inc, lpc_coeff, |
289 | 19.1k | filt->order, scale_lpc, |
290 | 19.1k | usac_data->x_ac_dec); |
291 | 19.1k | } |
292 | | |
293 | 19.1k | { |
294 | 19.1k | ptr_temp = ptr_spec + start; |
295 | 19.1k | i = size; |
296 | | |
297 | 2.07M | do { |
298 | 2.07M | *ptr_temp = *ptr_temp << scale_spec; |
299 | 2.07M | ptr_temp++; |
300 | 2.07M | i--; |
301 | 2.07M | } while (i != 0); |
302 | 19.1k | } |
303 | 19.1k | } |
304 | | |
305 | 3.71M | for (i = start; i <= stop - 1; i++) { |
306 | 3.67M | spec[i] = ptr_spec[i]; |
307 | 3.67M | } |
308 | 38.6k | } |
309 | 99.9k | } |
310 | | |
311 | 799k | spec += pstr_sfb_info->bins_per_sbk; |
312 | 799k | } |
313 | 227k | return 0; |
314 | 227k | } |