• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright (C) 2023 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 #ifndef IXHEAACD_MPS_BASIC_OP_H
21 #define IXHEAACD_MPS_BASIC_OP_H
22 
23 #define NORM32 (0x40000000)
24 #define INV_SQRT_2_Q31 (1518500250)
25 #define Q_SQRT_TAB (15)
26 #define LOG2XQ17 (5171707904LL)
27 #define LOG_COEFF1 (27890)
28 #define LOG_COEFF2 (16262)
29 #define LOG_COEFF3 (7574)
30 #define LOG_COEFF4 (1786)
31 
32 #define TRIG_TABLE_CONV_FAC 326
33 
ixheaacd_mps_get_rshift_bits(WORD64 a)34 static PLATFORM_INLINE WORD32 ixheaacd_mps_get_rshift_bits(WORD64 a) {
35   WORD32 temp_1, temp_2;
36   temp_1 = (WORD32)(a >> 32);
37   temp_2 = ixheaacd_norm32(temp_1);
38   if (temp_2 < 31) {
39     return (32 - temp_2);
40   } else {
41     temp_2 = (WORD32)(a);
42     if ((temp_1 ^ temp_2) < 0) {
43       return 1;
44     } else {
45       return 0;
46     }
47   }
48 }
49 
ixheaacd_mps_narrow(WORD64 a,WORD16 * qfac)50 static PLATFORM_INLINE WORD32 ixheaacd_mps_narrow(WORD64 a, WORD16 *qfac) {
51   WORD32 x;
52   x = ixheaacd_mps_get_rshift_bits(a);
53   *qfac = 20 - x;
54   return (WORD32)((WORD64)a >> x);
55 }
56 
ixheaacd_mps_sqrt(WORD32 num,WORD16 * q,const WORD32 * sqrt_tab)57 static PLATFORM_INLINE WORD32 ixheaacd_mps_sqrt(WORD32 num, WORD16 *q, const WORD32 *sqrt_tab) {
58   WORD32 index, answer, temp;
59   WORD k;
60 
61   if (num == 0) return 0;
62 
63   k = ixheaacd_norm32(num);
64   temp = ixheaacd_shr32(ixheaacd_shl32(num, k), 21);
65   *q += k;
66   index = temp & 0x1FF;
67   answer = sqrt_tab[index];
68   if (*q & 1) {
69     *q -= 1;
70     answer = ixheaacd_mult32_shl(answer, INV_SQRT_2_Q31);
71   }
72   *q = *q >> 1;
73   *q += Q_SQRT_TAB;
74   return answer;
75 }
76 
ixheaacd_mps_reshape_add32(WORD32 op1,WORD32 op2,WORD16 * qop1,WORD16 qop2)77 static PLATFORM_INLINE WORD32 ixheaacd_mps_reshape_add32(WORD32 op1, WORD32 op2, WORD16 *qop1,
78                                                          WORD16 qop2) {
79   WORD64 tempresult;
80   if (0 == op2) {
81     return op1;
82   }
83   if (0 == op1) {
84     *qop1 = qop2;
85     return op2;
86   }
87   if (*qop1 < qop2) {
88     if ((qop2 - *qop1) > 31)
89       op2 = 0;
90     else
91       op2 = op2 >> (qop2 - *qop1);
92     tempresult = (WORD64)op1 + (WORD64)op2;
93   } else {
94     if ((*qop1 - qop2) > 31)
95       op1 = 0;
96     else
97       op1 = op1 >> (*qop1 - qop2);
98     *qop1 = qop2;
99     tempresult = (WORD64)op1 + (WORD64)op2;
100   }
101   if (tempresult > (WORD32)0x7fffffff || tempresult < (WORD32)0x80000000) {
102     tempresult = tempresult >> 1;
103     *qop1 -= 1;
104   }
105   return (WORD32)tempresult;
106 }
107 
ixheaacd_mps_add32(WORD32 a,WORD32 b,WORD16 * q_a,WORD16 q_b)108 static PLATFORM_INLINE WORD32 ixheaacd_mps_add32(WORD32 a, WORD32 b, WORD16 *q_a, WORD16 q_b) {
109   WORD64 temp_result;
110 
111   if (a == 0 || b == 0) {
112     if (b == 0) {
113       return a;
114     } else {
115       *q_a = q_b;
116       return b;
117     }
118   }
119   if (*q_a > q_b) {
120     if (((*q_a) - q_b) > 31) {
121       a = 0;
122       *q_a = q_b;
123     } else {
124       a = (a >> ((*q_a) - q_b));
125       *q_a = q_b;
126     }
127   } else {
128     if ((q_b - (*q_a)) > 31) {
129       b = 0;
130     } else {
131       b = (b >> (q_b - (*q_a)));
132       q_b = *q_a;
133     }
134   }
135   temp_result = (WORD64)a + (WORD64)b;
136   if (temp_result > (WORD32)0x7fffffff || temp_result < (WORD32)0x80000000) {
137     temp_result = temp_result >> 1;
138     *q_a -= 1;
139   }
140 
141   return (WORD32)temp_result;
142 }
143 
ixheaacd_mps_mult32(WORD32 a,WORD32 b,WORD16 * q_a,WORD16 q_b)144 static PLATFORM_INLINE WORD32 ixheaacd_mps_mult32(WORD32 a, WORD32 b, WORD16 *q_a, WORD16 q_b) {
145   WORD64 temp_result;
146   WORD32 temp;
147 
148   if (a == 0 || b == 0) {
149     temp_result = 0;
150     *q_a = 15;
151     return (WORD32)temp_result;
152   }
153 
154   *q_a = *q_a + q_b;
155 
156   temp_result = (WORD64)a * (WORD64)b;
157   temp = ixheaacd_mps_get_rshift_bits(temp_result);
158   if (0 != temp) {
159     *q_a -= temp;
160     temp_result = temp_result >> temp;
161   }
162 
163   return (WORD32)temp_result;
164 }
165 
ixheaacd_mps_mult32x32(WORD32 a,WORD32 b,WORD16 * q_a,WORD16 q_b)166 static PLATFORM_INLINE WORD32 ixheaacd_mps_mult32x32(WORD32 a, WORD32 b, WORD16 *q_a,
167                                                      WORD16 q_b) {
168   WORD64 temp_result;
169   if (a == 0 || b == 0) {
170     temp_result = 0;
171     *q_a = 15;
172     return (WORD32)temp_result;
173   }
174   *q_a = *q_a + q_b;
175 
176   temp_result = (WORD64)a * (WORD64)b;
177   while (temp_result > (WORD32)0x7fffffff || temp_result < (WORD32)0x80000000) {
178     temp_result = temp_result >> 1;
179     *q_a -= 1;
180   }
181 
182   return (WORD32)temp_result;
183 }
184 
ixheaacd_mps_mult32_shr_n(WORD32 a,WORD32 b,WORD16 n)185 static PLATFORM_INLINE WORD32 ixheaacd_mps_mult32_shr_n(WORD32 a, WORD32 b, WORD16 n) {
186   WORD32 result;
187   WORD64 temp_result;
188 
189   temp_result = (WORD64)a * (WORD64)b;
190   result = (WORD32)(temp_result >> n);
191 
192   return (result);
193 }
194 
ixheaacd_mps_mult32_shr_30(WORD32 a,WORD32 b)195 static PLATFORM_INLINE WORD32 ixheaacd_mps_mult32_shr_30(WORD32 a, WORD32 b) {
196   WORD32 result;
197   WORD64 temp_result;
198 
199   temp_result = (WORD64)a * (WORD64)b;
200   result = (WORD32)(temp_result >> 30);
201 
202   return (result);
203 }
204 
ixheaacd_mps_mult32_shr_16(WORD32 a,WORD32 b)205 static PLATFORM_INLINE WORD32 ixheaacd_mps_mult32_shr_16(WORD32 a, WORD32 b) {
206   WORD32 result;
207   WORD64 temp_result;
208 
209   temp_result = (WORD64)a * (WORD64)b;
210   result = (WORD32)(temp_result >> 16);
211   return (result);
212 }
213 
ixheaacd_mps_mult32x16_shr_16(WORD32 a,WORD32 b)214 static PLATFORM_INLINE WORD32 ixheaacd_mps_mult32x16_shr_16(WORD32 a, WORD32 b) {
215   WORD32 result;
216   WORD64 temp_result;
217   temp_result = (WORD64)a * (WORD64)b;
218   result = (WORD32)(temp_result >> 16);
219   return (result);
220 }
221 
ixheaacd_mps_mult32_shr_15(WORD32 a,WORD32 b)222 static PLATFORM_INLINE WORD32 ixheaacd_mps_mult32_shr_15(WORD32 a, WORD32 b) {
223   WORD32 result;
224   WORD64 temp_result;
225   temp_result = (WORD64)a * (WORD64)b;
226   result = (WORD32)(temp_result >> 15);
227 
228   return (result);
229 }
230 
ixheaacd_mps_mult32_shr_14(WORD32 a,WORD32 b)231 static PLATFORM_INLINE WORD32 ixheaacd_mps_mult32_shr_14(WORD32 a, WORD32 b) {
232   WORD32 result;
233   WORD64 temp_result;
234 
235   temp_result = (WORD64)a * (WORD64)b;
236   result = (WORD32)(temp_result >> 16);
237   result = result << 2;
238 
239   return (result);
240 }
241 
ixheaacd_mps_div_32(WORD32 a,WORD32 b,WORD16 * q_format)242 static PLATFORM_INLINE WORD32 ixheaacd_mps_div_32(WORD32 a, WORD32 b, WORD16 *q_format) {
243   WORD32 quotient;
244   UWORD32 mantissa_nr, mantissa_dr;
245   LOOPINDEX i;
246   WORD q_nr, q_dr;
247 
248   quotient = 0;
249 
250   if (0 == b) {
251     *q_format = 0;
252     return (a);
253   }
254 
255   quotient = 0;
256 
257   q_nr = ixheaacd_norm32(a);
258   mantissa_nr = (UWORD32)a << (q_nr);
259   q_dr = ixheaacd_norm32(b);
260   mantissa_dr = (UWORD32)b << (q_dr);
261   *q_format = (WORD)(30 + q_nr - q_dr);
262 
263   for (i = 0; i < 31; i++) {
264     quotient <<= 1;
265 
266     if (mantissa_nr >= mantissa_dr) {
267       mantissa_nr -= mantissa_dr;
268       quotient += 1;
269     }
270     mantissa_nr <<= 1;
271   }
272 
273   if ((a ^ b) < 0) {
274     return -(quotient);
275   }
276 
277   return quotient;
278 }
279 
ixheaacd_mps_convert_to_qn(WORD32 temp,WORD16 qtemp,WORD16 n)280 static WORD32 ixheaacd_mps_convert_to_qn(WORD32 temp, WORD16 qtemp, WORD16 n) {
281   WORD64 result;
282   if (qtemp == n)
283     return temp;
284   else if (qtemp > n)
285     temp = (WORD32)((WORD64)temp >> (qtemp - n));
286   else {
287     result = (WORD32)((WORD64)temp << (n - qtemp));
288     if (result > (WORD32)0x7fffffff || result < (WORD32)0x80000000) {
289       return 0;
290     } else
291       temp = (WORD32)result;
292   }
293   return temp;
294 }
295 
ixheaacd_mps_div32_in_q15(WORD32 num,WORD32 den)296 static PLATFORM_INLINE WORD32 ixheaacd_mps_div32_in_q15(WORD32 num, WORD32 den) {
297   WORD32 quotient;
298   WORD16 q_quotient;
299 
300   quotient = ixheaacd_mps_div_32(num, den, &q_quotient);
301   quotient = ixheaacd_mps_convert_to_qn(quotient, q_quotient, 15);
302   return quotient;
303 }
304 
ixheaacd_mps_log10(WORD32 a,WORD16 q_a)305 static PLATFORM_INLINE WORD32 ixheaacd_mps_log10(WORD32 a, WORD16 q_a) {
306   WORD32 x;
307   WORD16 q_x;
308   WORD32 j, k, temp;
309   WORD16 q_num;
310   q_num = ixheaacd_norm32(a);
311   a = a << q_num;
312   x = ixheaacd_mps_div_32(a, NORM32, &q_x);
313 
314   if (q_x > 16)
315     x = x >> (q_x - 16);
316   else
317     x = x << (16 - q_x);
318 
319   q_num = 30 - (q_num + q_a);
320 
321   j = x - ONE_IN_Q16;
322   k = ixheaacd_mps_mult32_shr_16(SQRT_THREE_Q15, j);
323   temp = ixheaacd_mps_mult32_shr_16(j, j);
324   k -= ixheaacd_mps_mult32_shr_16(LOG_COEFF1, temp);
325   temp = ixheaacd_mps_mult32_shr_16(temp, j);
326   k += ixheaacd_mps_mult32_shr_16(LOG_COEFF2, temp);
327   temp = ixheaacd_mps_mult32_shr_16(temp, j);
328   k -= ixheaacd_mps_mult32_shr_16(LOG_COEFF3, temp);
329   temp = ixheaacd_mps_mult32_shr_16(temp, j);
330   k += ixheaacd_mps_mult32_shr_16(LOG_COEFF4, temp);
331 
332   k += (WORD32)(q_num * ((WORD32)LOG2XQ17));
333 
334   return (k >> 1);
335 }
336 
ixheaacd_mps_cos(WORD32 a,const WORD32 * cosine_tab)337 static PLATFORM_INLINE WORD32 ixheaacd_mps_cos(WORD32 a, const WORD32 *cosine_tab) {
338   WORD32 temp_result;
339 
340   if (a < 0) {
341     a = -a;
342   }
343 
344   a = a % TWO_PI_IN_Q15;
345 
346   temp_result = cosine_tab[((a * TRIG_TABLE_CONV_FAC) >> 15)];
347   return temp_result;
348 }
349 
ixheaacd_mps_sin(WORD32 a,const WORD32 * sine_tab)350 static PLATFORM_INLINE WORD32 ixheaacd_mps_sin(WORD32 a, const WORD32 *sine_tab) {
351   WORD32 temp_result, flag = 0;
352 
353   if (a < 0) {
354     a = -a;
355     flag = 1;
356   }
357 
358   a = a % TWO_PI_IN_Q15;
359 
360   temp_result = sine_tab[((a * TRIG_TABLE_CONV_FAC) >> 15)];
361   if (flag) temp_result = -temp_result;
362 
363   return temp_result;
364 }
365 
ixheaacd_mps_comp(WORD32 a,WORD32 b,WORD16 * q_a,WORD16 q_b)366 static PLATFORM_INLINE WORD32 ixheaacd_mps_comp(WORD32 a, WORD32 b, WORD16 *q_a, WORD16 q_b) {
367   if (a == 0 || b == 0) {
368     if (a == 0) {
369       if (b < 0)
370         return 1;
371       else
372         return 0;
373     } else if (b == 0) {
374       if (a > 0)
375         return 1;
376       else
377         return 0;
378     }
379   }
380 
381   if (*q_a > q_b) {
382     a = (a >> ((*q_a) - q_b));
383   } else {
384     b = (b >> (q_b - (*q_a)));
385   }
386 
387   if (a > b)
388     return 1;
389   else
390     return 0;
391 }
392 
393 #endif /* IXHEAACD_MPS_BASIC_OP_H */
394