Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,13 @@ config FORMAT_CONVERT_HIFI3
help
Use HIFI3 extensions for optimized format conversion (experimental).

config FORMAT_CONVERT_ARM_SIMD
bool "ARM SIMD optimized conversion"
default y
depends on ARM
help
Use ARMv7E-M DSP and SIMD instructions for optimized format conversion.

config PCM_CONVERTER_FORMAT_U8
bool "Support U8"
help
Expand Down
1 change: 1 addition & 0 deletions src/audio/dcblock/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_local_sources(sof dcblock.c)
add_local_sources(sof dcblock_generic.c)
add_local_sources(sof dcblock_hifi3.c)
add_local_sources(sof dcblock_hifi4.c)
add_local_sources(sof dcblock_arm.c)

if(CONFIG_IPC_MAJOR_3)
add_local_sources(sof dcblock_ipc3.c)
Expand Down
10 changes: 9 additions & 1 deletion src/audio/dcblock/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ config COMP_DCBLOCK
choice
prompt "DC Blocking Filter HIFI level"
depends on COMP_DCBLOCK
default DCBLOCK_HIFI_MAX
default DCBLOCK_HIFI_MAX if XTENSA
default DCBLOCK_ARM_SIMD if ARM
default DCBLOCK_HIFI_NONE

config DCBLOCK_ARM_SIMD
bool "ARM SIMD and FPU accelerated DCBLOCK"
depends on ARM
help
Select for ARMv7E-M SIMD and FPU accelerated DC Blocking Filter.

config DCBLOCK_HIFI_MAX
bool "Max level available in the toolchain"
Expand Down
157 changes: 157 additions & 0 deletions src/audio/dcblock/dcblock_arm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2026 Sound Open Firmware. All rights reserved.
//
// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>

#include <stdint.h>
#include <sof/audio/component.h>
#include <sof/audio/format.h>
#include <sof/audio/audio_stream.h>
#include <sof/audio/arm_simd.h>

#include "dcblock.h"

#if SOF_USE_ARM_SIMD(DCBLOCK)

LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL);

static inline int32_t dcblock_arm_process(struct dcblock_state *state, int64_t R, int32_t x)
{
/*
* R: Q2.30, y_prev: Q1.31 -> R * y_prev: Q3.61
* Q_SHIFT_RND(R * y_prev, 61, 31) shifts right by 30 bits with rounding.
*/
int64_t prod = R * state->y_prev;
int64_t out = ((int64_t)x) - state->x_prev + ((prod + (1LL << 29)) >> 30);

state->y_prev = arm_sat_q31(out);
state->x_prev = x;

return state->y_prev;
}

#if CONFIG_FORMAT_S16LE
static int dcblock_s16_arm(struct comp_data *cd,
struct cir_buf_source *source,
struct cir_buf_sink *sink,
uint32_t frames)
{
const int16_t *x = source->ptr;
int16_t *y = sink->ptr;
int samples_without_wrap;
int nch = cd->channels;
int remaining_samples = frames * nch;
int32_t tmp;
int ch = 0;
int i;

while (remaining_samples) {
samples_without_wrap = cir_buf_samples_without_wrap_s16(x, source->buf_end);
samples_without_wrap = MIN(samples_without_wrap,
cir_buf_samples_without_wrap_s16(y, sink->buf_end));
samples_without_wrap = MIN(samples_without_wrap, remaining_samples);
for (i = 0; i < samples_without_wrap; i++) {
tmp = dcblock_arm_process(&cd->state[ch], cd->R_coeffs[ch], (int32_t)*x << 16);
*y = arm_sat_s16(Q_SHIFT_RND(tmp, 31, 15));
x++;
y++;
if (++ch == nch)
ch = 0;
}
x = source_cir_buf_wrap(x, source->buf_start, source->buf_end);
y = cir_buf_wrap(y, sink->buf_start, sink->buf_end);
remaining_samples -= samples_without_wrap;
}

return 0;
}
#endif /* CONFIG_FORMAT_S16LE */

#if CONFIG_FORMAT_S24LE
static int dcblock_s24_arm(struct comp_data *cd,
struct cir_buf_source *source,
struct cir_buf_sink *sink,
uint32_t frames)
{
const int32_t *x = source->ptr;
int32_t *y = sink->ptr;
int samples_without_wrap;
int nch = cd->channels;
int remaining_samples = frames * nch;
int32_t tmp;
int ch = 0;
int i;

while (remaining_samples) {
samples_without_wrap = cir_buf_samples_without_wrap_s32(x, source->buf_end);
samples_without_wrap = MIN(samples_without_wrap,
cir_buf_samples_without_wrap_s32(y, sink->buf_end));
samples_without_wrap = MIN(samples_without_wrap, remaining_samples);
for (i = 0; i < samples_without_wrap; i++) {
tmp = dcblock_arm_process(&cd->state[ch], cd->R_coeffs[ch], *x << 8);
*y = arm_sat_s24(Q_SHIFT_RND(tmp, 31, 23));
x++;
y++;
if (++ch == nch)
ch = 0;
}
x = source_cir_buf_wrap(x, source->buf_start, source->buf_end);
y = cir_buf_wrap(y, sink->buf_start, sink->buf_end);
remaining_samples -= samples_without_wrap;
}

return 0;
}
#endif /* CONFIG_FORMAT_S24LE */

#if CONFIG_FORMAT_S32LE
static int dcblock_s32_arm(struct comp_data *cd,
struct cir_buf_source *source,
struct cir_buf_sink *sink,
uint32_t frames)
{
const int32_t *x = source->ptr;
int32_t *y = sink->ptr;
int samples_without_wrap;
int nch = cd->channels;
int remaining_samples = frames * nch;
int ch = 0;
int i;

while (remaining_samples) {
samples_without_wrap = cir_buf_samples_without_wrap_s32(x, source->buf_end);
samples_without_wrap = MIN(samples_without_wrap,
cir_buf_samples_without_wrap_s32(y, sink->buf_end));
samples_without_wrap = MIN(samples_without_wrap, remaining_samples);
for (i = 0; i < samples_without_wrap; i++) {
*y = dcblock_arm_process(&cd->state[ch], cd->R_coeffs[ch], *x);
x++;
y++;
if (++ch == nch)
ch = 0;
}
x = source_cir_buf_wrap(x, source->buf_start, source->buf_end);
y = cir_buf_wrap(y, sink->buf_start, sink->buf_end);
remaining_samples -= samples_without_wrap;
}

return 0;
}
#endif /* CONFIG_FORMAT_S32LE */

const struct dcblock_func_map dcblock_fnmap[] = {
#if CONFIG_FORMAT_S16LE
{ SOF_IPC_FRAME_S16_LE, dcblock_s16_arm },
#endif
#if CONFIG_FORMAT_S24LE
{ SOF_IPC_FRAME_S24_4LE, dcblock_s24_arm },
#endif
#if CONFIG_FORMAT_S32LE
{ SOF_IPC_FRAME_S32_LE, dcblock_s32_arm },
#endif
};

const size_t dcblock_fncount = ARRAY_SIZE(dcblock_fnmap);

#endif /* SOF_USE_ARM_SIMD(DCBLOCK) */
2 changes: 1 addition & 1 deletion src/audio/dcblock/dcblock_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#include "dcblock.h"

#if SOF_USE_HIFI(NONE, DCBLOCK)
#if SOF_USE_HIFI(NONE, DCBLOCK) && !SOF_USE_ARM_SIMD(DCBLOCK)

LOG_MODULE_DECLARE(dcblock, CONFIG_SOF_LOG_LEVEL);

Expand Down
2 changes: 2 additions & 0 deletions src/audio/drc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ else()
drc_generic.c
drc_hifi3.c
drc_hifi4.c
drc_arm.c
drc_math_generic.c
drc_math_hifi3.c
drc_math_arm.c
)
endif()

Expand Down
11 changes: 10 additions & 1 deletion src/audio/drc/Kconfig.simd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@ comment "DRC optimization level select"
choice "DRC_SIMD_LEVEL_SELECT"
prompt "choose which SIMD level used for DRC module"
depends on COMP_DRC
default DRC_HIFI_MAX
default DRC_HIFI_MAX if XTENSA
default DRC_ARM_SIMD if ARM
default DRC_HIFI_NONE

config DRC_ARM_SIMD
prompt "choose ARM SIMD & DSP optimized DRC module"
bool
depends on ARM
help
This option used to build ARMv7E-M DSP / SIMD optimized DRC code.

config DRC_HIFI_MAX
prompt "SIMD will selected by toolchain pre-defined header"
Expand Down
Loading
Loading