Skip to content

Commit 3601def

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() ,HiFi intrinsic function is added to replace C macros,and removed "exp_small_fixed()" from future use. Signed-off-by: shastry <malladi.sastry@intel.com>
1 parent 4d4421a commit 3601def

File tree

18 files changed

+238
-110
lines changed

18 files changed

+238
-110
lines changed

src/audio/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,18 @@ rsource "crossover/Kconfig"
122122

123123
rsource "drc/Kconfig"
124124

125+
config COMP_DRC
126+
bool "Dynamic Range Compressor component"
127+
select CORDIC_FIXED
128+
select NUMBERS_NORM
129+
select COMP_BLOB
130+
select MATH_EXP
131+
default n
132+
help
133+
Select for Dynamic Range Compressor (DRC) component. A DRC can be used
134+
to reduce the volume of loud sounds and amplify silent sounds thus
135+
compressing an audio signal's dynamic range.
136+
125137
rsource "multiband_drc/Kconfig"
126138

127139
rsource "dcblock/Kconfig"

src/audio/drc/drc_generic.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <sof/audio/drc/drc_math.h>
1111
#include <sof/audio/format.h>
1212
#include <sof/math/decibels.h>
13+
#include <sof/math/exp_fcn.h>
1314
#include <sof/math/numbers.h>
1415
#include <stdint.h>
1516

@@ -35,7 +36,7 @@ static int32_t knee_curveK(const struct sof_drc_params *p, int32_t x)
3536
* beta = -expf(k * linear_threshold) / k
3637
* gamma = -k * x
3738
*/
38-
knee_exp_gamma = exp_fixed(Q_MULTSR_32X32((int64_t)x, -p->K, 31, 20, 27)); /* Q12.20 */
39+
knee_exp_gamma = sofm_exp_fixed(Q_MULTSR_32X32((int64_t)x, -p->K, 31, 20, 27)); /* Q12.20 */
3940
return p->knee_alpha + Q_MULTSR_32X32((int64_t)p->knee_beta, knee_exp_gamma, 24, 20, 24);
4041
}
4142

@@ -65,8 +66,10 @@ static int32_t volume_gain(const struct sof_drc_params *p, int32_t x)
6566
* => y/x = ratio_base * x^(s - 1)
6667
* => y/x = ratio_base * e^(log(x) * (s - 1))
6768
*/
68-
exp_knee = exp_fixed(Q_MULTSR_32X32((int64_t)drc_log_fixed(Q_SHIFT_RND(x, 31, 26)),
69-
(p->slope - ONE_Q30), 26, 30, 27)); /* Q12.20 */
69+
exp_knee = sofm_exp_fixed(
70+
Q_MULTSR_32X32((int64_t)
71+
drc_log_fixed(Q_SHIFT_RND(x, 31, 26)),
72+
(p->slope - ONE_Q30), 26, 30, 27)); /* Q12.20 */
7073
y = Q_MULTSR_32X32((int64_t)p->ratio_base, exp_knee, 30, 20, 30);
7174
}
7275

src/audio/drc/drc_hifi3.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <sof/audio/drc/drc_math.h>
1111
#include <sof/audio/format.h>
1212
#include <sof/math/decibels.h>
13+
#include <sof/math/exp_fcn.h>
1314
#include <sof/math/numbers.h>
1415
#include <stdint.h>
1516

@@ -41,7 +42,7 @@ static int32_t knee_curveK(const struct sof_drc_params *p, int32_t x)
4142
* gamma = -k * x
4243
*/
4344
gamma = drc_mult_lshift(x, -p->K, drc_get_lshift(31, 20, 27));
44-
knee_exp_gamma = exp_fixed(gamma);
45+
knee_exp_gamma = sofm_exp_fixed(gamma);
4546
knee_curve_k = drc_mult_lshift(p->knee_beta, knee_exp_gamma, drc_get_lshift(24, 20, 24));
4647
knee_curve_k = AE_ADD32(knee_curve_k, p->knee_alpha);
4748
return knee_curve_k;
@@ -77,7 +78,7 @@ static int32_t volume_gain(const struct sof_drc_params *p, int32_t x)
7778
tmp = AE_SRAI32R(x, 5); /* Q1.31 -> Q5.26 */
7879
tmp = drc_log_fixed(tmp); /* Q6.26 */
7980
tmp2 = AE_SUB32(p->slope, ONE_Q30); /* Q2.30 */
80-
exp_knee = exp_fixed(drc_mult_lshift(tmp, tmp2, drc_get_lshift(26, 30, 27)));
81+
exp_knee = sofm_exp_fixed(drc_mult_lshift(tmp, tmp2, drc_get_lshift(26, 30, 27)));
8182
y = drc_mult_lshift(p->ratio_base, exp_knee, drc_get_lshift(30, 20, 30));
8283
}
8384

src/audio/drc/drc_math_generic.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <sof/audio/drc/drc_math.h>
88
#include <sof/audio/format.h>
99
#include <sof/math/decibels.h>
10+
#include <sof/math/exp_fcn.h>
1011
#include <sof/math/numbers.h>
1112
#include <sof/math/trig.h>
1213

@@ -219,8 +220,6 @@ inline int32_t drc_inv_fixed(int32_t x, int32_t precision_x, int32_t precision_y
219220
#undef qc
220221
}
221222

222-
#endif /* DRC_GENERIC */
223-
224223
/*
225224
* Input x is Q6.26; valid range: (0.0, 32.0); x <= 0 is not supported
226225
* y is Q2.30: (-2.0, 2.0)
@@ -233,8 +232,8 @@ inline int32_t drc_pow_fixed(int32_t x, int32_t y)
233232
return 0;
234233

235234
/* x^y = expf(y * log(x)) */
236-
return exp_fixed(q_mult(y, drc_log_fixed(x), 30, 26, 27));
235+
return sofm_exp_fixed(q_mult(y, drc_log_fixed(x), 30, 26, 27));
237236
}
238-
237+
#endif
239238
#undef q_multq
240239
#undef q_mult

src/audio/mfcc/mfcc_setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <sof/audio/component.h>
99
#include <sof/audio/audio_stream.h>
1010
#include <sof/math/auditory.h>
11+
#include <sof/math/decibels.h>
12+
#include <sof/math/exp_fcn.h>
1113
#include <sof/math/trig.h>
1214
#include <sof/math/window.h>
1315
#include <sof/trace/trace.h>

src/audio/multiband_drc/multiband_drc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static int multiband_drc_init(struct processing_module *mod)
258258
*/
259259
cd->process_enabled = true;
260260
#else
261-
cd->process_enabled = false;
261+
cd->process_enabled = true;
262262
#endif
263263

264264
/* Handler for configuration data */

src/include/sof/math/decibels.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@
1111

1212
#include <stdint.h>
1313

14-
#define EXP_FIXED_INPUT_QY 27
15-
#define EXP_FIXED_OUTPUT_QY 20
16-
#define DB2LIN_FIXED_INPUT_QY 24
17-
#define DB2LIN_FIXED_OUTPUT_QY 20
18-
19-
int32_t exp_fixed(int32_t x); /* Input is Q5.27, output is Q12.20 */
2014
int32_t db2lin_fixed(int32_t x); /* Input is Q8.24, output is Q12.20 */
2115

2216
#endif /* __SOF_MATH_DECIBELS_H__ */

src/include/sof/math/exp_fcn.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@
2626

2727
#endif
2828

29-
int32_t sofm_exp_int32(int32_t x);
30-
29+
int32_t sofm_exp_int32(int32_t x); /* Input is Q4.28, Output is Q9.23 */
30+
int32_t sofm_exp_fixed(int32_t x); /* Input is Q5.27, output is Q12.20 */
3131
#endif

src/math/auditory/auditory.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <rtos/alloc.h>
99
#include <sof/math/auditory.h>
1010
#include <sof/math/decibels.h>
11+
#include <sof/math/exp_fcn.h>
1112
#include <sof/math/fft.h>
1213
#include <sof/math/log.h>
1314
#include <sof/math/numbers.h>
@@ -80,7 +81,7 @@ int16_t psy_mel_to_hz(int16_t mel)
8081
return 0;
8182

8283
exp_arg = Q_MULTSR_32X32((int64_t)mel, ONE_OVER_MELDIV_Q31, 2, 31, 27);
83-
exp = exp_fixed(exp_arg) - ONE_Q20;
84+
exp = sofm_exp_fixed(exp_arg) - ONE_Q20;
8485
hz = Q_MULTSR_32X32((int64_t)exp, 700, 20, 0, 0);
8586
return hz;
8687
}

src/math/decibels.c

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

Comments
 (0)