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).