feat(audio): multitrack stem recording — Stage 1 (pure core + plan)

Scopes the differentiating "record every peer to their own synced track"
feature and lands its pure, isolated core (no live-audio wiring yet).

- docs/multitrack-recording-plan.md: scope contract + locked decisions
  (raw stems pre-volume/mute, stems + a mixed track, silence-pad late joiners).
- src/audio/multitrack.rs: MultitrackRecorder over the existing WavWriter.
  One master clock = the mixer cycle; every end_cycle() appends exactly
  FRAME_SAMPLES to every track (silence where idle) so all stems stay
  sample-aligned. add_peer back-pads a late joiner to cycle 0; track_filename
  gives fs-safe `<slug>-<shortid>.wav` (reuses sanitize_name). Optional mix
  track for "Both" mode.
- +5 unit tests: equal length across tracks, late-joiner leading silence,
  stems-only omits mix, fit() pad/truncate, filename slugging/disambiguation.

Stage 2 (wire into the mixer) is next, behind a checkpoint. 168 lib tests,
clippy --all-targets clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 23:48:07 -04:00
co-authored by Claude Opus 4.8
parent 3edac3f8d1
commit fde6f8a680
3 changed files with 358 additions and 0 deletions
+1
View File
@@ -54,6 +54,7 @@ pub trait AudioBackend: Send + Sync {
pub mod echo_cancel;
pub mod gate;
pub mod limiter;
pub mod multitrack;
pub mod pipewire_impl;
pub mod pw_cli;
pub mod recorder;