Skip to content

Commit 802cffa

Browse files
andrula-songkv2019i
authored andcommitted
Audio: Dcblock: Add HiFi4 implementation of dcblock
Add HiFi4 implementation of dcblock processing functions. Compared with generic C version, the 16 bit format can save about 54.8% cycles, and 53.1% for 24 bit format and 49.1% for 32 bit. Signed-off-by: Andrula Song <andrula.song@intel.com>
1 parent 29f3ac6 commit 802cffa

File tree

6 files changed

+189
-1
lines changed

6 files changed

+189
-1
lines changed

src/audio/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ set(src_sources src/src.c src/src_generic.c)
172172
set(asrc_sources asrc/asrc.c asrc/asrc_farrow.c asrc/asrc_farrow_generic.c)
173173
set(eq-fir_sources module_adapter/module_adapter.c module_adapter/module/generic.c eq_fir/eq_fir.c eq_fir/eq_fir_generic.c)
174174
set(eq-iir_sources module_adapter/module_adapter.c module_adapter/module/generic.c eq_iir/eq_iir.c)
175-
set(dcblock_sources dcblock/dcblock.c dcblock/dcblock_generic.c)
175+
set(dcblock_sources dcblock/dcblock.c dcblock/dcblock_generic.c dcblock/dcblock_hifi4.c)
176176
set(crossover_sources crossover/crossover.c crossover/crossover_generic.c)
177177
set(tdfb_sources tdfb/tdfb.c tdfb/tdfb_generic.c tdfb/tdfb_direction.c)
178178
set(drc_sources drc/drc.c drc/drc_generic.c drc/drc_math_generic.c)

src/audio/dcblock/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
add_local_sources(sof dcblock.c)
22
add_local_sources(sof dcblock_generic.c)
3+
add_local_sources(sof dcblock_hifi4.c)

src/audio/dcblock/dcblock_generic.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <sof/audio/format.h>
1010
#include <sof/audio/dcblock/dcblock.h>
1111

12+
#ifdef DCBLOCK_GENERIC
13+
1214
LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL);
1315

1416
/**
@@ -166,3 +168,4 @@ const struct dcblock_func_map dcblock_fnmap[] = {
166168
};
167169

168170
const size_t dcblock_fncount = ARRAY_SIZE(dcblock_fnmap);
171+
#endif

src/audio/dcblock/dcblock_hifi4.c

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2022 Intel Corporation. All rights reserved.
4+
//
5+
// Author: Andrula Song <andrula.song@intel.com>
6+
7+
#include <stdint.h>
8+
#include <sof/audio/component.h>
9+
#include <sof/audio/format.h>
10+
#include <sof/audio/dcblock/dcblock.h>
11+
12+
#ifdef DCBLOCK_HIFI4
13+
14+
#include <xtensa/tie/xt_hifi4.h>
15+
LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL);
16+
17+
static inline ae_int32x2 dcblock_cal(ae_int32x2 R, ae_int32x2 state_x, ae_int32x2 state_y,
18+
ae_int32x2 sample)
19+
{
20+
ae_int64 out, temp;
21+
22+
/* R: Q2.30, y_prev: Q1.31 the result is Q2.62 */
23+
temp = AE_MULF32S_LL(R, state_y);
24+
out = AE_SUB64(AE_MOVAD32_L(sample), AE_MOVAD32_L(state_x));
25+
/* shift out to 2.62 */
26+
out = AE_ADD64S(AE_SLAI64S(out, 31), temp);
27+
/* shift out to 1.63 */
28+
return AE_ROUND32F64SSYM(AE_SLAI64S(out, 1));
29+
}
30+
31+
/* Setup circular for component sink and source */
32+
static inline void dcblock_set_circular(const struct audio_stream __sparse_cache *source,
33+
const struct audio_stream __sparse_cache *sink)
34+
{
35+
/* Set source as circular buffer 0 */
36+
AE_SETCBEGIN0(source->addr);
37+
AE_SETCEND0(source->end_addr);
38+
39+
/* Set sink as circular buffer 1 */
40+
AE_SETCBEGIN1(sink->addr);
41+
AE_SETCEND1(sink->end_addr);
42+
}
43+
44+
#if CONFIG_FORMAT_S16LE
45+
static void dcblock_s16_default(const struct comp_dev *dev,
46+
const struct audio_stream __sparse_cache *source,
47+
const struct audio_stream __sparse_cache *sink,
48+
uint32_t frames)
49+
{
50+
struct comp_data *cd = comp_get_drvdata(dev);
51+
ae_int16 *in;
52+
ae_int16 *out;
53+
ae_int32x2 R, state_x, state_y, sample;
54+
ae_int16x4 in_sample, out_sample;
55+
int ch, i;
56+
int nch = source->channels;
57+
const int inc = nch * sizeof(ae_int16);
58+
59+
dcblock_set_circular(source, sink);
60+
for (ch = 0; ch < nch; ch++) {
61+
in = (ae_int16 *)source->r_ptr + ch;
62+
out = (ae_int16 *)sink->w_ptr + ch;
63+
state_x = cd->state[ch].x_prev;
64+
state_y = cd->state[ch].y_prev;
65+
R = cd->R_coeffs[ch];
66+
for (i = 0; i < frames; i++) {
67+
/* Load a 16 bit sample*/
68+
AE_L16_XC(in_sample, in, inc);
69+
/* store the 16 bit sample to high 16bit of 32bit register*/
70+
sample = AE_CVT32X2F16_32(in_sample);
71+
state_y = dcblock_cal(R, state_x, state_y, sample);
72+
state_x = sample;
73+
out_sample = AE_ROUND16X4F32SSYM(state_y, state_y);
74+
AE_S16_0_XC1(out_sample, out, inc);
75+
}
76+
cd->state[ch].x_prev = state_x;
77+
cd->state[ch].y_prev = state_y;
78+
}
79+
}
80+
#endif /* CONFIG_FORMAT_S16LE */
81+
82+
#if CONFIG_FORMAT_S24LE
83+
static void dcblock_s24_default(const struct comp_dev *dev,
84+
const struct audio_stream __sparse_cache *source,
85+
const struct audio_stream __sparse_cache *sink,
86+
uint32_t frames)
87+
{
88+
struct comp_data *cd = comp_get_drvdata(dev);
89+
ae_int32 *in;
90+
ae_int32 *out;
91+
ae_int32x2 R, state_x, state_y;
92+
ae_int32x2 in_sample, out_sample;
93+
int ch, i;
94+
int nch = source->channels;
95+
const int inc = nch * sizeof(ae_int32);
96+
97+
dcblock_set_circular(source, sink);
98+
for (ch = 0; ch < nch; ch++) {
99+
in = (ae_int32 *)source->r_ptr + ch;
100+
out = (ae_int32 *)sink->w_ptr + ch;
101+
102+
state_x = cd->state[ch].x_prev;
103+
state_y = cd->state[ch].y_prev;
104+
R = cd->R_coeffs[ch];
105+
for (i = 0; i < frames; i++) {
106+
AE_L32_XC(in_sample, in, inc);
107+
in_sample = AE_SLAI32(in_sample, 8);
108+
state_y = dcblock_cal(R, state_x, state_y, in_sample);
109+
state_x = in_sample;
110+
out_sample = AE_SRAI32R(state_y, 8);
111+
out_sample = AE_SLAI32S(out_sample, 8);
112+
out_sample = AE_SRAI32R(out_sample, 8);
113+
AE_S32_L_XC1(out_sample, out, inc);
114+
}
115+
cd->state[ch].x_prev = state_x;
116+
cd->state[ch].y_prev = state_y;
117+
}
118+
}
119+
#endif /* CONFIG_FORMAT_S24LE */
120+
121+
#if CONFIG_FORMAT_S32LE
122+
static void dcblock_s32_default(const struct comp_dev *dev,
123+
const struct audio_stream __sparse_cache *source,
124+
const struct audio_stream __sparse_cache *sink,
125+
uint32_t frames)
126+
{
127+
struct comp_data *cd = comp_get_drvdata(dev);
128+
ae_int32 *in;
129+
ae_int32 *out;
130+
ae_int32x2 R, state_x, state_y;
131+
ae_int32x2 in_sample;
132+
int ch, i;
133+
int nch = source->channels;
134+
const int inc = nch * sizeof(ae_int32);
135+
136+
dcblock_set_circular(source, sink);
137+
for (ch = 0; ch < nch; ch++) {
138+
in = (ae_int32 *)source->r_ptr + ch;
139+
out = (ae_int32 *)sink->w_ptr + ch;
140+
141+
state_x = cd->state[ch].x_prev;
142+
state_y = cd->state[ch].y_prev;
143+
R = cd->R_coeffs[ch];
144+
for (i = 0; i < frames; i++) {
145+
AE_L32_XC(in_sample, in, inc);
146+
state_y = dcblock_cal(R, state_x, state_y, in_sample);
147+
state_x = in_sample;
148+
AE_S32_L_XC1(state_y, out, inc);
149+
}
150+
cd->state[ch].x_prev = state_x;
151+
cd->state[ch].y_prev = state_y;
152+
}
153+
}
154+
#endif /* CONFIG_FORMAT_S32LE */
155+
156+
const struct dcblock_func_map dcblock_fnmap[] = {
157+
/* { SOURCE_FORMAT , PROCESSING FUNCTION } */
158+
#if CONFIG_FORMAT_S16LE
159+
{ SOF_IPC_FRAME_S16_LE, dcblock_s16_default },
160+
#endif /* CONFIG_FORMAT_S16LE */
161+
#if CONFIG_FORMAT_S24LE
162+
{ SOF_IPC_FRAME_S24_4LE, dcblock_s24_default },
163+
#endif /* CONFIG_FORMAT_S24LE */
164+
#if CONFIG_FORMAT_S32LE
165+
{ SOF_IPC_FRAME_S32_LE, dcblock_s32_default },
166+
#endif /* CONFIG_FORMAT_S32LE */
167+
};
168+
169+
const size_t dcblock_fncount = ARRAY_SIZE(dcblock_fnmap);
170+
#endif

src/include/sof/audio/dcblock/dcblock.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@
1111
#include <stdint.h>
1212
#include <sof/platform.h>
1313
#include <ipc/stream.h>
14+
#include <sof/compiler_info.h>
15+
16+
/* __XCC__ is both for xt_xcc and xt_clang */
17+
#if defined(__XCC__)
18+
# include <xtensa/config/core-isa.h>
19+
# if XCHAL_HAVE_HIFI4
20+
# define DCBLOCK_HIFI4
21+
# else
22+
# define DCBLOCK_GENERIC
23+
# endif
24+
#else
25+
# define DCBLOCK_GENERIC
26+
#endif
1427

1528
struct audio_stream;
1629
struct comp_dev;

zephyr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ zephyr_library_sources_ifdef(CONFIG_COMP_ASRC
463463
zephyr_library_sources_ifdef(CONFIG_COMP_DCBLOCK
464464
${SOF_AUDIO_PATH}/dcblock/dcblock_generic.c
465465
${SOF_AUDIO_PATH}/dcblock/dcblock.c
466+
${SOF_AUDIO_PATH}/dcblock/dcblock_hifi4.c
466467
)
467468

468469
zephyr_library_sources_ifdef(CONFIG_COMP_SEL

0 commit comments

Comments
 (0)