You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
5.5 KiB
191 lines
5.5 KiB
/******************************************************************************
|
|
* *
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*****************************************************************************
|
|
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
|
*/
|
|
#include "ixheaacd_sbr_common.h"
|
|
#include "ixheaacd_type_def.h"
|
|
|
|
#include "ixheaacd_constants.h"
|
|
#include "ixheaacd_basic_ops32.h"
|
|
#include "ixheaacd_basic_ops16.h"
|
|
#include "ixheaacd_basic_ops40.h"
|
|
#include "ixheaacd_basic_op.h"
|
|
#include "ixheaacd_basic_ops.h"
|
|
#include "ixheaacd_intrinsics.h"
|
|
#include "ixheaacd_common_rom.h"
|
|
#include "ixheaacd_basic_funcs.h"
|
|
|
|
#define sat16_m(a) ixheaacd_sat16(a)
|
|
|
|
VOID ixheaacd_fix_mant_exp_add(WORD16 op1_mant, WORD16 op1_exp, WORD16 op2_mant,
|
|
WORD16 op2_exp, WORD16 *ptr_result_mant,
|
|
WORD16 *ptr_result_exp) {
|
|
WORD32 new_mant;
|
|
WORD32 new_exp;
|
|
new_exp = op1_exp - op2_exp;
|
|
if (new_exp < 0) {
|
|
op1_mant = op1_mant >> (-new_exp);
|
|
new_exp = op2_exp;
|
|
} else {
|
|
op2_mant = op2_mant >> new_exp;
|
|
new_exp = op1_exp;
|
|
}
|
|
|
|
new_mant = op1_mant + op2_mant;
|
|
|
|
if (ixheaacd_abs32(new_mant) >= 0x8000) {
|
|
new_mant = new_mant >> 1;
|
|
new_exp++;
|
|
}
|
|
|
|
*ptr_result_mant = new_mant;
|
|
*ptr_result_exp = (WORD16)(new_exp);
|
|
}
|
|
|
|
WORD32 ixheaacd_fix_mant_div(WORD16 op1_mant, WORD16 op2_mant,
|
|
WORD16 *ptr_result_mant,
|
|
ixheaacd_misc_tables *pstr_common_tables)
|
|
|
|
{
|
|
WORD32 pre_shift_val, post_shift_val;
|
|
WORD32 index;
|
|
WORD16 one_by_op2_mant;
|
|
|
|
pre_shift_val = ixheaacd_norm32(op2_mant) - 16;
|
|
|
|
index = (op2_mant << pre_shift_val) >> (SHORT_BITS - 3 - 8);
|
|
|
|
index &= (1 << (8 + 1)) - 1;
|
|
|
|
if (index == 0) {
|
|
post_shift_val = ixheaacd_norm32(op1_mant) - 16;
|
|
|
|
*ptr_result_mant = (op1_mant << post_shift_val);
|
|
} else {
|
|
WORD32 ratio_m;
|
|
|
|
index = ((index - 1) >> 1);
|
|
|
|
one_by_op2_mant = pstr_common_tables->inv_table[index];
|
|
|
|
ratio_m = ixheaacd_mult16x16in32(one_by_op2_mant, op1_mant);
|
|
|
|
post_shift_val = ixheaacd_norm32(ratio_m) - 1;
|
|
|
|
*ptr_result_mant = (WORD16)((ratio_m << post_shift_val) >> 15);
|
|
}
|
|
return (pre_shift_val - post_shift_val);
|
|
}
|
|
|
|
VOID ixheaacd_fix_mant_exp_sqrt(WORD16 *ptr_in_out, WORD16 *sqrt_table) {
|
|
WORD32 index;
|
|
WORD32 pre_shift_val;
|
|
WORD32 op_mant = *ptr_in_out;
|
|
WORD32 op_exp = *(ptr_in_out + 1);
|
|
WORD32 result_m;
|
|
WORD32 result_e;
|
|
|
|
if (op_mant > 0) {
|
|
pre_shift_val = (ixheaacd_norm32((WORD16)op_mant) - 16);
|
|
op_exp = (op_exp - pre_shift_val);
|
|
index = (op_mant << pre_shift_val) >> (SHORT_BITS - 3 - 8);
|
|
index &= (1 << (8 + 1)) - 1;
|
|
result_m = sqrt_table[index >> 1];
|
|
if ((op_exp & 1) != 0) {
|
|
result_m = (result_m * 0x5a82) >> 16;
|
|
op_exp += 3;
|
|
}
|
|
result_e = (op_exp >> 1);
|
|
|
|
} else {
|
|
result_m = 0;
|
|
result_e = -SHORT_BITS;
|
|
}
|
|
|
|
*ptr_in_out++ = (WORD16)result_m;
|
|
*ptr_in_out = (WORD16)result_e;
|
|
}
|
|
|
|
WORD32 ixheaacd_fix_div_dec(WORD32 op1, WORD32 op2) {
|
|
WORD32 quotient = 0;
|
|
UWORD32 abs_num, abs_den;
|
|
WORD32 k;
|
|
WORD32 sign;
|
|
|
|
abs_num = ixheaacd_abs32(op1 >> 1);
|
|
abs_den = ixheaacd_abs32(op2 >> 1);
|
|
sign = op1 ^ op2;
|
|
|
|
if (abs_num != 0) {
|
|
for (k = 15; k > 0; k--) {
|
|
quotient = (quotient << 1);
|
|
abs_num = (abs_num << 1);
|
|
if (abs_num >= abs_den) {
|
|
abs_num -= abs_den;
|
|
quotient++;
|
|
}
|
|
}
|
|
}
|
|
if (sign < 0) quotient = -(quotient);
|
|
|
|
return quotient;
|
|
}
|
|
|
|
#define ONE_IN_Q30 0x40000000
|
|
|
|
static PLATFORM_INLINE WORD32 ixheaacd_one_by_sqrt_calc(WORD32 op) {
|
|
WORD32 a = ixheaacd_add32_sat(0x900ebee0,
|
|
ixheaacd_mult32x16in32_shl_sat(op, 0x39d9));
|
|
WORD32 iy =
|
|
ixheaacd_add32_sat(0x573b645a, ixheaacd_mult32x16h_in32_shl_sat(op, a));
|
|
|
|
iy = ixheaacd_shl32_dir_sat_limit(iy, 1);
|
|
|
|
a = ixheaacd_mult32_shl_sat(op, iy);
|
|
a = ixheaacd_sub32_sat(ONE_IN_Q30, ixheaacd_shl32_dir_sat_limit(
|
|
ixheaacd_mult32_shl_sat(a, iy), 1));
|
|
iy = ixheaacd_add32_sat(iy, ixheaacd_mult32_shl_sat(a, iy));
|
|
|
|
a = ixheaacd_mult32_shl_sat(op, iy);
|
|
a = ixheaacd_sub32_sat(ONE_IN_Q30, ixheaacd_shl32_dir_sat_limit(
|
|
ixheaacd_mult32_shl_sat(a, iy), 1));
|
|
iy = ixheaacd_add32_sat(iy, ixheaacd_mult32_shl_sat(a, iy));
|
|
|
|
a = ixheaacd_mult32_shl_sat(op, iy);
|
|
a = ixheaacd_sub32_sat(ONE_IN_Q30, ixheaacd_shl32_dir_sat_limit(
|
|
ixheaacd_mult32_shl_sat(a, iy), 1));
|
|
iy = ixheaacd_add32_sat(iy, ixheaacd_mult32_shl_sat(a, iy));
|
|
|
|
return iy;
|
|
}
|
|
|
|
WORD32 ixheaacd_sqrt(WORD32 op) {
|
|
WORD32 result = 0;
|
|
WORD16 shift;
|
|
|
|
if (op != 0) {
|
|
shift = (WORD16)(ixheaacd_norm32(op) & ~1);
|
|
op = ixheaacd_shl32_dir_sat_limit(op, shift);
|
|
shift = ixheaacd_shr32_dir_sat_limit(shift, 1);
|
|
op = ixheaacd_mult32_shl_sat(ixheaacd_one_by_sqrt_calc(op), op);
|
|
result = ixheaacd_shr32_dir_sat_limit(op, ixheaacd_sat16(shift - 1));
|
|
}
|
|
|
|
return result;
|
|
}
|