feat(dock): master strip + MONO output (the accessibility switch)
Unit 9, the one that matters most for this creator. MASTER STRIP (top, nearest the preview): - one ladder fed by the MEASURED mix — `AudioMixer` now measures the buffer the encoder receives (`MasterLevel`, `MasterImbalanceDb`), so the master cannot show a source instead of the output - `-12.4 dB` readout, and ONE L/R flag that appears above a 6 dB gap instead of a second ladder - bitrate / FPS / dropped / duration from the existing health poll MONO OUTPUT: - `AudioFold.ToMono` averages each stereo pair into both channels, applied after the limiter and the sync delay, so the stream AND the recording get what was folded - `MonoOutput` is persisted (`Audio.MonoOutput`) and restored at startup: an accessibility switch that resets each session is an accessibility failure - one click in the strip, remembered forever Guard: AudioFoldTests (hard-left reaches the right at half amplitude, hard-right — the inaudible case — reaches the left, centred material keeps its level, mono buffers untouched) and MasterStripTests (the strip binds the measured mix + the switch, the store round-trips it, and the fold is the tested helper rather than new arithmetic). 33 audio tests green.
This commit is contained in:
@@ -55,6 +55,7 @@ public partial class MainViewModel
|
||||
OnPropertyChanged(nameof(MeterBrush));
|
||||
OnPropertyChanged(nameof(MicMeterFraction));
|
||||
UpdateDuckState();
|
||||
RaiseMasterReadouts();
|
||||
OnPropertyChanged(nameof(MicMeterFraction));
|
||||
OnPropertyChanged(nameof(MicVolumeDb));
|
||||
OnPropertyChanged(nameof(MicVolumeDbLabel));
|
||||
@@ -200,6 +201,39 @@ public partial class MainViewModel
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Master strip ────────────────────────────────────────────────────────
|
||||
|
||||
private bool _monoOutput;
|
||||
|
||||
/// <summary>Collapse the output to mono. Persisted, because a creator who needs it needs it on
|
||||
/// every session — an accessibility switch that resets is an accessibility failure.</summary>
|
||||
public bool MonoOutput
|
||||
{
|
||||
get => _monoOutput;
|
||||
set
|
||||
{
|
||||
if (!SetProperty(ref _monoOutput, value)) return;
|
||||
_audioMixer.MonoOutput = value;
|
||||
_layoutStore.SaveMonoOutput(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Master ladder input: the measured mix, 0…1 on the same display scale.</summary>
|
||||
public double MasterMeterFraction => AudioLevelMeter.ToDisplay(_audioMixer.MasterLevel);
|
||||
|
||||
public string MasterLevelLabel => Helpers.GainDb.Label(Helpers.GainDb.ToDb(_audioMixer.MasterLevel)) + " dB";
|
||||
|
||||
/// <summary>True when the mix's channels differ by more than 6 dB — the one thing L/R is
|
||||
/// genuinely good for, shown as one flag instead of two ladders.</summary>
|
||||
public bool MasterImbalance => _audioMixer.MasterImbalanceDb > 6f;
|
||||
|
||||
private void RaiseMasterReadouts()
|
||||
{
|
||||
OnPropertyChanged(nameof(MasterMeterFraction));
|
||||
OnPropertyChanged(nameof(MasterLevelLabel));
|
||||
OnPropertyChanged(nameof(MasterImbalance));
|
||||
}
|
||||
|
||||
/// <summary>"0 ms (aligned)", "+50 ms", "−120 ms" — what the dock shows beside the slider.</summary>
|
||||
public string SyncOffsetLabel => AudioSyncOffsetMs == 0
|
||||
? "0 ms (aligned)"
|
||||
|
||||
Reference in New Issue
Block a user