feat(audio): input/output volume sliders in Settings

Adds Discord-style app-internal gain controls under each device picker:
input volume scales the captured mic (applied before the meter/gate/encode,
so it also moves the mic meter), output volume scales the mixed playback
(on top of per-peer volumes). PeerSpeak-only — no system/other-app effect.

Both persist in config (input_volume/output_volume, serde default 1.0 for
backward compat) and read live by the audio loops via f32-bit atomics, so
they take effect mid-call. Sliders apply live on drag and save on release.
The standalone mic-test monitor applies the same input gain so the test
meter reflects it. Reuses the existing apply_volume helper (unity fast-path
+ i16 saturation).

Tests: config backward-compat + round-trip for the new fields (gain math
itself is covered by the existing apply_volume tests). 65 lib tests, clippy
clean. Field-verified: input slider moves the mic-test meter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 16:21:39 -04:00
co-authored by Claude Opus 4.8
parent cb2776cc1d
commit 5af25bff5e
4 changed files with 104 additions and 5 deletions
+4
View File
@@ -12,6 +12,10 @@ pub enum CoreCommand {
SetPttActive(bool),
SetPeerVolume(EndpointId, f32),
SetNoiseGateThreshold(f32),
/// App-internal capture gain (mic), applied before the gate/encode. 1.0 = unity.
SetInputVolume(f32),
/// App-internal playback gain on the mixed output. 1.0 = unity.
SetOutputVolume(f32),
/// Start/stop a standalone capture-only stream that reports the raw mic
/// level via [`UiEvent::MicLevel`], for gate calibration outside a call.
/// Ignored while a room session is active (the in-call meter covers that).