Skip to content

fix(audio): bound playback backlog and clear acknowledgement - #29

Merged
malhashemi merged 4 commits into
malhashemi:mainfrom
francocarballar:fix/playback-buffer-safety
Oct 7, 2026
Merged

malhashemi merged 4 commits into
malhashemi:mainfrom
francocarballar:fix/playback-buffer-safety

Conversation

@francocarballar

@francocarballar francocarballar commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

The native audio engine moves decoded voice output to the local speaker.
The resampler converts samples to the output device’s rate.
The renderer drains samples from a ring buffer, a short queue between conversion and playback.
A growing queue can make older speech play late.

Playback flow

The resampler now keeps at most one second of pending output.
On overflow, the resampler drops the oldest samples and keeps the newest audio.
That cap bounds this queue, but it cannot guarantee end-to-end audio latency.
Before refilling, the engine clears its pending samples and signals a ring-buffer reset.
The renderer clears that ring buffer and acknowledges the reset.
If no acknowledgement arrives within one second, the engine exits with an error instead of waiting indefinitely.
The error uses the existing call shutdown path; it does not repair a failed audio device.

Related issue

Issue #28 describes speech remaining in local audio buffers after interruption.
This PR bounds the playback queue and times out if the renderer does not acknowledge a clear.
It does not connect interruption events to the helper’s clear command, so it does not close #28.

Limits and verification

Linux native tests passed with 11 tests.
One manual DSP timing diagnostic was ignored.
Clippy, formatting, and whitespace checks passed.
Real-call testing on macOS has not been performed.
Please test a real call on macOS during review.

francocarballar and others added 3 commits October 6, 2026 12:50
Reset pending resampler audio and wait for the renderer to acknowledge clearing its ring. Cover overflow, repeated clears and real sample-rate conversion without devices.

Co-authored-by: OpenAI <noreply@openai.com>
Acota a un segundo el audio pendiente del resampler y descarta las muestras más antiguas. Si el renderer no confirma una limpieza en un segundo, el engine falla para cerrar la llamada en vez de quedar silenciado.

Co-Authored-By: OpenAI <noreply@openai.com>
…ropped early

The engine decoded up to 32 packets before moving any audio to the speaker
ring, so a batch over one second overflowed the pending cap and dropped its
oldest audio even when the ring had room. Flush after every packet instead.
@malhashemi

Copy link
Copy Markdown
Owner

Thank you @francocarballar, great work on this! Both the backlog cap and the clear-acknowledgement timeout look good. I pushed one small follow-up commit (41fba42): playback is now flushed into the speaker ring after each packet, so a big batch of packets can't overflow the one-second cap while the ring still has room, plus a test for it. Merging now, and thanks again for all the care you've put into these PRs. 🙏

@malhashemi
malhashemi merged commit 1a359f8 into malhashemi:main Oct 7, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Interruptions don't clear GPT-Live audio that is already buffered locally

2 participants