feat(dock): the GAME bay — dB fader, measured ladder, mute, real duck badge

Unit 6. Mirrors the mic bay for the desktop/game bed, plus the badge that matters to a creator who
cannot hear the duck: it shows while the ducker is actually attenuating, and it prints the gain the
mixer applied (−12.0 DUCK by design).

- `AudioMixer.DuckGain` exposes `AutoDucker.CurrentGain` instead of leaving it internal.
- VM: `GameVolumeDb` / `GameVolumeDbLabel` (fader face), `GameMeterFraction` (measured level),
  `IsGameDucking` + `GameDuckLabel` refreshed on the level tick — the same moment the ducker runs,
  so the badge cannot lag behind the mix.
- The bay: header chip + source, ladder, mute dot (uses the meter band, so mute reads at a glance),
  dB readout, fader.

Guard: GameBayTests — the dock binds all four, `AutoDucker.DuckGain` is −12.04 dB and the label is
produced through the same dB scale as the faders, and the mixer property exists so the badge cannot
become a hardcoded number.
This commit is contained in:
2026-10-30 13:12:10 -07:00
parent 3524ede480
commit a1d8e761ea
4 changed files with 122 additions and 4 deletions
+4
View File
@@ -44,6 +44,10 @@ public sealed class AudioMixer : IDisposable
private readonly AudioRingBuffer _alertBuffer;
private readonly VoiceFilterChain _voiceChain;
private readonly AutoDucker _ducker;
/// <summary>The ducker's CURRENT gain (1 = not ducking, 0.25 = the −12 dB duck). Read by the
/// dock's badge: a duck indicator that is not the real value is decoration.</summary>
public float DuckGain => _ducker.CurrentGain;
private readonly MasterLimiter _masterLimiter = new();
private TinyResampler? _micResampler;
private TinyResampler? _loopbackResampler;