66
77#include <sof/audio/format.h>
88#include <sof/math/decibels.h>
9+ #include <sof/math/exp_fcn.h>
910#include <stdint.h>
1011
11- #define ONE_Q20 Q_CONVERT_FLOAT(1.0, 20) /* Use Q12.20 */
12- #define ONE_Q23 Q_CONVERT_FLOAT(1.0, 23) /* Use Q9.23 */
13- #define TWO_Q27 Q_CONVERT_FLOAT(2.0, 27) /* Use Q5.27 */
14- #define MINUS_TWO_Q27 Q_CONVERT_FLOAT(-2.0, 27) /* Use Q5.27 */
1512#define LOG10_DIV20_Q27 Q_CONVERT_FLOAT(0.1151292546, 27) /* Use Q5.27 */
1613
17- /* Exponent function for small values of x. This function calculates
18- * fairly accurately exponent for x in range -2.0 .. +2.0. The iteration
19- * uses first 11 terms of Taylor series approximation for exponent
20- * function. With the current scaling the numerator just remains under
21- * 64 bits with the 11 terms.
22- *
23- * See https://en.wikipedia.org/wiki/Exponential_function#Computation
24- *
25- * The input is Q3.29
26- * The output is Q9.23
27- */
28-
29- static int32_t exp_small_fixed (int32_t x )
30- {
31- int64_t p ;
32- int64_t num = Q_SHIFT_RND (x , 29 , 23 );
33- int32_t y0 = (int32_t )num ;
34- int32_t den = 1 ;
35- int32_t inc ;
36- int k ;
37-
38- /* Numerator is x^k, denominator is k! */
39- for (k = 2 ; k < 12 ; k ++ ) {
40- p = num * x ; /* Q9.23 x Q3.29 -> Q12.52 */
41- num = Q_SHIFT_RND (p , 52 , 23 );
42- den = den * k ;
43- inc = (int32_t )(num / den );
44- y0 += inc ;
45- }
46-
47- return y0 + ONE_Q23 ;
48- }
49-
5014/* Decibels to linear conversion: The function uses exp() to calculate
5115 * the linear value. The argument is multiplied by log(10)/20 to
5216 * calculate equivalent of 10^(db/20).
@@ -68,50 +32,5 @@ int32_t db2lin_fixed(int32_t db)
6832
6933 /* Q8.24 x Q5.27, result needs to be Q5.27 */
7034 arg = (int32_t )Q_MULTSR_32X32 ((int64_t )db , LOG10_DIV20_Q27 , 24 , 27 , 27 );
71- return exp_fixed (arg );
72- }
73-
74- /* Fixed point exponent function for approximate range -11.5 .. 7.6
75- * that corresponds to decibels range -100 .. +66 dB.
76- *
77- * The functions uses rule exp(x) = exp(x/2) * exp(x/2) to reduce
78- * the input argument for private small value exp() function that is
79- * accurate with input range -2.0 .. +2.0. The number of possible
80- * divisions by 2 is computed into variable n. The returned value is
81- * exp()^(2^n).
82- *
83- * Input is Q5.27, -16.0 .. +16.0, but note the input range limitation
84- * Output is Q12.20, 0.0 .. +2048.0
85- */
86-
87- int32_t exp_fixed (int32_t x )
88- {
89- int32_t xs ;
90- int32_t y ;
91- int32_t y0 ;
92- int i ;
93- int n = 0 ;
94-
95- if (x < Q_CONVERT_FLOAT (-11.5 , 27 ))
96- return 0 ;
97-
98- if (x > Q_CONVERT_FLOAT (7.6245 , 27 ))
99- return INT32_MAX ;
100-
101- /* x is Q5.27 */
102- xs = x ;
103- while (xs >= TWO_Q27 || xs <= MINUS_TWO_Q27 ) {
104- xs >>= 1 ;
105- n ++ ;
106- }
107-
108- /* exp_small_fixed() input is Q3.29, while x1 is Q5.27
109- * exp_small_fixed() output is Q9.23, while y0 is Q12.20
110- */
111- y0 = Q_SHIFT_RND (exp_small_fixed (Q_SHIFT_LEFT (xs , 27 , 29 )), 23 , 20 );
112- y = ONE_Q20 ;
113- for (i = 0 ; i < (1 << n ); i ++ )
114- y = (int32_t )Q_MULTSR_32X32 ((int64_t )y , y0 , 20 , 20 , 20 );
115-
116- return y ;
35+ return sofm_exp_fixed (arg );
11736}
0 commit comments