1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2020 Google LLC. All rights reserved.
4 *
5 * Author: Pin-chih Lin <johnylin@google.com>
6 */
7 #ifndef __SOF_AUDIO_DRC_DRC_MATH_H__
8 #define __SOF_AUDIO_DRC_DRC_MATH_H__
9
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <sof/audio/drc/drc_plat_conf.h>
13 #include <sof/audio/format.h>
14 #include <sof/math/numbers.h>
15 #include <sof/math/trig.h>
16
17 /* Unmark this define to use cordic arc sine implementation. */
18 /* #define DRC_USE_CORDIC_ASIN */
19
20 #if DRC_HIFI3
21
22 #include <xtensa/tie/xt_hifi3.h>
23
24 #define PI_OVER_TWO_Q30 1686629713 /* Q_CONVERT_FLOAT(1.57079632679489661923, 30); pi/2 */
25 #define TWO_OVER_PI_Q30 683565248 /* Q_CONVERT_FLOAT(0.63661977236758134, 30); 2/pi */
26
27 /*
28 * A substitutive function of Q_MULTSR_32X32(a, b, qa, qb, qy) in HIFI manners.
29 *
30 * In AE_MULF32R, it takes the multiplication of 1.31 and 1.31 to 17.47, which means it does
31 * right-shift 15 bits. Let's consider a is .qa, b is .qb, then tmp will be .(qa+qb-15)
32 * In AE_ROUND32F48SSYM, it rounds 17.47 to 1.31, equally right-shifts 16 bits. Let's consider the
33 * output is .qy, then tmp here needs to be .(qy+16)
34 * If we set the left-shift bit from the former tmp to the latter tmp as "lshift", then:
35 * (qa+qb-15) + lshift = (qy+16)
36 * lshift = qy-qa-qb+31
37 */
drc_mult_lshift(int32_t a,int32_t b,int32_t lshift)38 static inline int32_t drc_mult_lshift(int32_t a, int32_t b, int32_t lshift)
39 {
40 ae_f64 tmp;
41 ae_f32 y;
42
43 tmp = AE_MULF32R_LL(a, b);
44 tmp = AE_SLAA64S(tmp, lshift);
45 y = AE_ROUND32F48SSYM(tmp);
46 return y;
47 }
48
drc_get_lshift(int32_t qa,int32_t qb,int32_t qy)49 static inline int32_t drc_get_lshift(int32_t qa, int32_t qb, int32_t qy)
50 {
51 return qy - qa - qb + 31;
52 }
53
54 /*
55 * Input is Q2.30: (-2.0, 2.0)
56 * Output range: (-1.0, 1.0); regulated to Q1.31: (-1.0, 1.0)
57 */
drc_sin_fixed(int32_t x)58 static inline int32_t drc_sin_fixed(int32_t x)
59 {
60 const int32_t lshift = drc_get_lshift(30, 30, 28);
61 int32_t denorm_x = drc_mult_lshift(x, PI_OVER_TWO_Q30, lshift);
62 int32_t sin_val = sin_fixed_16b(denorm_x);
63
64 return sin_val << 16;
65 }
66
67 #ifdef DRC_USE_CORDIC_ASIN
68 /*
69 * Input is Q2.30; valid range: [-1.0, 1.0]
70 * Output range: [-1.0, 1.0]; regulated to Q2.30: (-2.0, 2.0)
71 */
drc_asin_fixed(int32_t x)72 static inline int32_t drc_asin_fixed(int32_t x)
73 {
74 const int32_t lshift = drc_get_lshift(30, 30, 30);
75 int32_t asin_val = asin_fixed_16b(x); /* Q2.14, [-pi/2, pi/2] */
76
77 return drc_mult_lshift(asin_val << 16, TWO_OVER_PI_Q30, lshift);
78 }
79 #endif /* DRC_USE_CORDIC_ASIN */
80
81 #else
82
83 /*
84 * Input is Q2.30: (-2.0, 2.0)
85 * Output range: (-1.0, 1.0); regulated to Q1.31: (-1.0, 1.0)
86 */
drc_sin_fixed(int32_t x)87 static inline int32_t drc_sin_fixed(int32_t x)
88 {
89 const int32_t PI_OVER_TWO = Q_CONVERT_FLOAT(1.57079632679489661923, 30);
90 int32_t sin_val = sin_fixed_16b(Q_MULTSR_32X32((int64_t)x, PI_OVER_TWO, 30, 30, 28));
91
92 return sin_val << 16;
93 }
94
95 #ifdef DRC_USE_CORDIC_ASIN
96 /*
97 * Input is Q2.30; valid range: [-1.0, 1.0]
98 * Output range: [-1.0, 1.0]; regulated to Q2.30: (-2.0, 2.0)
99 */
drc_asin_fixed(int32_t x)100 static inline int32_t drc_asin_fixed(int32_t x)
101 {
102 const int32_t TWO_OVER_PI = Q_CONVERT_FLOAT(0.63661977236758134, 30); /* 2/pi */
103 int32_t asin_val = asin_fixed_16b(x); /* Q2.14, [-pi/2, pi/2] */
104
105 return Q_MULTSR_32X32((int64_t)asin_val, TWO_OVER_PI, 14, 30, 30);
106 }
107 #endif /* DRC_USE_CORDIC_ASIN */
108
109 #endif /* DRC_HIFI3 */
110
111 int32_t drc_lin2db_fixed(int32_t linear); /* Input:Q6.26 Output:Q11.21 */
112 int32_t drc_log_fixed(int32_t x); /* Input:Q6.26 Output:Q6.26 */
113 int32_t drc_pow_fixed(int32_t x, int32_t y); /* Input:Q6.26, Q2.30 Output:Q12.20 */
114 int32_t drc_inv_fixed(int32_t x, int32_t precision_x, int32_t precision_y);
115
116 #ifndef DRC_USE_CORDIC_ASIN
117 int32_t drc_asin_fixed(int32_t x); /* Input:Q2.30 Output:Q2.30 */
118 #endif /* !DRC_USE_CORDIC_ASIN */
119
120 #endif // __SOF_AUDIO_DRC_DRC_MATH_H__
121