From d50c05744fee59955bae5276a11dd9338383007b Mon Sep 17 00:00:00 2001 From: Mollusk Date: Mon, 15 Jun 2026 05:53:16 -0400 Subject: [PATCH] docs(architecture): correct stale playback buffer-quantum description Section 3 claimed playout is pinned to exactly 1024 frames; the code now follows the graph's Buffer::requested() quantum (pipewire_impl.rs:229-237), with 1024 only as a fallback -- the doc described the pre-fix behavior that caused crackle. Flagged by the 2026-06-15 Codex/GPT-5.5 review (backlog A20). The broader ARCHITECTURE refresh (missing modules, persistent identity, signed gossip, friends/W7, recording modes) remains under A20. Co-Authored-By: Claude Opus 4.8 --- docs/ARCHITECTURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index a31fcab..4da13b5 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -105,7 +105,7 @@ Audio processing runs on a 20ms clock (960 samples at 48kHz mono S16LE): ``` * **RT Playout Safety**: The playout process callback inside [src/audio/pipewire_impl.rs](file:///home/mollusk/git/butter/peerspeak/src/audio/pipewire_impl.rs#L64) pops mixed PCM samples directly from the SPSC ring buffer. No allocations or mutex locks are used. -* **Buffer Quantum Pinning**: Playout streams enforce an explicit `SPA_TYPE_OBJECT_ParamBuffers` configuration during stream setup, pinning the hardware buffer size to exactly 1024 frames (2048 bytes mono S16LE). This limits the driver from over-pulling beyond the SPSC ring buffer's capacity and eliminates playback crackle. +* **Buffer Quantum Handling**: The playout callback honors the graph's per-cycle quantum from `Buffer::requested()` (`src/audio/pipewire_impl.rs:229-237`), serving exactly that many frames each cycle and falling back to a safe cap (`FALLBACK_FRAMES = 1024`) only when the graph reports no quantum. This replaced an earlier hard pin to 1024 frames, which crackled on machines whose `clock.quantum` wasn't 1024; following the requested quantum makes playback correct on any graph quantum. * **Jitter Buffers & Mix Loop**: Incoming UDP datagrams are parsed in the Core `datagram_task` and routed to the peer's `JitterBuffer` (`src/core/jitter.rs`). Every 20ms, the Core `mixer_task` runs a tick: 1. It pulls from each active peer's jitter buffer. 2. If a sequence gap exists, it asks the Opus decoder to perform Packet Loss Concealment (PLC).