Skip to content

refactor(audio): sample rate handling and dynamic format detection - #39

Merged
Horuse merged 9 commits into
mainfrom
feat/configurable-sample-rate
Sep 8, 2026
Merged

refactor(audio): sample rate handling and dynamic format detection#39
Horuse merged 9 commits into
mainfrom
feat/configurable-sample-rate

Conversation

@Horuse

@Horuse Horuse commented Sep 6, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

  1. Configurable pipeline and virtual device sample rates:

    • Adds pipeline sample rate selection in Settings (44.1k, 48k default, 88.2k, 96k, 176.4k, 192k + 1 Hz custom stepper).
    • Adds per-virtual-device sample rate configuration in Virtual Devices UI and macOS HAL driver (SplitAudioDriver.cpp, bumped driver version to 5).
    • Eliminates startup sample rate mismatch panics/crashes (Issue [crash] audio stream error: #32) via input normalizer and output rate adaptation.
    • Bit-transparent audio path: dynamically bypasses rubato resampling when source and pipeline sample rates match.
  2. Flow UI sample rate badge and minimal resample indicator:

    • Header displays current pipeline sample rate badge.
    • Node header shows minimalist ArrowSwap icon with tooltip (Resampling: 48 kHz → 96 kHz) only when a node undergoes resampling.
    • Technical audio specs row (48 kHz · 2 ch · f32) added across input/output nodes (microphone, speaker, app_audio, system_audio, file_recording, net_receiver, net_sender)
  3. Net Sender sample rate selection & Net Receiver dynamic format detection:

    • Net Sender gains sample rate selector (Auto, 44.1, 48, 88.2, 96 kHz + Custom stepper) for PCM mode.
    • Stateless UDP wire protocol update:
      • 100% backwards-compatible with legacy 4-byte headers (b0 < 0x80).
    • Net Receiver automatically detects incoming format (PCM f32 / Opus), sample rate, channels, and codec profile without connection negotiation.
    • Dynamic on-the-fly sample rate adaptation in receiver stream via MultiResamplerOut.

Why is this the right approach?

  • Eliminates mismatch crashes: Hardware and pro-audio devices frequently operate outside 48 kHz (e.g. 44.1 kHz music mastering, 96 kHz monitoring). Hardcoding 48 kHz caused panics on non-standard device rates.
  • Zero-cost bit transparency: Resamplers are only allocated and executed when rates actually differ; identical rates pass audio untouched.
  • Correct lifecycle scope: Pipeline audio I/O tasks must remain alive as long as the pipeline is running, regardless of whether the user is on the Flow canvas or navigating elsewhere in the UI.

Checklist

  • Diff is limited to the change — no unrelated edits
  • bun run check passes
  • cargo check --manifest-path src-tauri/Cargo.toml passes
  • bun run format leaves the tree clean
  • Generated TS types are committed with the Rust change (if any)
  • No new dependency without a reason in the PR description
  • I read the RT audio path section of docs/CONCEPT.md and confirmed this
    change adds no allocations, locks, or syscalls to cpal / SCK callbacks
    or DspWorker::run

Platform coverage

  • Developed on: macOS 14.7.8 (aarch64)
  • Tested on: macOS 14.7.8, Fedora 44, Windows 11
  • What I did to test:
    • Pipeline sample rate switching across 44.1, 48, 88.2, 96, 176.4, 192 kHz with active mic and speaker streams.
    • Virtual device rate reconfiguration and HAL driver audio pass-through.
    • CoreAudio process tap capture on app and system audio at non-48 kHz pipeline rates.
    • Local UDP loopback streaming between Net Sender and Net Receiver across rates and Opus bitrates/modes.

Related

- Add pipeline sample rate setting in Settings (presets: 44.1k, 48k default, 88.2k, 96k, 176.4k, 192k + 1 Hz custom stepper).
- Add sample rate configuration per virtual device in Virtual Devices UI and HAL driver.
- Ensure bit-transparent signal path without resampling when device and pipeline rates match.
- Add input normalizer and output rate adaptation to eliminate Issue #32 capture startup mismatch crashes.
- Bump virtual driver version to 5.
@Horuse
Horuse merged commit f596951 into main Sep 8, 2026
9 checks passed
@Horuse
Horuse deleted the feat/configurable-sample-rate branch September 8, 2026 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[crash] audio stream error:

1 participant