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
18 changes: 18 additions & 0 deletions src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
if(CONFIG_COMP_VOLUME)
add_subdirectory(volume)
endif()
if(CONFIG_COMP_WEBRTC_VAD)
add_subdirectory(webrtc_vad)
endif()
Comment thread
lgirdwood marked this conversation as resolved.
if(CONFIG_COMP_WEBRTC_NS)
add_subdirectory(webrtc_ns)
endif()
if(CONFIG_COMP_WEBRTC_AEC)
add_subdirectory(webrtc_aec)
endif()
if(CONFIG_COMP_WEBRTC_NS2)
add_subdirectory(webrtc_ns2)
endif()
if(CONFIG_COMP_WEBRTC_AGC)
add_subdirectory(webrtc_agc)
endif()
if(CONFIG_COMP_WEBRTC_HPF)
add_subdirectory(webrtc_hpf)
endif()
if(CONFIG_DTS_CODEC)
add_subdirectory(codec)
endif()
Expand Down
6 changes: 6 additions & 0 deletions src/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ rsource "tensorflow/Kconfig"
rsource "tone/Kconfig"
rsource "up_down_mixer/Kconfig"
rsource "volume/Kconfig"
rsource "webrtc_vad/Kconfig"
rsource "webrtc_ns/Kconfig"
rsource "webrtc_aec/Kconfig"
rsource "webrtc_ns2/Kconfig"
rsource "webrtc_agc/Kconfig"
rsource "webrtc_hpf/Kconfig"
# --- End Kconfig Sources (alphabetical order) ---

rsource "level_multiplier/Kconfig"
Expand Down
185 changes: 185 additions & 0 deletions src/audio/webrtc_aec/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# SPDX-License-Identifier: BSD-3-Clause

if(CONFIG_COMP_WEBRTC_AEC STREQUAL "m" AND DEFINED CONFIG_LLEXT)
add_subdirectory(llext ${PROJECT_BINARY_DIR}/webrtc_aec_llext)
add_dependencies(app webrtc_aec)
else()
add_local_sources(sof webrtc_aec.c)
if(CONFIG_COMP_WEBRTC_AEC_STUB)
add_local_sources(sof webrtc_aec-stub.c)
else()
if(NOT DEFINED SOF_WEBRTC_APM_SRC_DIR)
set(SOF_WEBRTC_APM_SRC_DIR "${sof_top_dir}/../modules/audio/webrtc-apm"
CACHE PATH "webrtc-audio-processing 0.3.x source directory")
endif()
cmake_path(NORMAL_PATH SOF_WEBRTC_APM_SRC_DIR)

zephyr_include_directories(
"${SOF_WEBRTC_APM_SRC_DIR}"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aecm/include"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/include"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/include"
)

zephyr_compile_definitions(
WEBRTC_ARCH_32_BITS
WEBRTC_ARCH_LITTLE_ENDIAN
)

set(_clang_fp_flags "")
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(_clang_fp_flags "-Xclang;-target-feature;-Xclang;-fp")
endif()

if(CONFIG_WEBRTC_AEC_BACKEND_AEC3)
if(DEFINED CONFIG_SOC_TOOLCHAIN_NAME)
set(_xtensa_target "${CONFIG_SOC_TOOLCHAIN_NAME}")
else()
set(_xtensa_target "intel_ace30_ptl")
endif()
set(_sdk_cxx_dir "/home/lrg/zephyr-sdk-1.0.1/gnu/xtensa-${_xtensa_target}_zephyr-elf/xtensa-${_xtensa_target}_zephyr-elf")

target_include_directories(zephyr_interface SYSTEM BEFORE INTERFACE
$<$<COMPILE_LANGUAGE:CXX>:${_sdk_cxx_dir}/include/c++/14.3.0>
$<$<COMPILE_LANGUAGE:CXX>:${_sdk_cxx_dir}/include/c++/14.3.0/xtensa-${_xtensa_target}_zephyr-elf>
$<$<COMPILE_LANGUAGE:CXX>:${_sdk_cxx_dir}/include>
)

# Do not link heavy libstdc++.a to prevent out-of-range relocations and unwinder bloat.
# Minimal C++ runtime, new/delete, and exception stubs are provided in webrtc_aec3_shims.cpp.

add_local_sources(sof
webrtc_aec-aec3.c
webrtc_aec-math.c
webrtc_aec3_wrapper.cpp
webrtc_aec3_shims.cpp
)

file(GLOB _aec3_srcs
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec3/*.cc"
)
list(FILTER _aec3_srcs EXCLUDE REGEX ".*_(avx2|neon|mips|sse2)\\.cc$")

set(_aec3_support_srcs
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/api/audio/echo_canceller3_config.cc"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/third_party/ooura/fft_size_128/ooura_fft.cc"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/high_pass_filter.cc"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/utility/cascaded_biquad_filter.cc"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec3_buffer/audio_buffer.cc"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/logging/apm_data_dumper.cc"
)

add_local_sources(sof ${_aec3_srcs} ${_aec3_support_srcs})

set(_aec3_cxx_all
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec3_wrapper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec3_shims.cpp
${_aec3_srcs}
${_aec3_support_srcs}
)

set_source_files_properties(
${_aec3_cxx_all}
TARGET_DIRECTORY modules_sof
PROPERTIES COMPILE_OPTIONS "-std=c++17;-fno-exceptions;-fno-rtti;-O3;-fno-vectorize;-fno-slp-vectorize;${_clang_fp_flags};-DWEBRTC_POSIX;-DWEBRTC_ARCH_GENERIC;-DWEBRTC_APM_DEBUG_DUMP=0;-DRTC_DISABLE_METRICS;-DNDEBUG;-Wno-macro-redefined;-Wno-unused-function;-Wno-double-promotion"
)
elseif(CONFIG_WEBRTC_AEC_BACKEND_FLOAT)
add_local_sources(sof webrtc_aec-aec.c webrtc_aec-math.c)
add_local_sources(sof
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/echo_cancellation.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/aec_core.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/aec_rdft.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/aec_resampler.c"
)
else()
add_local_sources(sof webrtc_aec-aecm.c)
add_local_sources(sof
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aecm/echo_control_mobile.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aecm/aecm_core.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aecm/aecm_core_c.c"
)
endif()

add_local_sources(sof webrtc_aec-shims.c)
add_local_sources(sof
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/ring_buffer.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/utility/delay_estimator.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/complex_bit_reverse.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/complex_fft.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/cross_correlation.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/downsample_fast.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/real_fft.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/vector_scaling_operations.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/min_max_operations.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/spl_sqrt_floor.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/randomization_functions.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/spl_init.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/spl_sqrt.c"
)

add_local_sources(sof
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/division_operations.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/resample_by_2_internal.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/resample_fractional.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/resample_48khz.c"
)

set(_webrtc_aec_srcs
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/ring_buffer.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/utility/delay_estimator.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/complex_bit_reverse.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/complex_fft.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/cross_correlation.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/downsample_fast.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/real_fft.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/vector_scaling_operations.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/min_max_operations.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/spl_sqrt_floor.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/randomization_functions.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/spl_init.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/spl_sqrt.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/resample_48khz.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/resample_by_2_internal.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/common_audio/signal_processing/resample_fractional.c"
)

list(APPEND _webrtc_aec_srcs
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec.c
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec-shims.c
)

if(CONFIG_WEBRTC_AEC_BACKEND_AEC3)
list(APPEND _webrtc_aec_srcs
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec-aec3.c
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec-math.c
)
elseif(CONFIG_WEBRTC_AEC_BACKEND_FLOAT)
list(APPEND _webrtc_aec_srcs
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec-aec.c
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec-math.c
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/echo_cancellation.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/aec_core.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/aec_rdft.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aec/aec_resampler.c"
)
else()
list(APPEND _webrtc_aec_srcs
${CMAKE_CURRENT_SOURCE_DIR}/webrtc_aec-aecm.c
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aecm/echo_control_mobile.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aecm/aecm_core.c"
"${SOF_WEBRTC_APM_SRC_DIR}/webrtc/modules/audio_processing/aecm/aecm_core_c.c"
)
endif()

set_source_files_properties(
${_webrtc_aec_srcs}
TARGET_DIRECTORY modules_sof
PROPERTIES COMPILE_OPTIONS "-O3;${_clang_fp_flags};-Wno-double-promotion;-Wno-implicit-function-declaration;-Wno-unused-function;-Dmalloc=webrtc_malloc;-Dcalloc=webrtc_calloc;-Drealloc=webrtc_realloc;-Dfree=webrtc_free"
)
endif()
endif()
98 changes: 98 additions & 0 deletions src/audio/webrtc_aec/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# SPDX-License-Identifier: BSD-3-Clause

config COMP_WEBRTC_AEC
tristate "WebRTC AECm — fixed-point Acoustic Echo Canceller"
help
Select to include the WebRTC AECm (Mobile) acoustic echo canceller.
AECm is a fixed-point Q15 implementation derived from the WebRTC
audio processing library. It requires no floating-point unit and is
well suited to Xtensa HiFi3/HiFi4 class DSPs.

The module accepts two input streams (2 input pins):
Pin 0 — microphone capture (same pipeline as the output)
Pin 1 — playback echo reference (from the render pipeline)
and produces one denoised microphone output stream.

This module is intended as an open-source drop-in replacement for
the google_rtc_audio_processing module that requires a proprietary
library. Both implement the same two-input / one-output topology so
topologies are interchangeable.

The real backend requires webrtc-audio-processing 0.3.x source
(west module modules/audio/webrtc-apm, same as COMP_WEBRTC_NS).
For CI/testing without that source, select COMP_WEBRTC_AEC_STUB.

if COMP_WEBRTC_AEC

choice WEBRTC_AEC_BACKEND
prompt "WebRTC AEC processing backend"
default WEBRTC_AEC_BACKEND_FLOAT if COMP_WEBRTC_AEC = y
default WEBRTC_AEC_BACKEND_AECM

config WEBRTC_AEC_BACKEND_FLOAT
bool "Classic Float AEC (Multidelay Block Frequency Domain with hardware FPU)"
depends on COMP_WEBRTC_AEC = y
help
Single-precision floating-point AEC using partitioned-block
frequency domain adaptive filtering (MDF) accelerated by the
hardware FPU and HiFi4 VFPU.

config WEBRTC_AEC_BACKEND_AEC3
bool "Modern WebRTC AEC3 (State-of-the-art C++17 Echo Canceller)"
depends on COMP_WEBRTC_AEC = y
help
Modern WebRTC AEC3 with matched filter delay estimator, multi-partition
linear adaptive filter, non-linear suppression, and full-band ERLE estimator.

config WEBRTC_AEC_PERF_TELEMETRY
bool "Enable AEC3 cycle profiling telemetry via printk"
default y
depends on WEBRTC_AEC_BACKEND_AEC3
help
Periodically emits [AEC3_P1] and [AEC3_P2] cycle count breakdowns
every 200ms to monitor DSP cycle budgets.

config WEBRTC_AEC_BACKEND_AECM
bool "AECm (Mobile fixed-point integer AEC)"
help
Pure integer Q15 fixed-point echo cancellation. Low memory (~12 KB/ch)
and low CPU (~1.5 MCPS).

config COMP_WEBRTC_AEC_STUB
bool "WebRTC AEC stub backend (no WebRTC source dependency)"
help
Build the webrtc_aec module against a dependency-free stub backend
that passes microphone audio through without modification.
endchoice

config WEBRTC_AEC_FILTER_LEN_MS
int "AECm adaptive filter length in ms (32, 64 or 128)"
default 64
help
Length of the adaptive echo-cancellation filter. Longer filters
can handle larger acoustic echo delays (e.g. in rooms with long
reverb tails) at the cost of increased memory and CPU.
Valid values: 32, 64, 128.

config WEBRTC_AEC_SUPPRESSION_LEVEL
int "AECm comfort-noise suppression level (0=off, 1=low, 2=medium)"
range 0 2
default 1
help
Controls how aggressively residual echo / background noise is
suppressed in the CNG (comfort noise generator) post-filter:
0 - disabled (only echo suppression, no CNG)
1 - low suppression (recommended)
2 - medium suppression

config WEBRTC_AEC_SAMPLE_RATE_HZ
int "AECm processing sample rate in Hz"
default 16000
help
AECm operates at 8000 or 16000 Hz. When the pipeline runs at a
higher rate (e.g. 48 kHz), the module downsamples before AEC
processing and upsamples afterward. 16 kHz is recommended for
best echo suppression quality.
Valid values: 8000, 16000.

endif # COMP_WEBRTC_AEC
Loading
Loading