audio: mixer: Improve handling of inactive input streams

The old code does not deal correctly with input streams going away
without everything stopping. This commit ensures only active streams are
considered as mixer input, and the other streams are ignored (considered
zeroed out).

Signed-off-by: Paul Olaru <paul.olaru@nxp.com>
This commit is contained in:
Paul Olaru 2023-03-31 13:16:10 +03:00 committed by Daniel Baluta
parent 362a0781f2
commit 908876cc5f
2 changed files with 19 additions and 15 deletions

View File

@ -82,11 +82,12 @@ static int mixer_process(struct processing_module *mod,
struct mixer_data *md = module_get_private_data(mod);
struct comp_dev *dev = mod->dev;
const struct audio_stream __sparse_cache *sources_stream[PLATFORM_MAX_STREAMS];
int32_t i = 0;
int32_t i = 0, j = 0;
uint32_t frames = INT32_MAX;
/* Redundant, but helps the compiler */
uint32_t source_bytes = 0;
uint32_t sink_bytes;
int active_input_buffers = 0;
comp_dbg(dev, "mixer_process() %d", num_input_buffers);
@ -105,10 +106,11 @@ static int mixer_process(struct processing_module *mod,
if (avail_frames == 0)
continue;
active_input_buffers++;
frames = MIN(frames, avail_frames);
}
if (!num_input_buffers || (frames == 0 && md->sources_inactive)) {
if (!active_input_buffers) {
/*
* Generate silence when sources are inactive. When
* sources change to active, additionally keep
@ -119,33 +121,37 @@ static int mixer_process(struct processing_module *mod,
if (!audio_stream_set_zero(mod->output_buffers[0].data, sink_bytes))
mod->output_buffers[0].size = sink_bytes;
md->sources_inactive = true;
return 0;
}
/* Every source has the same format, so calculate bytes based on the first one */
source_bytes = frames * audio_stream_frame_bytes(mod->input_buffers[0].data);
if (md->sources_inactive) {
md->sources_inactive = false;
comp_dbg(dev, "mixer_copy exit sources_inactive state");
}
sink_bytes = frames * audio_stream_frame_bytes(mod->output_buffers[0].data);
comp_dbg(dev, "mixer_process(), source_bytes = 0x%x, sink_bytes = 0x%x",
source_bytes, sink_bytes);
/* mix streams */
for (i = 0; i < num_input_buffers; i++)
sources_stream[i] = mod->input_buffers[i].data;
for (i = 0; i < num_input_buffers; i++) {
uint32_t avail_frames;
md->mix_func(dev, mod->output_buffers[0].data, sources_stream, num_input_buffers, frames);
avail_frames = audio_stream_avail_frames_aligned(mod->input_buffers[i].data,
mod->output_buffers[0].data);
/* if one source is inactive, skip it */
if (avail_frames == 0)
continue;
sources_stream[j++] = mod->input_buffers[i].data;
}
if (j)
md->mix_func(dev, mod->output_buffers[0].data, sources_stream, j, frames);
mod->output_buffers[0].size = sink_bytes;
/* update source buffer consumed bytes */
for (i = 0; i < num_input_buffers; i++)
for (i = 0; i < j; i++)
mod->input_buffers[i].consumed = source_bytes;
return 0;

View File

@ -32,8 +32,6 @@ void sys_comp_module_mixer_interface_init(void);
/* mixer component private data */
struct mixer_data {
bool sources_inactive;
void (*mix_func)(struct comp_dev *dev, struct audio_stream __sparse_cache *sink,
const struct audio_stream __sparse_cache **sources, uint32_t count,
uint32_t frames);