Skip to content

Commit c6b4925

Browse files
committed
Math: Replace exp() function with more accurate and fast version
The function sofm_exp_int32() is replaced with new sofm_exp_approx() function. It's not a direct replacement so the name is changed. The input range changes from +/- 5 to +/- 8. The wrapper function sofm_exp_fixed() with input range -16 .. +7.6 is updated to use the new function with a simpler range reduction for large negative input values. All current exponent function usage in SOF components is for the wrapper function that remains compatible. The function sofm_db2lin_fixed() is updated to handle larger negative input decibels values made possible by the new more accurate exponent function. The accuracy in exponent function for input ranges from -8 to +8 or -16 to 7.6 depending on used exponent function improves from absolute error of 1 to 1000 ppm to constant less than 1 ppm. The cycles count for exponent function calculate decreases from about 369 max to 78 max on MTL platform for HiFi code version with -O2 or -O3 optimization. The generic C version on MTL platform is max 88 cycles. The DRC component is a heavy user of the exponent function. The saving in MTL build of DRC is 10.5 MCPS, it drops from 22.17 to 11.70 with profiler run: "scripts/sof-testbench-helper.sh -x -m drc -p profile.txt" The saving in MTL build of multiband DRC is 30.2 MCPS, it drops from 127.95 to 97.78 with profiler run: "scripts/sof-testbench-helper.sh -x -m drc_multiband -p profile.txt" This patch also updates the cmocka test. The test functions are changed due to changed function name, changed achievable accuracy. Also the random values test points vector is replaced fixed a fixed linearly spaced vector for repeatable test and risk for random failures. Signed-off-by: Shriram Shastry <[email protected]> Signed-off-by: Seppo Ingalsuo <[email protected]>
1 parent e95d7ee commit c6b4925

File tree

4 files changed

+533
-628
lines changed

4 files changed

+533
-628
lines changed

src/include/sof/math/exp_fcn.h

+31-30
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/* SPDX-License-Identifier: BSD-3-Clause
22
*
3-
* Copyright(c) 2022 Intel Corporation. All rights reserved.
3+
* Copyright(c) 2022-2025 Intel Corporation.
44
*
55
* Author: Shriram Shastry <[email protected]>
6+
* Seppo Ingalsuo <[email protected]>
67
*
78
*/
89
#ifndef __SOFM_EXP_FCN_H__
@@ -26,40 +27,40 @@
2627

2728
#endif
2829

29-
/* TODO: Is there a MCPS difference */
30-
#define USING_QCONVERT 1
30+
/* Q5.27 int32(round(log((2^31 - 1)/2^20) * 2^27)) */
31+
#define SOFM_EXP_FIXED_INPUT_MAX 1023359037
3132

32-
#if USING_QCONVERT
33+
/* Q8.24 int32(round((log((2^31 - 1)/2^20) * 20 / log(10)) * 2^24)) */
34+
#define SOFM_DB2LIN_INPUT_MAX 1111097957
3335

34-
#include <sof/audio/format.h>
35-
#define SOFM_EXP_FIXED_INPUT_MIN Q_CONVERT_FLOAT(-11.5, 27) /* Q5.27 */
36-
#define SOFM_EXP_FIXED_INPUT_MAX Q_CONVERT_FLOAT(7.6245, 27) /* Q5.27 */
37-
#define SOFM_EXP_TWO_Q27 Q_CONVERT_FLOAT(2.0, 27) /* Q5.27 */
38-
#define SOFM_EXP_MINUS_TWO_Q27 Q_CONVERT_FLOAT(-2.0, 27) /* Q5.27 */
39-
#define SOFM_EXP_ONE_Q20 Q_CONVERT_FLOAT(1.0, 20) /* Q12.20 */
40-
#define SOFM_EXP_MINUS_100_Q24 Q_CONVERT_FLOAT(-100.0, 24) /* Q8.24 */
41-
#define SOFM_EXP_LOG10_DIV20_Q27 Q_CONVERT_FLOAT(0.1151292546, 27) /* Q5.27 */
42-
43-
#else
44-
45-
#define SOFM_EXP_FIXED_INPUT_MIN -1543503872 /* Q_CONVERT_FLOAT(-11.5, 27) */
46-
#define SOFM_EXP_FIXED_INPUT_MAX 1023343067 /* Q_CONVERT_FLOAT(7.6245, 27) */
47-
#define SOFM_EXP_TWO_Q27 268435456 /* Q_CONVERT_FLOAT(2.0, 27) */
48-
#define SOFM_EXP_MINUS_TWO_Q27 -268435456 /* Q_CONVERT_FLOAT(-2.0, 27) */
49-
#define SOFM_EXP_ONE_Q20 1048576 /* Q_CONVERT_FLOAT(1.0, 20) */
50-
#define SOFM_EXP_MINUS_100_Q24 -1677721600 /* Q_CONVERT_FLOAT(-100.0, 24) */
51-
#define SOFM_EXP_LOG10_DIV20_Q27 15452387 /* Q_CONVERT_FLOAT(0.1151292546, 27) */
36+
/**
37+
* Calculates exponent function exp(x) = e^x with accurate and efficient technique that
38+
* includes range reduction operations, approximation with Taylor series, and reconstruction
39+
* operations to compensate the range reductions.
40+
* @param x The input argument as Q4.28 from -8 to +8
41+
* @return The calculated e^x value as Q13.19 from 3.3546e-04 to 2981.0
42+
*/
43+
int32_t sofm_exp_approx(int32_t x);
5244

53-
#endif
45+
/**
46+
* Calculated exponent function exp(x) = e^x by using sofm_exp_approx(). The input range for
47+
* large arguments is internally reduced to -8 to +8 with rule exp(x) = exp(x/2) * exp(x/2)
48+
* and reconstructed back. This function is essentially a wrapper for compatibility with
49+
* existing usage of exp() function and Q-format choice. Note that the return value saturates
50+
* to INT32_MAX with input arguments larger than 7.6246.
51+
* @param x The input argument as Q5.27 from -16 to +16
52+
* @return The calculated e^x value as Q12.20
53+
*/
54+
int32_t sofm_exp_fixed(int32_t x);
5455

55-
#define SOFM_EXP_BIT_MASK_LOW_Q27P5 0x0000000008000000
56-
#define SOFM_EXP_BIT_MASK_Q62P2 0x4000000000000000LL
57-
#define SOFM_EXP_QUOTIENT_SCALE 0x40000000
58-
#define SOFM_EXP_TERMS_Q23P9 0x800000
59-
#define SOFM_EXP_LSHIFT_BITS 0x2000
6056

61-
int32_t sofm_exp_int32(int32_t x);
62-
int32_t sofm_exp_fixed(int32_t x);
57+
/**
58+
* Converts a decibels value to liner amplitude lin = 10^(db/20) value with optimized
59+
* equation exp(db * log(10)/20). Note that due to range limitation of sofm_exp_fixed()
60+
* the output saturates to maximum with about +66 dB input.
61+
* @param db Decibels value in Q8.24 format, from -128 to +66.226
62+
* @return Linear value in Q12.20 format, from 3.9811e-07 to 2048
63+
*/
6364
int32_t sofm_db2lin_fixed(int32_t db);
6465

6566
#endif /* __SOFM_EXP_FCN_H__ */

0 commit comments

Comments
 (0)