The repo never enforced rustfmt, so formatting had drifted broadly. This is a
single mechanical `cargo fmt` pass over the whole crate (no behavioral change;
lib suite green, 493 passed). Going forward fmt should be enforced (planned CI
fmt --check step). Part of the 0.6.1 hygiene pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses Codex's xhigh RT-audio audit of the new Windows cpal path (review
2026-06-19; all Windows-only, no Linux-path change):
- W1 (P1): start_capture/start_playback reported Ok as soon as cpal's play()
returned, but cpal's WASAPI play() only QUEUES IAudioClient::Start(); a later
Start failure left the UI joined-but-silent. Readiness is now driven by the
stream actually proving itself: the first RT data callback sets a started
flag (or the error callback sets an error code), and the owner thread waits
(bounded by STREAM_START_TIMEOUT) before reporting Ok.
- W2: both RT error callbacks ran format!+log_msg on the time-critical stream
thread. They now store a category in an AtomicU8 only; the owner / health
logger translate + log off the RT path.
- W3: the playback ring was published one interleaved sample at a time, letting
the RT consumer read a half-written L/R pair and letting a raced fetch_sub
wrap ring_fill to usize::MAX (wedging mixer pacing). Now reserves occupancy
before publishing and writes the whole frame with a single push_slice.
- W6: finish_start did an unbounded recv() while holding the slot mutex, so a
wedged driver hung start_* and any concurrent stop. Now recv_timeout with a
FINISH_START_TIMEOUT backstop; on timeout it signals + detaches (never joins).
- W7: OS-reported device geometry is validated in resolve() (channels>0, rate in
8k-384k) so 0 channels can't panic chunks_exact(0) and a 0/absurd rate can't
make an infinite/huge resample ratio. resample.rs constructors also clamp
rates >=1 (release-safe; +2 tests) instead of a debug-only assert.
- W4 (diagnostic half): the playout-health logger compared raw device samples
against the internal-stereo prefill target. The callback now records demand in
internal 48 kHz-stereo units (internal_demand) so the comparison is correct
for remapped/non-48k devices. The dynamic-target restructure stays deferred.
Deferred (logged in review-2026-06-19-cpal-rt-audit.md): W5 (bounded mixer->
worker channel) touches the shared Linux audio path and wants its own design +
regression pass; the W2 dynamic-target sizing needs a real WASAPI callback.
Verified: Linux cargo test --lib 326/0, clippy --all-targets clean; windows-gnu
cargo check --lib --tests --bins clean; windows-gnu release peerspeak.exe builds.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- src/audio/resample.rs: pure linear PushResampler (capture) +
StereoPullResampler (playback pull), 6 unit tests green on Linux.
- choose_config: prefer native 48kHz, else fall back to device default
config and convert at the boundary instead of hard-erroring.
- run_capture: resample device-rate mono -> 48kHz on the drain thread.
- i16<->f32 helpers. Playback build_output remap still TODO (Codex).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>