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 <stdlib.h> 21 #include <string.h> 22 #include <math.h> 23 24 #include <ixheaacd_type_def.h> 25 #include "ixheaacd_bitbuffer.h" 26 #include "ixheaacd_interface.h" 27 #include "ixheaacd_tns_usac.h" 28 #include "ixheaacd_cnst.h" 29 #include "ixheaacd_acelp_info.h" 30 #include "ixheaacd_td_mdct.h" 31 #include "ixheaacd_sbrdecsettings.h" 32 #include "ixheaacd_info.h" 33 #include "ixheaacd_sbr_common.h" 34 #include "ixheaacd_drc_data_struct.h" 35 #include "ixheaacd_drc_dec.h" 36 #include "ixheaacd_sbrdecoder.h" 37 #include "ixheaacd_mps_polyphase.h" 38 #include "ixheaacd_sbr_const.h" 39 #include "ixheaacd_main.h" 40 #include "ixheaacd_arith_dec.h" 41 #include "ixheaacd_windows.h" 42 #include "ixheaacd_constants.h" 43 #include <ixheaacd_type_def.h> 44 #include <ixheaacd_basic_ops32.h> 45 #include <ixheaacd_basic_ops40.h> 46 #include "ixheaacd_func_def.h" 47 #include "ixheaacd_acelp_com.h" 48 49 static PLATFORM_INLINE WORD32 ixheaacd_mult32_m(WORD32 a, WORD32 b) { 50 WORD32 result; 51 WORD64 temp_result; 52 53 temp_result = (WORD64)a * (WORD64)b; 54 result = (WORD32)(temp_result >> 31); 55 56 return (result); 57 } 58 59 static VOID ixheaacd_weighted_synthesis_filter(WORD32 *a, WORD32 *ap) { 60 WORD32 f; 61 WORD32 i; 62 ap[0] = a[0]; 63 f = IGAMMA1; 64 for (i = 1; i <= ORDER; i++) { 65 ap[i] = ixheaacd_mult32_m(f, a[i]); 66 f = ixheaacd_mult32_m(f, IGAMMA1); 67 } 68 return; 69 } 70 71 static VOID ixheaacd_synthesis_tool(WORD32 a[], WORD32 x[], WORD32 l, 72 WORD32 qshift, WORD32 *preshift) { 73 WORD32 s; 74 WORD32 i, j; 75 76 for (i = 0; i < l; i++) { 77 s = x[i]; 78 for (j = 1; j <= ORDER; j += 4) { 79 s = ixheaacd_sub32_sat( 80 s, ixheaacd_mul32_sh(a[j], x[i - j], (WORD8)(qshift))); 81 s = ixheaacd_sub32_sat( 82 s, ixheaacd_mul32_sh(a[j + 1], x[i - (j + 1)], (WORD8)(qshift))); 83 s = ixheaacd_sub32_sat( 84 s, ixheaacd_mul32_sh(a[j + 2], x[i - (j + 2)], (WORD8)(qshift))); 85 s = ixheaacd_sub32_sat( 86 s, ixheaacd_mul32_sh(a[j + 3], x[i - (j + 3)], (WORD8)(qshift))); 87 } 88 x[i] = s; 89 } 90 91 (*preshift)++; 92 return; 93 } 94 95 WORD32 ixheaacd_fwd_alias_cancel_tool( 96 ia_usac_data_struct *usac_data, ia_td_frame_data_struct *pstr_td_frame_data, 97 WORD32 fac_length, FLOAT32 *lp_filt_coeff, WORD32 gain) { 98 WORD32 i; 99 FLOAT32 lp_filt_coeff_a[ORDER + 1]; 100 WORD32 qshift = 0; 101 WORD32 err = 0; 102 103 WORD32 *x_in = pstr_td_frame_data->fac_data; 104 WORD32 *ptr_scratch = &usac_data->scratch_buffer[0]; 105 WORD32 *fac_signal = &usac_data->x_ac_dec[16]; 106 FLOAT32 fac_signal_flt[128 + 16]; 107 FLOAT32 *ptr_fac_signal_flt = &fac_signal_flt[16]; 108 WORD32 *ptr_overlap_buf = 109 &(usac_data->overlap_data_ptr[usac_data->present_chan] 110 [(usac_data->ccfl / 2) - fac_length]); 111 112 memset(fac_signal - 16, 0, ORDER * sizeof(WORD32)); 113 114 err = ixheaacd_acelp_mdct(x_in, fac_signal, &qshift, fac_length, ptr_scratch); 115 if (err == -1) return err; 116 117 ixheaacd_lpc_coeff_wt_apply(lp_filt_coeff, lp_filt_coeff_a); 118 119 for (i = 0; i < fac_length; i++) 120 ptr_fac_signal_flt[i] = 121 (FLOAT32)((FLOAT32)fac_signal[i] / (1 << (16 - qshift))); 122 123 memset(ptr_fac_signal_flt - 16, 0, 16 * sizeof(FLOAT32)); 124 125 ixheaacd_synthesis_tool_float1(lp_filt_coeff_a, ptr_fac_signal_flt, 126 fac_length); 127 128 for (i = 0; i < fac_length; i++) 129 fac_signal[i] = (WORD32)(ptr_fac_signal_flt[i] * (1 << (16 - qshift))); 130 131 for (i = 0; i < fac_length; i++) 132 ptr_overlap_buf[i] = ixheaacd_add32_sat( 133 ptr_overlap_buf[i], 134 (WORD32)ixheaacd_mul32_sh(fac_signal[i], gain, (WORD8)(16 - qshift))); 135 136 return err; 137 } 138 139 WORD32 ixheaacd_fr_alias_cnx_fix(WORD32 *x_in, WORD32 len, WORD32 fac_length, 140 WORD32 *lp_filt_coeff, WORD32 *izir, 141 WORD32 *fac_data_out, WORD8 *qshift1, 142 WORD8 qshift2, WORD8 qshift3, WORD32 *preshift, 143 WORD32 *ptr_scratch) { 144 WORD32 i; 145 const WORD32 *sine_window; 146 WORD32 fac_window[2 * FAC_LENGTH]; 147 WORD32 lp_filt_coeff_a[ORDER + 1]; 148 WORD32 err = 0; 149 150 if (fac_length == 48) { 151 sine_window = ixheaacd_sine_win_96; 152 } else if (fac_length == 64) { 153 sine_window = ixheaacd_sine_win_128; 154 } else if (fac_length == 96) { 155 sine_window = ixheaacd_sine_win_192; 156 } else { 157 sine_window = ixheaacd_sine_win_256; 158 } 159 if (FAC_LENGTH < fac_length) { 160 return -1; 161 } 162 163 if (FAC_LENGTH < fac_length) { 164 return -1; 165 } 166 if ((1 + (len / 2)) < (fac_length + 1)) { 167 return -1; 168 } 169 if ((len / 2 + 1) > (2 * LEN_FRAME - fac_length - 1)) { 170 return -1; 171 } 172 173 if (lp_filt_coeff != NULL && fac_data_out != NULL) { 174 memset(fac_data_out - 16, 0, ORDER * sizeof(WORD32)); 175 err = ixheaacd_acelp_mdct(x_in, fac_data_out, preshift, fac_length, 176 ptr_scratch); 177 if (err == -1) return err; 178 179 ixheaacd_weighted_synthesis_filter(lp_filt_coeff, lp_filt_coeff_a); 180 181 memset(fac_data_out + fac_length, 0, fac_length * sizeof(WORD32)); 182 183 ixheaacd_synthesis_tool(lp_filt_coeff_a, fac_data_out, 2 * fac_length, 184 qshift2, preshift); 185 186 if (izir != NULL) { 187 for (i = 0; i < fac_length; i++) { 188 fac_window[i] = ixheaacd_mult32_m( 189 sine_window[i], sine_window[(2 * fac_length) - 1 - i]); 190 fac_window[fac_length + i] = 191 2147483647 - ixheaacd_mult32_m(sine_window[fac_length + i], 192 sine_window[fac_length + i]); 193 } 194 for (i = 0; i < fac_length; i++) { 195 WORD32 temp1; 196 WORD32 temp2; 197 198 temp1 = ixheaacd_mul32_sh( 199 izir[1 + (len / 2) + i], fac_window[fac_length + i], 200 (char)((qshift3 - *qshift1 + 31 + (WORD8)(*preshift)))); 201 202 temp2 = ixheaacd_mul32_sh( 203 izir[1 + (len / 2) - 1 - i], fac_window[fac_length - 1 - i], 204 (char)((qshift3 - *qshift1 + 31 + (WORD8)(*preshift)))); 205 206 fac_data_out[i] = 207 ixheaacd_add32_sat3((fac_data_out[i] / 2), temp1, temp2); 208 209 fac_data_out[fac_length + i] = (fac_data_out[fac_length + i] / 2); 210 } 211 } 212 } 213 214 return err; 215 } 216