Skip to content

Commit fb9cd9c

Browse files
DRC: math: Replace exponential function for performance
For DRC performance, replace "exp_small_fixed()" with "sofm_exp_int32()". Included supporting change to include "sofm_exp_int32()" within exp_fixed() and repositioned "exp_small_fixed()" for future use. Signed-off-by: shastry <malladi.sastry@intel.com>
1 parent 20705ad commit fb9cd9c

6 files changed

Lines changed: 57 additions & 42 deletions

File tree

src/audio/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ config COMP_DRC
280280
select NUMBERS_NORM
281281
select MATH_DECIBELS
282282
select COMP_BLOB
283+
select MATH_EXP
283284
default n
284285
help
285286
Select for Dynamic Range Compressor (DRC) component. A DRC can be used

src/include/sof/math/decibels.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define DB2LIN_FIXED_OUTPUT_QY 20
1818

1919
int32_t exp_fixed(int32_t x); /* Input is Q5.27, output is Q12.20 */
20+
int32_t exp_small_fixed(int32_t x); /* Input is Q3.29, Output is Q9.23 */
2021
int32_t db2lin_fixed(int32_t x); /* Input is Q8.24, output is Q12.20 */
2122

2223
#endif /* __SOF_MATH_DECIBELS_H__ */

src/math/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ config MATH_EXP
4747
an input range of -5 to +5 gives positive numbers between 0.00673794699908547 and
4848
148.413159102577. The precision of this function is 1e-4.
4949

50+
config MATH_EXP_SMALL_FXD
51+
bool "Small Exponential functions"
52+
default n
53+
help
54+
By selecting this, the 32-bit exp_small_fixed() function can be used to calculate
55+
exponential values. With a mean thdn of -131.205(dBc), an exponential function with
56+
an input range of -2 to +2 gives positive numbers between 0.135335255 and
57+
7.38905609. The precision of this function is 1e-6.
58+
5059
config NATURAL_LOGARITHM_FIXED
5160
bool "Natural Logarithm function"
5261
default n

src/math/decibels.c

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,47 +6,14 @@
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

1112
#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 */
1313
#define TWO_Q27 Q_CONVERT_FLOAT(2.0, 27) /* Use Q5.27 */
1414
#define MINUS_TWO_Q27 Q_CONVERT_FLOAT(-2.0, 27) /* Use Q5.27 */
1515
#define LOG10_DIV20_Q27 Q_CONVERT_FLOAT(0.1151292546, 27) /* Use Q5.27 */
1616

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-
5017
/* Decibels to linear conversion: The function uses exp() to calculate
5118
* the linear value. The argument is multiplied by log(10)/20 to
5219
* calculate equivalent of 10^(db/20).
@@ -105,10 +72,10 @@ int32_t exp_fixed(int32_t x)
10572
n++;
10673
}
10774

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
75+
/* sofm_exp_int32() input is Q4.28, while x1 is Q5.27
76+
* sofm_exp_int32() output is Q9.23, while y0 is Q12.20
11077
*/
111-
y0 = Q_SHIFT_RND(exp_small_fixed(Q_SHIFT_LEFT(xs, 27, 29)), 23, 20);
78+
y0 = Q_SHIFT_RND(sofm_exp_int32(Q_SHIFT_LEFT(xs, 27, 28)), 23, 20);
11279
y = ONE_Q20;
11380
for (i = 0; i < (1 << n); i++)
11481
y = (int32_t)Q_MULTSR_32X32((int64_t)y, y0, 20, 20, 20);

src/math/exp_fcn.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*
77
*/
88

9+
#include <sof/math/decibels.h>
10+
#include <sof/audio/format.h>
911
#include <sof/math/exp_fcn.h>
1012
#include <sof/math/numbers.h>
1113
#include <sof/common.h>
@@ -20,7 +22,7 @@
2022
#define SOFM_BIT_MASK_Q62P2 0x4000000000000000LL
2123
#define SOFM_CONVERG_ERROR 28823037607936LL // error smaller than 1e-4,1/2 ^ -44.7122876200884
2224
#define SOFM_BIT_MASK_LOW_Q27P5 0x8000000
23-
#define SOFM_QUOTIENT_SCALE BIT(30)
25+
#define SOFM_QUOTIENT_SCALE 0x400000000
2426
#define SOFM_TERMS_Q23P9 8388608
2527
#define SOFM_LSHIFT_BITS 8192
2628

@@ -217,4 +219,38 @@ int32_t sofm_exp_int32(int32_t x)
217219
}
218220
return ts;
219221
}
222+
223+
#define ONE_Q23 Q_CONVERT_FLOAT(1.0, 23) /* Use Q9.23 */
224+
225+
/* Exponent function for small values of x. This function calculates
226+
* fairly accurately exponent for x in range -2.0 .. +2.0. The iteration
227+
* uses first 11 terms of Taylor series approximation for exponent
228+
* function. With the current scaling the numerator just remains under
229+
* 64 bits with the 11 terms.
230+
*
231+
* See https://en.wikipedia.org/wiki/Exponential_function#Computation
232+
*
233+
* The input is Q3.29
234+
* The output is Q9.23
235+
*/
236+
int32_t exp_small_fixed(int32_t x)
237+
{
238+
int64_t p;
239+
int64_t num = Q_SHIFT_RND(x, 29, 23);
240+
int32_t y0 = (int32_t)num;
241+
int32_t den = 1;
242+
int32_t inc;
243+
int k;
244+
245+
/* Numerator is x^k, denominator is k! */
246+
for (k = 2; k < 12; k++) {
247+
p = num * x; /* Q9.23 x Q3.29 -> Q12.52 */
248+
num = Q_SHIFT_RND(p, 52, 23);
249+
den = den * k;
250+
inc = (int32_t)(num / den);
251+
y0 += inc;
252+
}
253+
254+
return y0 + ONE_Q23;
255+
}
220256
#endif

src/math/exp_fcn_hifi.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#define SOFM_CONVERG_ERROR 28823037624320LL /* error smaller than 1e-4,1/2 ^ -44.7122876209085 */
3030
#define SOFM_BIT_MASK_LOW_Q27P5 0x0000000008000000
3131
#define SOFM_BIT_MASK_Q62P2 0x4000000000000000LL
32-
#define SOFM_QUOTIENT_SCALE BIT(30)
32+
#define SOFM_QUOTIENT_SCALE 0x400000000
3333
#define SOFM_TERMS_Q23P9 0x800000
3434
#define SOFM_LSHIFT_BITS 0x2000
3535
/*
@@ -89,7 +89,7 @@ static void mul_s64(ae_int64 in_0, ae_int64 in_1, ae_int64 *__restrict__ ptroutb
8989
ae_int64 *__restrict__ ptroutbitslo)
9090
{
9191
ae_int64 producthihi, producthilo, productlolo;
92-
ae_int64 producthi, productlo, product_hl_lh_h, product_hl_lh_l, carry;
92+
ae_int64 producthi, product_hl_lh_h, product_hl_lh_l, carry;
9393

9494
#if (SOFM_EXPONENTIAL_HIFI4 == 1 || SOFM_EXPONENTIAL_HIFI5 == 1)
9595

@@ -130,6 +130,7 @@ static void mul_s64(ae_int64 in_0, ae_int64 in_1, ae_int64 *__restrict__ ptroutb
130130
ae_int64 producthi_1c;
131131
ae_int64 producthi_2c;
132132
ae_int64 productlo_2c;
133+
ae_int64 productlo;
133134

134135
ae_int64 s0 = AE_SRLI64(in_0, 63);
135136
ae_int64 s1 = AE_SRLI64(in_1, 63);
@@ -194,7 +195,7 @@ static int64_t lomul_s64_sr_sat_near(int64_t a, int64_t b)
194195
return AE_ADD64(temp, roundup);
195196
}
196197

197-
static ae_int64 onebyfact_Q63[19] = {
198+
int64_t onebyfact_Q63[19] = {
198199
4611686018427387904LL,
199200
1537228672809129301LL,
200201
384307168202282325LL,
@@ -239,7 +240,7 @@ int32_t sofm_exp_int32(int32_t x)
239240
ae_int64 onebyfact;
240241
ae_int64 temp;
241242

242-
ae_int64 *ponebyfact_Q63 = &onebyfact_Q63[0];
243+
ae_int64 *ponebyfact_Q63 = (ae_int64 *)&onebyfact_Q63[0];
243244
ae_int64 ts = SOFM_TERMS_Q23P9;
244245
ae_int64 mp = (x + SOFM_LSHIFT_BITS) >> 14; /* x in Q50.14 */;
245246
xtbool flag;

0 commit comments

Comments
 (0)