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 "ixheaacd_sbr_common.h" 21 #include <ixheaacd_type_def.h> 22 23 #include "ixheaacd_constants.h" 24 #include <ixheaacd_basic_ops32.h> 25 #include <ixheaacd_basic_ops16.h> 26 #include <ixheaacd_basic_ops40.h> 27 #include <ixheaacd_basic_ops.h> 28 29 #include <ixheaacd_basic_op.h> 30 #include "ixheaacd_intrinsics.h" 31 #include "ixheaacd_common_rom.h" 32 #include "ixheaacd_basic_funcs.h" 33 34 #define sat16_m(a) ixheaacd_sat16(a) 35 36 VOID ixheaacd_fix_mant_exp_add(WORD16 op1_mant, WORD16 op1_exp, WORD16 op2_mant, 37 WORD16 op2_exp, WORD16 *ptr_result_mant, 38 WORD16 *ptr_result_exp) { 39 WORD32 new_mant; 40 WORD32 new_exp; 41 new_exp = op1_exp - op2_exp; 42 if (new_exp < 0) { 43 op1_mant = op1_mant >> (-new_exp); 44 new_exp = op2_exp; 45 } else { 46 op2_mant = op2_mant >> new_exp; 47 new_exp = op1_exp; 48 } 49 50 new_mant = op1_mant + op2_mant; 51 52 if (ixheaacd_abs32(new_mant) >= 0x8000) { 53 new_mant = new_mant >> 1; 54 new_exp++; 55 } 56 57 *ptr_result_mant = new_mant; 58 *ptr_result_exp = (WORD16)(new_exp); 59 } 60 61 WORD32 ixheaacd_fix_mant_div(WORD16 op1_mant, WORD16 op2_mant, 62 WORD16 *ptr_result_mant, 63 ixheaacd_misc_tables *pstr_common_tables) 64 65 { 66 WORD32 pre_shift_val, post_shift_val; 67 WORD32 index; 68 WORD16 one_by_op2_mant; 69 70 pre_shift_val = ixheaacd_norm32(op2_mant) - 16; 71 72 index = (op2_mant << pre_shift_val) >> (SHORT_BITS - 3 - 8); 73 74 index &= (1 << (8 + 1)) - 1; 75 76 if (index == 0) { 77 post_shift_val = ixheaacd_norm32(op1_mant) - 16; 78 79 *ptr_result_mant = (op1_mant << post_shift_val); 80 } else { 81 WORD32 ratio_m; 82 83 index = ((index - 1) >> 1); 84 85 one_by_op2_mant = pstr_common_tables->inv_table[index]; 86 87 ratio_m = ixheaacd_mult16x16in32(one_by_op2_mant, op1_mant); 88 89 post_shift_val = ixheaacd_norm32(ratio_m) - 1; 90 91 *ptr_result_mant = (WORD16)((ratio_m << post_shift_val) >> 15); 92 } 93 return (pre_shift_val - post_shift_val); 94 } 95 96 VOID ixheaacd_fix_mant_exp_sqrt(WORD16 *ptr_in_out, WORD16 *sqrt_table) { 97 WORD32 index; 98 WORD32 pre_shift_val; 99 WORD32 op_mant = *ptr_in_out; 100 WORD32 op_exp = *(ptr_in_out + 1); 101 WORD32 result_m; 102 WORD32 result_e; 103 104 if (op_mant > 0) { 105 pre_shift_val = (ixheaacd_norm32((WORD16)op_mant) - 16); 106 op_exp = (op_exp - pre_shift_val); 107 index = (op_mant << pre_shift_val) >> (SHORT_BITS - 3 - 8); 108 index &= (1 << (8 + 1)) - 1; 109 result_m = sqrt_table[index >> 1]; 110 if ((op_exp & 1) != 0) { 111 result_m = (result_m * 0x5a82) >> 16; 112 op_exp += 3; 113 } 114 result_e = (op_exp >> 1); 115 116 } else { 117 result_m = 0; 118 result_e = -SHORT_BITS; 119 } 120 121 *ptr_in_out++ = (WORD16)result_m; 122 *ptr_in_out = (WORD16)result_e; 123 } 124 125 WORD32 ixheaacd_fix_div_dec(WORD32 op1, WORD32 op2) { 126 WORD32 quotient = 0; 127 UWORD32 abs_num, abs_den; 128 WORD32 k; 129 WORD32 sign; 130 131 abs_num = ixheaacd_abs32(op1 >> 1); 132 abs_den = ixheaacd_abs32(op2 >> 1); 133 sign = op1 ^ op2; 134 135 if (abs_num != 0) { 136 for (k = 15; k > 0; k--) { 137 quotient = (quotient << 1); 138 abs_num = (abs_num << 1); 139 if (abs_num >= abs_den) { 140 abs_num -= abs_den; 141 quotient++; 142 } 143 } 144 } 145 if (sign < 0) quotient = -(quotient); 146 147 return quotient; 148 } 149 150 #define ONE_IN_Q30 0x40000000 151 152 static PLATFORM_INLINE WORD32 ixheaacd_one_by_sqrt_calc(WORD32 op) { 153 WORD32 a = ixheaacd_add32_sat(0x900ebee0, 154 ixheaacd_mult32x16in32_shl_sat(op, 0x39d9)); 155 WORD32 iy = 156 ixheaacd_add32_sat(0x573b645a, ixheaacd_mult32x16h_in32_shl_sat(op, a)); 157 158 iy = ixheaacd_shl32_dir_sat_limit(iy, 1); 159 160 a = ixheaacd_mult32_shl_sat(op, iy); 161 a = ixheaacd_sub32_sat(ONE_IN_Q30, ixheaacd_shl32_dir_sat_limit( 162 ixheaacd_mult32_shl_sat(a, iy), 1)); 163 iy = ixheaacd_add32_sat(iy, ixheaacd_mult32_shl_sat(a, iy)); 164 165 a = ixheaacd_mult32_shl_sat(op, iy); 166 a = ixheaacd_sub32_sat(ONE_IN_Q30, ixheaacd_shl32_dir_sat_limit( 167 ixheaacd_mult32_shl_sat(a, iy), 1)); 168 iy = ixheaacd_add32_sat(iy, ixheaacd_mult32_shl_sat(a, iy)); 169 170 a = ixheaacd_mult32_shl_sat(op, iy); 171 a = ixheaacd_sub32_sat(ONE_IN_Q30, ixheaacd_shl32_dir_sat_limit( 172 ixheaacd_mult32_shl_sat(a, iy), 1)); 173 iy = ixheaacd_add32_sat(iy, ixheaacd_mult32_shl_sat(a, iy)); 174 175 return iy; 176 } 177 178 WORD32 ixheaacd_sqrt(WORD32 op) { 179 WORD32 result = 0; 180 WORD16 shift; 181 182 if (op != 0) { 183 shift = (WORD16)(ixheaacd_norm32(op) & ~1); 184 op = ixheaacd_shl32_dir_sat_limit(op, shift); 185 shift = ixheaacd_shr32_dir_sat_limit(shift, 1); 186 op = ixheaacd_mult32_shl_sat(ixheaacd_one_by_sqrt_calc(op), op); 187 result = ixheaacd_shr32_dir_sat_limit(op, ixheaacd_sat16(shift - 1)); 188 } 189 190 return result; 191 } 192