feat: protocol compliance, sync improvements, and FLAC fixes#15
Merged
feat: protocol compliance, sync improvements, and FLAC fixes#15
Conversation
…s post-reconnect) After a WebSocket reconnect, the Kalman clock synchronizer is reset and needs ~2 seconds to re-converge. During this window, sync error measurements are unreliable. Without suppression, the correction system reacts to garbage measurements causing audible artifacts. Adds NotifyReconnect() through the pipeline chain (AudioPipeline → TimedAudioBuffer + IAudioPlayer → SyncCorrectionCalculator) to suppress corrections during the stabilization period. Covers both Read() (deprecated) and ReadRaw() (current) correction paths. Matches Android client's RECONNECT_STABILIZATION_US = 2,000,000. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…oid/Python CLI) Without a cooldown, persistent clock sync error can trigger re-anchors every ~750ms (500ms grace + 250ms rebuffer), causing audio stuttering. The cooldown timer persists across Clear() calls since reanchor itself calls Clear(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…/start) The server's stream/start reports bit_depth=32 (PyAV's s32 container format) but the actual FLAC STREAMINFO declares 24-bit precision. Using the wrong bit depth for the scale factor (dividing by 2^31 instead of 2^23) produced near-zero sample values = silence. Changes: - Use server codec_header (real STREAMINFO) instead of synthetic header - Calibrate scale factor from SimpleFlac's actual BitsPerSample - Fix integer overflow in scale factor calc (1<<31 -> 1L<<31) - Add logging to FlacDecoder via ILoggerFactory - Catch NotSupportedException in addition to InvalidDataException Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rack start The server paces data by compressed byte capacity (32MB), which for FLAC with ~4:1 compression decodes to 30+ seconds of audio. The previous 8s internal buffer overflowed on every track start, causing 230+ frame drops and a fast-forward sound artifact. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stats for Nerds and main UI were showing 32-bit (from stream/start's PyAV container format) instead of the actual 24-bit FLAC precision. Now the FlacDecoder updates Format.BitDepth on calibration so all downstream displays reflect reality. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When connecting to a server mid-track, the server sends an artwork-only stream/start (no "player" key) before the real audio stream/start. Previously this created a phantom Opus pipeline and forced "Playing" state, causing the UI to show playback with no audio until the user skipped tracks. Now StreamStartPayload.Format is nullable — artwork-only messages are detected and skipped, so the pipeline only starts when actual audio format info arrives. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4 tasks
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
Test plan
🤖 Generated with Claude Code