https://gitlab.synchro.net/main/sbbs/-/commit/0f56014594e1d842c3a3fed0
Modified Files:
src/xpdev/xpbeep.c
Log Message:
xpbeep: gaplessly hand off when a mixer buffer ends mid-pull
xp_mixer_pull() mixed only the head buffer per pull (plus a crossfade
partner). When a queued buffer was exhausted partway through a pull, the
rest of that pull was left silent and the next buffer did not start until
the following pull.
For one-shot sounds that is inaudible, but a channel fed a continuous
stream cut into back-to-back chunks -- a game door streaming Opus/PCM
through SyncTERM's A;Queue FIFO -- crosses a buffer boundary mid-pull
about four times a second at 250 ms chunks over a ~23 ms (1024-frame)
device callback. Each boundary dropped up to a full callback of silence,
heard as constant clicking/popping over the whole stream. It was masked
on backends with a very small callback (Win32 WASAPI) and obvious on the 1024-frame Linux backends (PulseAudio, PortAudio, SDL).
Fix: drain successive FIFO buffers into the same pull until it is filled
or the queue empties, so a buffer that ends mid-pull hands off to its
successor with no gap. The crossfade-overlay path (head and next mixed concurrently, one pair per pull) is preserved unchanged; a plain buffer
that drains into a crossfade pair now fills what it used to leave silent.
Verified with a hardware-free mixer harness: gapless draining across two/three/N buffers, drain-to-empty, exact buffer/pull alignment, and
consumed state carried across pulls, plus the crossfade behavior, all
clean under AddressSanitizer/UBSan/LSan.
Co-Authored-By: Claude Opus 4.8 (1M context) <
noreply@anthropic.com>
---
þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net