echo-cancel: reset buffers when deactivating

Reset buffers when deactivating to avoid having old data in the
ringbuffers, which also adds latency when activated again.

Clear sink_ready and capture_ready when resetting buffers to avoid
calling process() before there is new data to process.
This commit is contained in:
Jonas Holmberg 2025-07-09 10:17:23 +02:00
parent 0efd0258a7
commit 85ff73d690

View file

@ -458,6 +458,31 @@ done:
impl->capture_ready = false;
}
static void reset_buffers(struct impl *impl)
{
uint32_t index, i;
spa_ringbuffer_init(&impl->rec_ring);
spa_ringbuffer_init(&impl->play_ring);
spa_ringbuffer_init(&impl->play_delayed_ring);
spa_ringbuffer_init(&impl->out_ring);
for (i = 0; i < impl->rec_info.channels; i++)
memset(impl->rec_buffer[i], 0, impl->rec_ringsize);
for (i = 0; i < impl->play_info.channels; i++)
memset(impl->play_buffer[i], 0, impl->play_ringsize);
for (i = 0; i < impl->out_info.channels; i++)
memset(impl->out_buffer[i], 0, impl->out_ringsize);
spa_ringbuffer_get_write_index(&impl->play_ring, &index);
spa_ringbuffer_write_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay)));
spa_ringbuffer_get_read_index(&impl->play_ring, &index);
spa_ringbuffer_read_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay)));
impl->sink_ready = false;
impl->capture_ready = false;
}
static void capture_destroy(void *d)
{
struct impl *impl = d;
@ -542,6 +567,8 @@ static void capture_state_changed(void *data, enum pw_stream_state old,
if (old == PW_STREAM_STATE_STREAMING) {
if (pw_stream_get_state(impl->sink, NULL) != PW_STREAM_STATE_STREAMING) {
reset_buffers(impl);
pw_log_debug("%p: deactivate %s", impl, impl->aec->name);
res = spa_audio_aec_deactivate(impl->aec);
if (res < 0 && res != -EOPNOTSUPP) {
@ -593,28 +620,6 @@ static void source_state_changed(void *data, enum pw_stream_state old,
}
}
static void reset_buffers(struct impl *impl)
{
uint32_t index, i;
spa_ringbuffer_init(&impl->rec_ring);
spa_ringbuffer_init(&impl->play_ring);
spa_ringbuffer_init(&impl->play_delayed_ring);
spa_ringbuffer_init(&impl->out_ring);
for (i = 0; i < impl->rec_info.channels; i++)
memset(impl->rec_buffer[i], 0, impl->rec_ringsize);
for (i = 0; i < impl->play_info.channels; i++)
memset(impl->play_buffer[i], 0, impl->play_ringsize);
for (i = 0; i < impl->out_info.channels; i++)
memset(impl->out_buffer[i], 0, impl->out_ringsize);
spa_ringbuffer_get_write_index(&impl->play_ring, &index);
spa_ringbuffer_write_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay)));
spa_ringbuffer_get_read_index(&impl->play_ring, &index);
spa_ringbuffer_read_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay)));
}
static void input_param_latency_changed(struct impl *impl, const struct spa_pod *param)
{
struct spa_latency_info latency;
@ -797,6 +802,8 @@ static void sink_state_changed(void *data, enum pw_stream_state old,
impl->current_delay = 0;
if (pw_stream_get_state(impl->capture, NULL) != PW_STREAM_STATE_STREAMING) {
reset_buffers(impl);
pw_log_debug("%p: deactivate %s", impl, impl->aec->name);
res = spa_audio_aec_deactivate(impl->aec);
if (res < 0 && res != -EOPNOTSUPP) {