Reduce audible startup sync correction#255
Open
trisweb wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This reduces audible pitch shift / warble during Sendspin client playback startup and other stream transitions.
The main issue appears to be that the client can start playback with a consistent initial sync offset, then correct that offset quite aggressively using sample insert/drop correction. On my Linux endpoint this was especially noticeable at the beginning of tracks. Some discussion of this occurred at #107, however it was indeterminate and difficult to pin down the cause.
With analysis and help from GPT5.5, with my full understanding and detailed review, this PR makes three related changes:
Analysis
I was hearing pitch shift and warble on a fully up-to-date sendspin endpoint, most noticeably at playback start and during track changes.
Looking through
sendspin/audio.py, the most suspicious path was the sync correction logic. The previous drop correction branch did this:That effectively produced a duplicate-then-skip pattern, which is more audible than a simple one-frame drop.
Separately, the correction loop allowed up to +/-4% playback speed correction over a 2 second target window. On real playback that is enough to sound like pitch movement, especially right after startup when the first sync estimate is still settling.
This was changed to a maximum +/-0.2% correction over an 8 second window, which is more conservative, but still within reasonable sync delay expectations (counting to 8 will help provide confidence; if we believe users would reasonably be OK with out-of-sync clients converging within 8 seconds, then this is a reasonable default). Importantly, this is well below the threshold of audible pitch shift or warble while still providing a means to converge.
In any case, if the sync is too far out, a reanchor will be triggered.
Additionally, a 750ms sync correction delay was added; this does not delay audible playback, it only suppresses sample insert/drop correction briefly after playback enters the PLAYING state. That gives the DAC timing and clock-sync estimates a short window to settle before the client starts making speed adjustments based on them. In practice this avoids reacting to the first unstable startup measurements while still allowing scheduled playback to begin on time.
Real Endpoint Comparison
I tested this on my actual Sendspin Linux endpoint using the same daemon config, audio device, and negotiated format:
flac:48000:24:2The original version repeatedly started streams around
-42 mssync error, then corrected aggressively.Original observed debug stats:
00098.29%to100.11%82155Patched observed debug stats:
00099.78%to100.04%10621The startup offset is still visible, but correction is much less aggressive and avoids the previous drop-frame artifact.
Tests
Added focused regression tests for:
Local verification:
Results:
Testing for a day in real world scenarios has also been very successful.