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