Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
002f765
audio: kpb: add multi-client downstream WOV detector triggering and d…
lrgirdwo Sep 6, 2026
c549ccf
audio: ams: add WOV detect and control message definitions
lrgirdwo Sep 6, 2026
9a870f6
audio: wov_arbiter: add multi-slot WOV arbiter component
lrgirdwo Sep 6, 2026
1f52b35
app: enable WOV arbiter and KPB on intel_adsp_cavs25
lrgirdwo Sep 6, 2026
6c05aea
audio: detect_test: add multi-slot WOV support with DP thread batching
lrgirdwo Sep 6, 2026
1943843
audio: pipeline: support dynamic routing for WOV capture
lrgirdwo Sep 6, 2026
bd280d2
topology: wov: add multi-slot Wake-on-Voice and regular PCM capture m…
lrgirdwo Sep 6, 2026
db86bfd
tools: wov_capture: add multi-cycle WOV capture application and test …
lrgirdwo Sep 6, 2026
536d447
doc: wov_arbiter: add architecture and usage guide for multi-slot WOV
lrgirdwo Sep 6, 2026
db24f8f
topology2: add multi-slot Wake-on-Voice topologies for PTL and WCL
lrgirdwo Sep 7, 2026
32dab9b
topology2: add 4-channel 16kHz native DMIC multi-slot WOV topologies …
lrgirdwo Sep 7, 2026
8d97fe3
doc: add topology NHLT generation and BIOS NHLT override to READMEs
lrgirdwo Sep 7, 2026
fe80256
topology2: align multi-slot WOV topologies to 3-fanout mixin architec…
lrgirdwo Sep 7, 2026
50d2af1
ptl: enable WOV arbiter and KPB for Panther Lake
lrgirdwo Sep 7, 2026
27a02c6
audio: add ECNS DP module with 20ms period, 4ch split, 1ch KPB buffer…
lrgirdwo Sep 7, 2026
afbf1ae
doc: add 4-channel ECNS and Multi-Slot WOV topology architecture diag…
lrgirdwo Sep 7, 2026
a9c8966
llext: add missing modules to WCL overlay
naveen-manohar Sep 3, 2026
66c07b0
topology2: kpb: add default KPB_BUFF_TIME_MS
naveen-manohar Sep 4, 2026
54e83df
topology2: add DMIC WoV feature topology target
naveen-manohar Sep 4, 2026
c262bdf
topology2: wcl: enable NHLT-override WoV capture on PCM 11
naveen-manohar Sep 7, 2026
91bd09b
topology2: wcl: wire ecns.toml into the rimage config
naveen-manohar Sep 8, 2026
5dd5694
topology2: wcl: integrate ECNS into WoV
naveen-manohar Sep 8, 2026
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
9 changes: 9 additions & 0 deletions app/boards/intel_adsp_ace30_ptl.conf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=m
CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK=y
CONFIG_COMP_STFT_PROCESS=y

# WOV Arbiter, KPB, Mixin/Mixout and Sample Detector
CONFIG_COMP_MIXIN_MIXOUT=y
CONFIG_COMP_WOV_ARBITER=y
CONFIG_COMP_KPB=y
CONFIG_KPB_MAX_BUFF_TIME=2000
CONFIG_COMP_ECNS=y
CONFIG_SAMPLES=y
CONFIG_SAMPLE_KEYPHRASE=y

# SOF / infrastructure
CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n
CONFIG_PROBE=y
Expand Down
6 changes: 6 additions & 0 deletions app/boards/intel_adsp_ace30_wcl.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ CONFIG_FORMAT_CONVERT_HIFI3=n
# SOF / audio modules / mocks
# This mock is part of official sof-bin releases because the CI that
# tests it can't use extra CONFIGs. See #9410, #8722 and #9386
# Google hotword needs the proprietary hotword_dsp_api.h and an ACE30 library build
CONFIG_COMP_GOOGLE_HOTWORD_DETECT=n
CONFIG_COMP_WOV_ARBITER=y
CONFIG_COMP_ECNS=y
# Post-ECNS KPB is mono 16-bit: 2000 ms needs 64000 B, well within the DSP heap
CONFIG_KPB_MAX_BUFF_TIME=2000
CONFIG_COMP_GOOGLE_RTC_AUDIO_PROCESSING=m
CONFIG_GOOGLE_RTC_AUDIO_PROCESSING_MOCK=y
CONFIG_COMP_STFT_PROCESS=y
Expand Down
4 changes: 4 additions & 0 deletions app/boards/intel_adsp_cavs25.conf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ CONFIG_COMP_DRC=y
CONFIG_COMP_MFCC=y
CONFIG_COMP_MULTIBAND_DRC=y
CONFIG_COMP_VOLUME_WINDOWS_FADE=y
CONFIG_COMP_WOV_ARBITER=y
CONFIG_COMP_KPB=y
CONFIG_SAMPLES=y
CONFIG_SAMPLE_KEYPHRASE=y
CONFIG_FORMAT_CONVERT_HIFI3=n
CONFIG_PCM_CONVERTER_FORMAT_S16LE=y
CONFIG_PCM_CONVERTER_FORMAT_S24LE=y
Expand Down
2 changes: 2 additions & 0 deletions app/configs/wcl/modules.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_COMP_TDFB=m
CONFIG_COMP_VOLUME=m
6 changes: 6 additions & 0 deletions src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
if(CONFIG_COMP_DRC)
add_subdirectory(drc)
endif()
if(CONFIG_COMP_ECNS)
add_subdirectory(ecns)
endif()
if(CONFIG_COMP_FIR)
add_subdirectory(eq_fir)
endif()
Expand Down Expand Up @@ -107,6 +110,9 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
if(CONFIG_COMP_VOLUME)
add_subdirectory(volume)
endif()
if(CONFIG_COMP_WOV_ARBITER)
add_subdirectory(wov_arbiter)
endif()
if(CONFIG_DTS_CODEC)
add_subdirectory(codec)
endif()
Expand Down
35 changes: 35 additions & 0 deletions src/audio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,48 @@ config COMP_STUBS
Select to force all 3P blocks to link against stubs rather than their libraries. This
should only be used in testing environments like fuzzers or CI.

config COMP_WOV_ARBITER
bool "WOV arbiter component"
depends on COMP_KPB
depends on IPC_MAJOR_4
help
Select to build the WOV (Wake-on-Voice) arbiter. The arbiter sits
between multiple KPB host-drain outputs and a single host PCM copier.
When a keyword is detected by one of the WOV detectors the arbiter
routes that KPB's drain stream to the host and instructs the remaining
detectors to pause.

config COMP_ECNS
bool "ECNS data processing component"
default y
depends on IPC_MAJOR_4
help
Select to build the ECNS (Echo Cancellation and Noise Suppression)
Data Processing (DP) component. Operates with a 20ms period to process
4 DMIC channels (2 mics + 2 echo references) and outputs clean mono
to KPB and clean stereo to host capture.

config COMP_KPB
bool "KPB component"
default y
help
Select for KPB component
if COMP_KPB

config KPB_MAX_NO_OF_CLIENTS
int "Maximum number of KPB clients"
default 4
help
Maximum number of simultaneous KPB drain clients (host + WOV detectors).
Increase if more than 4 clients need concurrent KPB access.

config KPB_MAX_BUFF_TIME
int "KPB history buffer time (ms)"
default 6000 if XCHAL_HW_VERSION_MAJOR >= 300
default 2100
help
KPB history ring-buffer length in milliseconds.

config KPB_FORCE_COPY_TYPE_NORMAL
bool "KPB force copy type normal"
default y
Expand Down
16 changes: 12 additions & 4 deletions src/audio/copier/copier_dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,13 +415,21 @@ __cold void copier_dai_free(struct processing_module *mod)
assert_can_be_cold();

for (int i = 0; i < cd->endpoint_num; i++) {
dai_common_free(cd->dd[i]);
mod_free(mod, cd->dd[i]->gain_data);
mod_free(mod, cd->dd[i]);
if (cd->dd[i]) {
if (cd->dd[i]->gain_data) {
mod_free(mod, cd->dd[i]->gain_data);
cd->dd[i]->gain_data = NULL;
}
dai_common_free(cd->dd[i]);
mod_free(mod, cd->dd[i]);
cd->dd[i] = NULL;
}
}
/* only dai have multi endpoint case */
if (cd->multi_endpoint_buffer)
if (cd->multi_endpoint_buffer) {
buffer_free(cd->multi_endpoint_buffer);
cd->multi_endpoint_buffer = NULL;
}
}

int copier_dai_prepare(struct comp_dev *dev, struct copier_data *cd)
Expand Down
30 changes: 25 additions & 5 deletions src/audio/dai-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,25 +683,40 @@ __cold void dai_common_free(struct dai_data *dd)
{
assert_can_be_cold();

if (!dd)
return;

#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS
io_perf_monitor_release_slot(dd->io_perf_dai_byte_count);
#endif

if (dd->group)
if (dd->group) {
dai_group_put(dd->group);
dd->group = NULL;
}

if (dd->chan_index >= 0) {
sof_dma_release_channel(dd->dma, dd->chan_index);
if (dd->dma)
sof_dma_release_channel(dd->dma, dd->chan_index);
dd->chan_index = -EINVAL;
}

sof_dma_put(dd->dma);
if (dd->dma) {
sof_dma_put(dd->dma);
dd->dma = NULL;
}

dai_release_llp_slot(dd);

dai_put(dd->dai);
if (dd->dai) {
dai_put(dd->dai);
dd->dai = NULL;
}

sof_heap_free(dd->alloc_ctx.heap, dd->dai_spec_config);
if (dd->dai_spec_config) {
sof_heap_free(dd->alloc_ctx.heap, dd->dai_spec_config);
dd->dai_spec_config = NULL;
}
}

__cold static void dai_free(struct comp_dev *dev)
Expand All @@ -710,6 +725,11 @@ __cold static void dai_free(struct comp_dev *dev)

assert_can_be_cold();

if (!dd) {
comp_free_device(dev);
return;
}

if (dd->group)
notifier_unregister(dev, dd->group, NOTIFIER_ID_DAI_TRIGGER);

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

add_local_sources(sof ecns.c)
77 changes: 77 additions & 0 deletions src/audio/ecns/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# ECNS (Echo Cancellation & Noise Suppression) Processing Module

## Overview

The `ecns` component is an IPC4 Data Processing (DP) module operating at a 20 ms period (320 samples at 16 kHz). It consumes a 4-channel audio stream comprising:
- **Channels 0 & 1**: Primary microphone inputs.
- **Channels 2 & 3**: Far-end echo reference inputs.

The module performs echo cancellation and noise suppression, delivering two distinct output streams via separate output pins:
1. **Output Pin 0 (Mono Clean Mic)**: Provides a single-channel, echo-canceled and noise-suppressed speech stream intended for keyword detection and pre-roll buffering in the Key Phrase Buffer (`kpb`).
2. **Output Pin 1 (Stereo Clean Mic)**: Provides a two-channel clean speech stream routed directly or via a host mixin/mixout bridge to a standard ALSA capture device (e.g. `hw:0,10`).

---

## Topology Architecture

```mermaid
graph LR
subgraph Capture["Pipeline 100 — 4ch DMIC"]
DAI["DAI Copier (4ch 16kHz)"] --> M100["mixin 100.1"]
end

subgraph ECNS_DP["Pipeline 105 — ECNS DP Module (20ms / 320 frames)"]
M100 --> MO105["mixout 105.1"]
MO105 --> ECNS["ecns.105.1\n(UUID: 214f8a6c-493a-4b1e-8b1e0d3b6f8a2c15)"]
ECNS -- "Pin 0 (1ch Mono)" --> MIX105_1["mixin 105.1 (KPB Mixin)"]
ECNS -- "Pin 1 (2ch Stereo)" --> MIX105_2["mixin 105.2 (Host Mixin)"]
end

subgraph WOV_Path["Pipeline 106 & 104 — WOV / KPB Path"]
MIX105_1 --> MO106["mixout 106.1"]
MO106 --> KPB["kpb.106.1\n(2.0s mono / 64 KB)"]
KPB --> WOV["WOV Slots 0..2"] --> ARB["wov_arbiter.104.1"]
ARB --> HC11["host-copier.11\n(ALSA hw:0,11)"]
end

subgraph Host_Path["Pipeline 107 — ECNS Host Capture Path"]
MIX105_2 --> MO107["mixout 107.1"]
MO107 --> HC10["host-copier.10\n(ALSA hw:0,10)"]
end

style ECNS fill:#1b4f72,stroke:#555,color:#fff
style KPB fill:#1c4966,stroke:#555,color:#fff
style ARB fill:#4a235a,stroke:#555,color:#fff
style HC10 fill:#1e8449,stroke:#555,color:#fff
style HC11 fill:#2d5a27,stroke:#555,color:#fff
```

---

## Specifications

| Parameter | Specification |
|---|---|
| Module UUID | `214f8a6c-493a-4b1e-8b1e0d3b6f8a2c15` |
| Processing Domain | DP (Data Processing) thread |
| Execution Period | 20 ms (320 samples at 16 kHz) |
| Input Channels | 4 (Ch 0,1: Microphones; Ch 2,3: Echo Reference) |
| Input Format | 16 kHz · 16-bit signed little-endian (`S16_LE`) |
| Output Pin 0 | 1 channel (Mono clean mic) · 16 kHz · `S16_LE` · OBS = 640 bytes (20ms) |
| Output Pin 1 | 2 channels (Stereo clean mic) · 16 kHz · `S16_LE` · OBS = 1280 bytes (20ms) |
| Sinks Acceptance | Independent sink buffer limit checks (`kpb_frames` vs `host_frames`) |
| Dynamic Pipeline | Compatible (`dynamic_pipeline 1`) |

---

## Verification & Usage

### 1. Recording Clean Stereo Audio (Pin 1 / PCM 10)
```bash
arecord -D hw:0,10 -c 2 -r 16000 -f S16_LE -d 3 /tmp/ecns_stereo.wav
```

### 2. Recording Keyword Detection Pre-Roll Audio (Pin 0 / PCM 11)
```bash
arecord -D hw:0,11 -c 1 -r 16000 -f S16_LE -d 3 /tmp/wov_mono.wav
```
Loading