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 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 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 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 181 VOID ixheaacd_tns_apply(ia_usac_data_struct *usac_data, WORD32 *spec, 182 WORD32 nbands, ia_sfb_info_struct *pstr_sfb_info, 183 ia_tns_frame_info_struct *pstr_tns) { 184 WORD32 f, max_order, start, stop, size, inc; 185 WORD32 n_filt, coef_res, order, direction; 186 WORD32 *ptr_spec; 187 WORD32 scale_spec; 188 WORD32 scale_lpc; 189 WORD32 guard_band; 190 WORD32 shift; 191 WORD32 lpc_coeff[TNS_MAX_ORDER + 1]; 192 WORD32 par_coeff[TNS_MAX_ORDER + 1]; 193 ia_tns_filter_struct *filt; 194 195 const WORD16 *sfb_top; 196 197 WORD32 nbins = (pstr_sfb_info->islong) ? 1024 : 128; 198 WORD32 i, j, idx; 199 200 max_order = (pstr_sfb_info->islong) ? 15 : 7; 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 > max_order) { 226 fprintf(stderr, "Error in tns max order: %d %d\n", order, max_order); 227 } 228 229 if (!order) continue; 230 231 ixheaacd_tns_dec_coef_usac(usac_data, filt, coef_res, 232 (WORD32 *)par_coeff); 233 234 ixheaacd_tns_parcor_lpc_convert_usac(par_coeff, lpc_coeff, &scale_lpc, 235 filt->order); 236 237 tmp = (*usac_data->tns_max_bands_tbl_usac)[usac_data->sampling_rate_idx] 238 [idx]; 239 240 start = ixheaacd_min32(start, tmp); 241 242 start = ixheaacd_min32(start, nbands); 243 start = sfb_offset(start); 244 245 stop = ixheaacd_min32(stop, tmp); 246 stop = ixheaacd_min32(stop, nbands); 247 stop = sfb_offset(stop); 248 249 guard_band = 31 - ixheaacd_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 = ixheaacd_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 } 314