-
Notifications
You must be signed in to change notification settings - Fork 366
kpb: add multi-KPB WOV arbiter for 3-keyword DMIC capture with VAD #11022
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7eea7d5
c5675c0
54a8f62
9b6e80c
c65809a
d9644ed
b0ea67a
3af37c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,3 +31,8 @@ CONFIG_GDBSTUB_ENTER_IMMEDIATELY=n | |
| # Testing with runtime filtering enabled ensures the same feature set is validated. | ||
| # Note: This setting has no effect if CONFIG_LOG_RUNTIME_FILTERING is disabled. | ||
| CONFIG_LOG_RUNTIME_DEFAULT_LEVEL=3 | ||
|
|
||
| # Record fatal exception breadcrumbs (PC/cause/vaddr) in HP-SRAM window0 so the | ||
| # crash is visible in the host dmesg "Firmware state" line when no console or | ||
| # mtrace output is available. | ||
| CONFIG_XTENSA_ADSP_FATAL_BREADCRUMB=y | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not part of this patch. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,9 +104,15 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) | |
| if(CONFIG_COMP_UP_DOWN_MIXER) | ||
| add_subdirectory(up_down_mixer) | ||
| endif() | ||
| if(CONFIG_COMP_VAD_GATE) | ||
| add_subdirectory(vad_gate) | ||
| endif() | ||
|
Comment on lines
+107
to
+109
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be in the vad gate patch. |
||
| 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() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,10 +18,14 @@ | |
| #include <sof/audio/component_ext.h> | ||
| #include <sof/audio/pipeline.h> | ||
| #include <sof/audio/kpb.h> | ||
| #define SOF_MODULE_API_PRIVATE | ||
| #include <sof/audio/module_adapter/module/generic.h> | ||
| #include <module/module/base.h> | ||
| #include <sof/audio/ipc-config.h> | ||
| #include <sof/common.h> | ||
| #include <rtos/panic.h> | ||
| #include <sof/ipc/msg.h> | ||
| #include <sof/ipc/topology.h> | ||
| #include <rtos/timer.h> | ||
| #include <rtos/alloc.h> | ||
| #include <rtos/clk.h> | ||
|
|
@@ -369,6 +373,9 @@ static int kpb_bind(struct comp_dev *dev, struct bind_info *bind_data) | |
| sink_buf_id = buf_get_id(sink); | ||
|
|
||
| if (sink_buf_id == buf_id) { | ||
| struct comp_dev *sc = comp_buffer_get_sink_component(sink); | ||
| comp_err(dev, "kpb_bind: buf_id=%d sink_comp=0x%x -> %s", | ||
| buf_id, sc ? dev_comp_id(sc) : 0, sink_buf_id == 0 ? "sel_sink" : "host_sink"); | ||
| if (sink_buf_id == 0) | ||
| kpb->sel_sink = sink; | ||
| else | ||
|
|
@@ -887,6 +894,38 @@ static int kpb_prepare(struct comp_dev *dev) | |
| return -ENOMEM; | ||
| } | ||
|
|
||
| struct comp_buffer *sink; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lets comment why this is needed, and what we are doing in these 2 new blocks. This does look like it would benefit a utility API. |
||
| comp_dev_for_each_consumer(dev, sink) { | ||
| struct comp_dev *sc = comp_buffer_get_sink_component(sink); | ||
| if (sc) { | ||
| comp_err(dev, "kpb consumer in bsink_list: comp_id=0x%x type=%d sink_buf=%p", | ||
| dev_comp_id(sc), sc->drv ? sc->drv->type : -1, sink); | ||
| if (dev_comp_id(sc) != 0x10) | ||
| kpb->sel_sink = sink; | ||
| else | ||
| kpb->host_sink = sink; | ||
| } | ||
| } | ||
| comp_err(dev, "kpb_params result: sel_sink=%p host_sink=%p", | ||
| kpb->sel_sink, kpb->host_sink); | ||
|
|
||
| if (kpb->sel_sink) { | ||
| struct comp_dev *sink_comp = comp_buffer_get_sink_component(kpb->sel_sink); | ||
| if (sink_comp && sink_comp->state == COMP_STATE_INIT) { | ||
| struct sof_ipc_stream_params sink_params; | ||
| memset_s(&sink_params, sizeof(sink_params), 0, sizeof(sink_params)); | ||
| sink_params.channels = kpb->config.channels ? kpb->config.channels : 2; | ||
| sink_params.rate = kpb->config.sampling_freq ? kpb->config.sampling_freq : 16000; | ||
| sink_params.sample_container_bytes = 4; | ||
| sink_params.sample_valid_bytes = 4; | ||
| sink_params.frame_fmt = SOF_IPC_FRAME_S32_LE; | ||
| comp_params(sink_comp, &sink_params); | ||
| comp_prepare(sink_comp); | ||
| } | ||
| } | ||
|
|
||
| kpb_change_state(kpb, KPB_STATE_RUN); | ||
|
|
||
| #ifndef CONFIG_IPC_MAJOR_4 | ||
| /* Search for KPB related sinks. | ||
| * NOTE! We assume here that channel selector component device | ||
|
|
@@ -936,10 +975,36 @@ static int kpb_prepare(struct comp_dev *dev) | |
| } | ||
| #endif /* CONFIG_IPC_MAJOR_4 */ | ||
|
|
||
| if (!kpb->sel_sink || !kpb->host_sink) { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lets comment what this block is doing and why. |
||
| struct comp_buffer *sink; | ||
|
|
||
| comp_dev_for_each_consumer(dev, sink) { | ||
| if (!kpb->sel_sink) | ||
| kpb->sel_sink = sink; | ||
| else if (!kpb->host_sink) | ||
| kpb->host_sink = sink; | ||
| } | ||
| } | ||
|
|
||
| if (!kpb->sel_sink) { | ||
| comp_err(dev, "could not find sink: sel_sink %p", | ||
| kpb->sel_sink); | ||
| ret = -EIO; | ||
| } else { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto re comments. |
||
| struct comp_dev *sink_comp = comp_buffer_get_sink_component(kpb->sel_sink); | ||
| if (sink_comp && sink_comp->state == COMP_STATE_INIT) { | ||
| struct sof_ipc_stream_params sink_params; | ||
| memset_s(&sink_params, sizeof(sink_params), 0, sizeof(sink_params)); | ||
| sink_params.channels = kpb->config.channels ? kpb->config.channels : 2; | ||
| sink_params.rate = kpb->config.sampling_freq ? kpb->config.sampling_freq : 16000; | ||
| sink_params.sample_container_bytes = 4; | ||
| sink_params.sample_valid_bytes = 4; | ||
| sink_params.frame_fmt = SOF_IPC_FRAME_S32_LE; | ||
| comp_params(sink_comp, &sink_params); | ||
| comp_prepare(sink_comp); | ||
| comp_info(dev, "kpb_prepare: prepared downstream sink_comp %d in state %d", | ||
| dev_comp_id(sink_comp), sink_comp->state); | ||
| } | ||
| } | ||
|
|
||
| kpb->sync_draining_mode = true; | ||
|
|
@@ -1234,19 +1299,16 @@ static int kpb_copy(struct comp_dev *dev) | |
| sink = kpb->sel_sink; | ||
| ret = PPL_STATUS_PATH_STOP; | ||
|
|
||
| comp_err(dev, "kpb_copy: source_buf=%p sel_sink=%p avail=%u", | ||
| source, sink, audio_stream_get_avail_bytes(&source->stream)); | ||
|
|
||
| if (!sink) { | ||
| comp_err(dev, "no sink."); | ||
| ret = -EINVAL; | ||
| break; | ||
| } | ||
|
|
||
| /* Discard data if sink is not active */ | ||
| if (comp_buffer_get_sink_component(sink)->state != COMP_STATE_ACTIVE) { | ||
| copy_bytes = audio_stream_get_avail_bytes(&source->stream); | ||
| comp_update_buffer_consume(source, copy_bytes); | ||
| comp_dbg(dev, "KD not active, dropping %zu bytes...", copy_bytes); | ||
| break; | ||
| } | ||
| /* Allow downstream WOV detector copy regardless of state */ | ||
|
|
||
| /* Validate sink */ | ||
| if (!audio_stream_get_wptr(&sink->stream)) { | ||
|
|
@@ -1313,6 +1375,15 @@ static int kpb_copy(struct comp_dev *dev) | |
| else | ||
| comp_update_buffer_produce(sink, produced_bytes); | ||
|
|
||
| struct comp_dev *wov_comp = sink ? comp_buffer_get_sink_component(sink) : NULL; | ||
| if (wov_comp) { | ||
| comp_err(dev, "kpb_copy: produced=%u bytes, triggering wov=0x%x", | ||
| copy_bytes, dev_comp_id(wov_comp)); | ||
| comp_copy(wov_comp); | ||
| } else { | ||
| comp_err(dev, "kpb_copy: downstream sink_comp returned NULL!"); | ||
| } | ||
|
|
||
| comp_update_buffer_consume(source, copy_bytes); | ||
|
|
||
| break; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
|
|
||
| #include <sof/audio/buffer.h> | ||
| #include <sof/audio/component.h> | ||
| #include <sof/audio/component_ext.h> | ||
| #include <sof/audio/format.h> | ||
| #include <sof/audio/module_adapter/module/generic.h> | ||
| #include <sof/audio/pipeline.h> | ||
|
|
@@ -309,7 +310,9 @@ static int mixin_process(struct processing_module *mod, | |
| int i, ret; | ||
| struct cir_buf_ptr source_ptr; | ||
|
|
||
| comp_dbg(dev, "entry"); | ||
| source_avail_frames = source_get_data_frames_available(sources[0]); | ||
| comp_err(dev, "mixin_process entry: num_sinks=%d sources=%d avail=%u", | ||
| num_of_sinks, num_of_sources, source_avail_frames); | ||
|
|
||
| source_avail_frames = source_get_data_frames_available(sources[0]); | ||
| sinks_free_frames = INT32_MAX; | ||
|
|
@@ -342,14 +345,8 @@ static int mixin_process(struct processing_module *mod, | |
| unused_in_between_buf = comp_buffer_get_from_sink(sinks[i]); | ||
| mixout = comp_buffer_get_sink_component(unused_in_between_buf); | ||
|
|
||
| /* Skip non-active mixout like it is not connected so it does not | ||
| * block other possibly connected mixouts. In addition, non-active | ||
| * mixouts might have their sink buffer/interface not yet configured. | ||
| */ | ||
| if (mixout->state != COMP_STATE_ACTIVE) { | ||
| active_mixouts[i] = NULL; | ||
| continue; | ||
| } | ||
| if (mixout->state != COMP_STATE_ACTIVE) | ||
| mixout->state = COMP_STATE_ACTIVE; | ||
|
|
||
| mixout_mod = comp_mod(mixout); | ||
| active_mixouts[i] = mixout_mod; | ||
|
|
@@ -394,8 +391,10 @@ static int mixin_process(struct processing_module *mod, | |
| sinks_free_frames = MIN(sinks_free_frames, free_frames - pending_frames->frames); | ||
| } | ||
|
|
||
| if (sinks_free_frames == 0 || sinks_free_frames == INT32_MAX) | ||
| if (sinks_free_frames == 0 || sinks_free_frames == INT32_MAX) { | ||
| comp_err(dev, "mixin_process early return 0: sinks_free=%u", sinks_free_frames); | ||
| return 0; | ||
| } | ||
|
|
||
| #if CONFIG_XRUN_NOTIFICATIONS_ENABLE | ||
| frame_bytes = source_get_frame_bytes(sources[0]); | ||
|
|
@@ -502,6 +501,9 @@ static int mixin_process(struct processing_module *mod, | |
|
|
||
| if (frames_to_copy + start_frame > mixout_data->mixed_frames) | ||
| mixout_data->mixed_frames = frames_to_copy + start_frame; | ||
|
|
||
| if (mixout_mod && mixout_mod->dev) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need comment for what we are checking and why. |
||
| comp_copy(mixout_mod->dev); | ||
| } | ||
|
|
||
| if (bytes_to_consume) | ||
|
|
@@ -596,6 +598,18 @@ static int mixout_process(struct processing_module *mod, | |
| sink_commit_buffer(sinks[0], bytes_to_produce); | ||
| md->acquired_buf.ptr = NULL; | ||
|
|
||
| if (bytes_to_produce > 0) { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditt re comments for this block |
||
| struct comp_buffer *sink_buf = comp_buffer_get_from_sink(sinks[0]); | ||
| if (sink_buf && comp_buffer_get_sink_component(sink_buf)) { | ||
| struct comp_dev *sink_comp = comp_buffer_get_sink_component(sink_buf); | ||
| comp_err(dev, "mixout_process: sink_buf=0x%x produced=%u bytes, triggering kpb=0x%x", | ||
| sink_buf, bytes_to_produce, dev_comp_id(sink_comp)); | ||
| comp_copy(sink_comp); | ||
| } else { | ||
| comp_err(dev, "mixout_process: produced=%u bytes, BUT sink_buf/comp NULL", bytes_to_produce); | ||
| } | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # SPDX-License-Identifier: BSD-3-Clause | ||
| add_local_sources(sof vad_gate.c) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # SPDX-License-Identifier: BSD-3-Clause | ||
|
|
||
| config COMP_VAD_GATE | ||
| bool "VAD gate component" | ||
| depends on IPC_MAJOR_4 | ||
| help | ||
| Select to build the VAD (Voice Activity Detection) gate component. | ||
| The gate sits between the DMIC copier and the downstream Mixin in | ||
| a WOV capture pipeline. During silence it drains the DMIC input | ||
| and returns PPL_STATUS_PATH_STOP so KPB and WOV detectors idle. | ||
| When voice onset is detected audio flows through and the downstream | ||
| chain wakes and begins buffering. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be =m