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