Conversation
The ALSA stream was started immediately when the first audio chunk arrived (queue.qsize() > 0), with only ~25ms of audio buffered. The PortAudio callback drains this single chunk before the next one arrives over the network, causing an immediate underflow and triggering the clear/re-anchor cycle. Wait until _MIN_BUFFER_DURATION_US (200ms) or _MIN_CHUNKS_TO_START (16) chunks are buffered before starting the stream, giving enough runway for the callback while the network delivers more chunks. Tested on Raspberry Pi 5 with Wondom GAB8 USB amplifiers (period_size=2048, output_latency=42ms at 48kHz).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0b5f9e2a7f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if not self._stream_started and self._stream is not None and ( | ||
| self._queued_duration_us >= self._MIN_BUFFER_DURATION_US | ||
| or self._queue.qsize() >= self._MIN_CHUNKS_TO_START | ||
| ): |
There was a problem hiding this comment.
Mark player non-drained while startup buffer is filling
Delaying stream start until the queue reaches this new threshold leaves _stream_started false while audio data is already buffered, but is_drained() treats any not _stream_started state as drained (sendspin/audio.py lines 318-320). In the format-switch workflow (sendspin/audio_connector.py lines 215-257), that causes the drain loop to be skipped and set_format() to run without clearing queued old-format PCM, so a format change that arrives before the 200ms/16-chunk threshold can play stale data with the new format (pitch/corruption).
Useful? React with 👍 / 👎.
|
Can you address CI and Codex. |
Includes #232 by @tobsch + addresses comments Closes #232 --------- Co-authored-by: Tobias Schlottke <[email protected]> Co-authored-by: Claude <[email protected]>
Problem
The ALSA stream starts immediately when the first audio chunk arrives (
queue.qsize() > 0), with only ~25ms of audio buffered. The PortAudio callback drains this single chunk before the next one arrives over the network, causing an immediate underflow.This triggers a clear/re-anchor cycle that can cascade into repeated underflows:
This is especially problematic with USB audio devices that have larger period sizes (2048 frames / ~42ms at 48kHz), where the output latency alone exceeds the buffered audio duration.
Fix
Wait until sufficient audio is buffered before starting the stream, using the existing
_MIN_BUFFER_DURATION_US(200ms) and_MIN_CHUNKS_TO_START(16) constants:This adds ~200ms of initial latency but eliminates the underflow/re-anchor cascade. After the fix:
Environment