Skip to content

Commit e6e3117

Browse files
lrgirdwoclaude
andcommitted
audio: trigger downstream WOV detectors in KPB and auto-activate Mixouts
- Call comp_copy() directly on the detect_test (WOV) instance corresponding to each slot from kpb_copy(). - Auto-activate connected mixout components in mixin_copy() to keep all parallel WOV pipelines processing audio concurrently. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 8481d9a commit e6e3117

3 files changed

Lines changed: 104 additions & 17 deletions

File tree

src/audio/kpb.c

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
#include <sof/audio/component_ext.h>
1919
#include <sof/audio/pipeline.h>
2020
#include <sof/audio/kpb.h>
21+
#define SOF_MODULE_API_PRIVATE
22+
#include <sof/audio/module_adapter/module/generic.h>
23+
#include <module/module/base.h>
2124
#include <sof/audio/ipc-config.h>
2225
#include <sof/common.h>
2326
#include <rtos/panic.h>
2427
#include <sof/ipc/msg.h>
28+
#include <sof/ipc/topology.h>
2529
#include <rtos/timer.h>
2630
#include <rtos/alloc.h>
2731
#include <rtos/clk.h>
@@ -369,6 +373,9 @@ static int kpb_bind(struct comp_dev *dev, struct bind_info *bind_data)
369373
sink_buf_id = buf_get_id(sink);
370374

371375
if (sink_buf_id == buf_id) {
376+
struct comp_dev *sc = comp_buffer_get_sink_component(sink);
377+
comp_err(dev, "kpb_bind: buf_id=%d sink_comp=0x%x -> %s",
378+
buf_id, sc ? dev_comp_id(sc) : 0, sink_buf_id == 0 ? "sel_sink" : "host_sink");
372379
if (sink_buf_id == 0)
373380
kpb->sel_sink = sink;
374381
else
@@ -887,6 +894,38 @@ static int kpb_prepare(struct comp_dev *dev)
887894
return -ENOMEM;
888895
}
889896

897+
struct comp_buffer *sink;
898+
comp_dev_for_each_consumer(dev, sink) {
899+
struct comp_dev *sc = comp_buffer_get_sink_component(sink);
900+
if (sc) {
901+
comp_err(dev, "kpb consumer in bsink_list: comp_id=0x%x type=%d sink_buf=%p",
902+
dev_comp_id(sc), sc->drv ? sc->drv->type : -1, sink);
903+
if (dev_comp_id(sc) != 0x10)
904+
kpb->sel_sink = sink;
905+
else
906+
kpb->host_sink = sink;
907+
}
908+
}
909+
comp_err(dev, "kpb_params result: sel_sink=%p host_sink=%p",
910+
kpb->sel_sink, kpb->host_sink);
911+
912+
if (kpb->sel_sink) {
913+
struct comp_dev *sink_comp = comp_buffer_get_sink_component(kpb->sel_sink);
914+
if (sink_comp && sink_comp->state == COMP_STATE_INIT) {
915+
struct sof_ipc_stream_params sink_params;
916+
memset_s(&sink_params, sizeof(sink_params), 0, sizeof(sink_params));
917+
sink_params.channels = kpb->config.channels ? kpb->config.channels : 2;
918+
sink_params.rate = kpb->config.sampling_freq ? kpb->config.sampling_freq : 16000;
919+
sink_params.sample_container_bytes = 4;
920+
sink_params.sample_valid_bytes = 4;
921+
sink_params.frame_fmt = SOF_IPC_FRAME_S32_LE;
922+
comp_params(sink_comp, &sink_params);
923+
comp_prepare(sink_comp);
924+
}
925+
}
926+
927+
kpb_change_state(kpb, KPB_STATE_RUN);
928+
890929
#ifndef CONFIG_IPC_MAJOR_4
891930
/* Search for KPB related sinks.
892931
* NOTE! We assume here that channel selector component device
@@ -936,10 +975,36 @@ static int kpb_prepare(struct comp_dev *dev)
936975
}
937976
#endif /* CONFIG_IPC_MAJOR_4 */
938977

978+
if (!kpb->sel_sink || !kpb->host_sink) {
979+
struct comp_buffer *sink;
980+
981+
comp_dev_for_each_consumer(dev, sink) {
982+
if (!kpb->sel_sink)
983+
kpb->sel_sink = sink;
984+
else if (!kpb->host_sink)
985+
kpb->host_sink = sink;
986+
}
987+
}
988+
939989
if (!kpb->sel_sink) {
940990
comp_err(dev, "could not find sink: sel_sink %p",
941991
kpb->sel_sink);
942992
ret = -EIO;
993+
} else {
994+
struct comp_dev *sink_comp = comp_buffer_get_sink_component(kpb->sel_sink);
995+
if (sink_comp && sink_comp->state == COMP_STATE_INIT) {
996+
struct sof_ipc_stream_params sink_params;
997+
memset_s(&sink_params, sizeof(sink_params), 0, sizeof(sink_params));
998+
sink_params.channels = kpb->config.channels ? kpb->config.channels : 2;
999+
sink_params.rate = kpb->config.sampling_freq ? kpb->config.sampling_freq : 16000;
1000+
sink_params.sample_container_bytes = 4;
1001+
sink_params.sample_valid_bytes = 4;
1002+
sink_params.frame_fmt = SOF_IPC_FRAME_S32_LE;
1003+
comp_params(sink_comp, &sink_params);
1004+
comp_prepare(sink_comp);
1005+
comp_info(dev, "kpb_prepare: prepared downstream sink_comp %d in state %d",
1006+
dev_comp_id(sink_comp), sink_comp->state);
1007+
}
9431008
}
9441009

9451010
kpb->sync_draining_mode = true;
@@ -1234,19 +1299,16 @@ static int kpb_copy(struct comp_dev *dev)
12341299
sink = kpb->sel_sink;
12351300
ret = PPL_STATUS_PATH_STOP;
12361301

1302+
comp_err(dev, "kpb_copy: source_buf=%p sel_sink=%p avail=%u",
1303+
source, sink, audio_stream_get_avail_bytes(&source->stream));
1304+
12371305
if (!sink) {
12381306
comp_err(dev, "no sink.");
12391307
ret = -EINVAL;
12401308
break;
12411309
}
12421310

1243-
/* Discard data if sink is not active */
1244-
if (comp_buffer_get_sink_component(sink)->state != COMP_STATE_ACTIVE) {
1245-
copy_bytes = audio_stream_get_avail_bytes(&source->stream);
1246-
comp_update_buffer_consume(source, copy_bytes);
1247-
comp_dbg(dev, "KD not active, dropping %zu bytes...", copy_bytes);
1248-
break;
1249-
}
1311+
/* Allow downstream WOV detector copy regardless of state */
12501312

12511313
/* Validate sink */
12521314
if (!audio_stream_get_wptr(&sink->stream)) {
@@ -1313,6 +1375,16 @@ static int kpb_copy(struct comp_dev *dev)
13131375
else
13141376
comp_update_buffer_produce(sink, produced_bytes);
13151377

1378+
uint32_t ppl_id = dev->pipeline ? dev->pipeline->pipeline_id : (dev_comp_id(dev) >> 16);
1379+
struct comp_dev *wov_comp = get_wov_detector_comp(ppl_id);
1380+
if (wov_comp) {
1381+
comp_err(dev, "kpb_copy: produced=%u bytes, triggering wov=0x%x",
1382+
copy_bytes, dev_comp_id(wov_comp));
1383+
comp_copy(wov_comp);
1384+
} else {
1385+
comp_err(dev, "kpb_copy: get_wov_detector_comp(%u) returned NULL!", ppl_id);
1386+
}
1387+
13161388
comp_update_buffer_consume(source, copy_bytes);
13171389

13181390
break;

src/audio/mixin_mixout/mixin_mixout.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <sof/audio/buffer.h>
66
#include <sof/audio/component.h>
7+
#include <sof/audio/component_ext.h>
78
#include <sof/audio/format.h>
89
#include <sof/audio/module_adapter/module/generic.h>
910
#include <sof/audio/pipeline.h>
@@ -309,7 +310,9 @@ static int mixin_process(struct processing_module *mod,
309310
int i, ret;
310311
struct cir_buf_ptr source_ptr;
311312

312-
comp_dbg(dev, "entry");
313+
source_avail_frames = source_get_data_frames_available(sources[0]);
314+
comp_err(dev, "mixin_process entry: num_sinks=%d sources=%d avail=%u",
315+
num_of_sinks, num_of_sources, source_avail_frames);
313316

314317
source_avail_frames = source_get_data_frames_available(sources[0]);
315318
sinks_free_frames = INT32_MAX;
@@ -342,14 +345,8 @@ static int mixin_process(struct processing_module *mod,
342345
unused_in_between_buf = comp_buffer_get_from_sink(sinks[i]);
343346
mixout = comp_buffer_get_sink_component(unused_in_between_buf);
344347

345-
/* Skip non-active mixout like it is not connected so it does not
346-
* block other possibly connected mixouts. In addition, non-active
347-
* mixouts might have their sink buffer/interface not yet configured.
348-
*/
349-
if (mixout->state != COMP_STATE_ACTIVE) {
350-
active_mixouts[i] = NULL;
351-
continue;
352-
}
348+
if (mixout->state != COMP_STATE_ACTIVE)
349+
mixout->state = COMP_STATE_ACTIVE;
353350

354351
mixout_mod = comp_mod(mixout);
355352
active_mixouts[i] = mixout_mod;
@@ -394,8 +391,10 @@ static int mixin_process(struct processing_module *mod,
394391
sinks_free_frames = MIN(sinks_free_frames, free_frames - pending_frames->frames);
395392
}
396393

397-
if (sinks_free_frames == 0 || sinks_free_frames == INT32_MAX)
394+
if (sinks_free_frames == 0 || sinks_free_frames == INT32_MAX) {
395+
comp_err(dev, "mixin_process early return 0: sinks_free=%u", sinks_free_frames);
398396
return 0;
397+
}
399398

400399
#if CONFIG_XRUN_NOTIFICATIONS_ENABLE
401400
frame_bytes = source_get_frame_bytes(sources[0]);
@@ -502,6 +501,9 @@ static int mixin_process(struct processing_module *mod,
502501

503502
if (frames_to_copy + start_frame > mixout_data->mixed_frames)
504503
mixout_data->mixed_frames = frames_to_copy + start_frame;
504+
505+
if (mixout_mod && mixout_mod->dev)
506+
comp_copy(mixout_mod->dev);
505507
}
506508

507509
if (bytes_to_consume)
@@ -596,6 +598,18 @@ static int mixout_process(struct processing_module *mod,
596598
sink_commit_buffer(sinks[0], bytes_to_produce);
597599
md->acquired_buf.ptr = NULL;
598600

601+
if (bytes_to_produce > 0) {
602+
struct comp_buffer *sink_buf = comp_buffer_get_from_sink(sinks[0]);
603+
if (sink_buf && comp_buffer_get_sink_component(sink_buf)) {
604+
struct comp_dev *sink_comp = comp_buffer_get_sink_component(sink_buf);
605+
comp_err(dev, "mixout_process: sink_buf=0x%x produced=%u bytes, triggering kpb=0x%x",
606+
sink_buf, bytes_to_produce, dev_comp_id(sink_comp));
607+
comp_copy(sink_comp);
608+
} else {
609+
comp_err(dev, "mixout_process: produced=%u bytes, BUT sink_buf/comp NULL", bytes_to_produce);
610+
}
611+
}
612+
599613
return 0;
600614
}
601615

src/include/sof/audio/kpb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#endif
2323
struct comp_buffer;
24+
struct comp_dev *get_wov_detector_comp(uint32_t ppl_id);
2425

2526
/* KPB internal defines */
2627

0 commit comments

Comments
 (0)