Home | History | Annotate | Download | only in decoder
      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