xref: /aosp_15_r20/external/libxaac/decoder/ixheaacd_tns.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
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