Skip to content
Draft
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
6 changes: 2 additions & 4 deletions src/audio/webrtc_aec/webrtc_aec-shims.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
#include <string.h>
#include <sof/audio/module_adapter/module/generic.h>
#include <rtos/alloc.h>
#include <rtos/panic.h>
#if !defined(LLEXT_MODULE)
#if !defined(LLEXT_MODULE) && !defined(LL_EXTENSION_BUILD)
#include <rtos/userspace_helper.h>
static APP_SYSUSER_BSS struct processing_module *active_aec_mod;
#else
Expand Down Expand Up @@ -73,7 +72,6 @@ void *webrtc_realloc(void *ptr, size_t size)
return NULL;
}

/* Not called by AEC3 */
k_panic();
/* Not called by AECm/AEC3 */
return NULL;
}
148 changes: 115 additions & 33 deletions src/audio/webrtc_aec/webrtc_aec.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,67 @@ static void s16_to_sink(struct sof_sink *dst, int16_t src[][WEBRTC_AEC_FIFO_FRAM
sink_commit_buffer(dst, nbytes);
}

static void src_drop_frames(struct sof_source *src, int frames)
{
size_t frame_bytes = source_get_frame_bytes(src);
const void *data_ptr, *buf_start;
size_t buf_size, nbytes;

if (frames <= 0 || !frame_bytes)
return;

nbytes = (size_t)frames * frame_bytes;
if (!source_get_data(src, nbytes, &data_ptr, &buf_start, &buf_size))
source_release_data(src, nbytes);
}

static void webrtc_aec_resolve_sources(struct sof_source **sources, int num_of_sources,
struct sof_sink **sinks, int num_of_sinks,
int *mic_idx, int *ref_idx)
{
*mic_idx = 0;
*ref_idx = -1;

if (num_of_sources <= 1)
return;

#ifdef CONFIG_IPC_MAJOR_4
{
uint32_t q0 = IPC4_SINK_QUEUE_ID(source_get_id(sources[0]));
uint32_t q1 = IPC4_SINK_QUEUE_ID(source_get_id(sources[1]));

if (q0 != q1) {
if (q0 == 0) {
*mic_idx = 0;
*ref_idx = 1;
} else {
*mic_idx = 1;
*ref_idx = 0;
}
return;
}
}
#endif

if (num_of_sinks > 0) {
if (source_get_pipeline_id(sources[0]) == sink_get_pipeline_id(sinks[0]) &&
source_get_pipeline_id(sources[1]) != sink_get_pipeline_id(sinks[0])) {
*mic_idx = 0;
*ref_idx = 1;
return;
}
if (source_get_pipeline_id(sources[1]) == sink_get_pipeline_id(sinks[0]) &&
source_get_pipeline_id(sources[0]) != sink_get_pipeline_id(sinks[0])) {
*mic_idx = 1;
*ref_idx = 0;
return;
}
}

*mic_idx = 0;
*ref_idx = 1;
}

/* ----------------------------------------------------------------
* module_interface operations
* ---------------------------------------------------------------- */
Expand Down Expand Up @@ -226,21 +287,8 @@ __cold static int webrtc_aec_prepare(struct processing_module *mod,
return -EINVAL;
}

if (num_of_sources == 1) {
cd->mic_src = 0;
cd->ref_src = -1;
} else if (source_get_pipeline_id(sources[0]) == sink_get_pipeline_id(sinks[0]) &&
source_get_pipeline_id(sources[1]) != sink_get_pipeline_id(sinks[0])) {
cd->mic_src = 0;
cd->ref_src = 1;
} else if (source_get_pipeline_id(sources[1]) == sink_get_pipeline_id(sinks[0]) &&
source_get_pipeline_id(sources[0]) != sink_get_pipeline_id(sinks[0])) {
cd->mic_src = 1;
cd->ref_src = 0;
} else {
cd->mic_src = 0;
cd->ref_src = 1;
}
webrtc_aec_resolve_sources(sources, num_of_sources, sinks, num_of_sinks,
&cd->mic_src, &cd->ref_src);

mic_fmt = source_get_frm_fmt(sources[cd->mic_src]);
mic_rate = source_get_rate(sources[cd->mic_src]);
Expand Down Expand Up @@ -313,7 +361,8 @@ __cold static int webrtc_aec_prepare(struct processing_module *mod,

#ifdef CONFIG_IPC_MAJOR_4
/* Apply reference format override from topology pin descriptor. */
if (cd->ref_src >= 0)
if (cd->ref_src >= 0 && mod->priv.cfg.nb_input_pins > 1 &&
mod->priv.cfg.input_pins)
ipc4_update_source_format(sources[cd->ref_src],
&mod->priv.cfg.input_pins[1].audio_fmt);
#endif
Expand Down Expand Up @@ -343,29 +392,52 @@ static int webrtc_aec_process(struct processing_module *mod,
struct sof_sink **sinks, int num_of_sinks)
{
struct webrtc_aec_comp_data *cd = module_get_private_data(mod);
struct sof_source *mic = sources[cd->mic_src];
struct sof_source *ref = cd->ref_src >= 0 ? sources[cd->ref_src] : NULL;
struct sof_sink *out = sinks[0];
int fmic = (int)source_get_data_frames_available(mic);
int fref = ref ? (int)source_get_data_frames_available(ref) : 0;
int n, drain, c;

if (fmic <= 0)
struct sof_source *mic;
struct sof_source *ref;
struct sof_sink *out;
int mic_idx, ref_idx;
int fmic, fref, n, drain, c;
bool ref_s32;

if (num_of_sources < 1 || num_of_sinks < 1)
return 0;

/* Cap to available space in input accumulation buffers */
webrtc_aec_resolve_sources(sources, num_of_sources, sinks, num_of_sinks,
&mic_idx, &ref_idx);
cd->mic_src = mic_idx;
cd->ref_src = ref_idx;

mic = sources[mic_idx];
ref = ref_idx >= 0 ? sources[ref_idx] : NULL;
out = sinks[0];
fmic = (int)source_get_data_frames_available(mic);
fref = ref ? (int)source_get_data_frames_available(ref) : 0;

/* Cap to available space in input accumulation and output sink buffers */
n = MIN(fmic, WEBRTC_AEC_FIFO_FRAMES - cd->buffered_in_frames);
if (n <= 0)
n = MIN(n, (int)sink_get_free_frames(out));
if (n <= 0) {
if (ref && fref > 0) {
size_t fb = source_get_frame_bytes(ref);
int keep = fb ? (int)(source_get_min_available(ref) / fb) : 0;

if (fref > keep)
src_drop_frames(ref, fref - keep);
}
return 0;
}

/* Convert mic input to per-channel S16 */
src_to_s16(mic, n, cd->mic_buf, cd->buffered_in_frames, cd->channels, cd->is_s32);

/* Convert ref input to per-channel S16; if starved/silent, fill with silence */
ref_s32 = ref ? (source_get_frm_fmt(ref) == SOF_IPC_FRAME_S32_LE) : cd->is_s32;
if (fref >= n) {
src_to_s16(ref, n, cd->ref_buf, cd->buffered_in_frames, cd->channels, cd->is_s32);
if (fref > n)
src_drop_frames(ref, fref - n);
src_to_s16(ref, n, cd->ref_buf, cd->buffered_in_frames, cd->channels, ref_s32);
} else if (fref > 0) {
src_to_s16(ref, fref, cd->ref_buf, cd->buffered_in_frames, cd->channels, cd->is_s32);
src_to_s16(ref, fref, cd->ref_buf, cd->buffered_in_frames, cd->channels, ref_s32);
for (c = 0; c < cd->channels; c++)
memset(&cd->ref_buf[c][cd->buffered_in_frames + fref], 0,
(size_t)(n - fref) * sizeof(int16_t));
Expand Down Expand Up @@ -648,17 +720,27 @@ static bool webrtc_aec_is_ready_to_process(struct processing_module *mod,
int num_of_sinks)
{
struct webrtc_aec_comp_data *cd = module_get_private_data(mod);
struct sof_source *mic;
struct sof_source *mic, *ref;
struct sof_sink *out;
int mic_idx, ref_idx;

if (!cd || !cd->configured || num_of_sources <= cd->mic_src || num_of_sinks < 1)
if (!cd || !cd->configured || num_of_sources < 1 || num_of_sinks < 1)
return false;

mic = sources[cd->mic_src];
webrtc_aec_resolve_sources(sources, num_of_sources, sinks, num_of_sinks,
&mic_idx, &ref_idx);
mic = sources[mic_idx];
ref = ref_idx >= 0 ? sources[ref_idx] : NULL;
out = sinks[0];

return source_get_data_available(mic) >= source_get_min_available(mic) &&
sink_get_free_size(out) >= sink_get_min_free_space(out);
if (source_get_data_available(mic) >= source_get_min_available(mic) &&
sink_get_free_size(out) >= sink_get_min_free_space(out))
return true;

if (ref && source_get_data_available(ref) >= 2 * source_get_min_available(ref))
return true;

return false;
}

static const struct module_interface webrtc_aec_interface = {
Expand Down
12 changes: 11 additions & 1 deletion src/audio/webrtc_aec/webrtc_aec.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ set(WEBRTC_AECM_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/webrtc-aecm-install"

set(_aecm_src "${SOF_WEBRTC_APM_SRC_DIR}/webrtc")

if("${ARCH}" STREQUAL "xtensa")
if(CONFIG_LLEXT_BUILD_PIC)
set(_aecm_arch_cflags "-fPIC -mlongcalls -mtext-section-literals")
else()
set(_aecm_arch_cflags "-fno-pic -fno-pie -mlongcalls -mtext-section-literals")
endif()
else()
set(_aecm_arch_cflags "-fPIC")
endif()

file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/webrtc-aecm-build.sh"
"#!/bin/sh
set -e
Expand All @@ -42,7 +52,7 @@ OBJ=${CMAKE_CURRENT_BINARY_DIR}/webrtc-aecm-obj

mkdir -p \"$OBJ\" \"$INST/lib\" \"$INST/include\" \"$INST/include/webrtc\"

CFLAGS=\"-O2 -fPIC -I${SOF_WEBRTC_APM_SRC_DIR} -I$SRC -I$SRC/common_audio/signal_processing/include -DWEBRTC_ARCH_32_BITS= -DWEBRTC_ARCH_LITTLE_ENDIAN= -Dmalloc=webrtc_malloc -Dcalloc=webrtc_calloc -Drealloc=webrtc_realloc -Dfree=webrtc_free\"
CFLAGS=\"-O2 ${_aecm_arch_cflags} -DNDEBUG -I${SOF_WEBRTC_APM_SRC_DIR} -I$SRC -I$SRC/common_audio/signal_processing/include -DWEBRTC_ARCH_32_BITS= -DWEBRTC_ARCH_LITTLE_ENDIAN= -Dmalloc=webrtc_malloc -Dcalloc=webrtc_calloc -Drealloc=webrtc_realloc -Dfree=webrtc_free\"

# AECm core
SRCS=\"
Expand Down
1 change: 1 addition & 0 deletions src/audio/webrtc_aec/webrtc_aec.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
domain_types = "1"
load_type = LOAD_TYPE
module_type = "9"
init_config = "1"
auto_start = "0"
sched_caps = [1, 0x00008000]
REM # pin = [dir, type, sample rate, size, container, channel-cfg]
Expand Down
Loading
Loading