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