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:
@@ -0,0 +1,41 @@
|
||||
using Xunit;
|
||||
using ytLive.Helpers;
|
||||
using ytLive.Services.Audio;
|
||||
using ytLive.ViewModels;
|
||||
|
||||
namespace ytLive.Tests;
|
||||
|
||||
/// <summary>The master strip is where the accessibility switch lives, so its wiring matters more
|
||||
/// than its looks: MONO must reach the mixer, be remembered across sessions, and the strip's ladder
|
||||
/// must show the MEASURED mix — with one L/R flag instead of two ladders.
|
||||
/// </summary>
|
||||
public class MasterStripTests
|
||||
{
|
||||
[Fact]
|
||||
public void The_master_strip_shows_the_measured_mix_and_the_mono_switch_is_persisted()
|
||||
{
|
||||
var dock = SourceAssert.Text("Controls", "AudioDock.xaml");
|
||||
Assert.Contains("IsChecked=\"{Binding MonoOutput, Mode=TwoWay}\"", dock);
|
||||
Assert.Contains("Level=\"{Binding MasterMeterFraction}\"", dock);
|
||||
Assert.Contains("Text=\"{Binding MasterLevelLabel}\"", dock);
|
||||
Assert.Contains("Visibility=\"{Binding MasterImbalance, Converter={StaticResource BoolToVis}}\"", dock);
|
||||
// One ladder on the master, not a pair.
|
||||
Assert.Equal(1, System.Text.RegularExpressions.Regex.Matches(
|
||||
dock[dock.IndexOf("MASTER", System.StringComparison.Ordinal)..], "SegmentMeter").Count);
|
||||
|
||||
// The switch reaches the mixer and the store.
|
||||
Assert.NotNull(typeof(AudioMixer).GetProperty("MonoOutput"));
|
||||
Assert.NotNull(typeof(MainViewModel).GetProperty("MonoOutput"));
|
||||
var settings = SourceAssert.Text("Services", "LayoutStore.Settings.cs");
|
||||
Assert.Contains("Audio.MonoOutput", settings);
|
||||
Assert.Contains("LoadMonoOutput", settings);
|
||||
|
||||
// The mixer measures the finished mix, so the ladder cannot show a source instead of the output.
|
||||
Assert.NotNull(typeof(AudioMixer).GetProperty("MasterLevel"));
|
||||
Assert.NotNull(typeof(AudioMixer).GetProperty("MasterImbalanceDb"));
|
||||
|
||||
// And the fold is the tested helper, not new arithmetic in the mixer.
|
||||
Assert.Contains("AudioFold.ToMono", SourceAssert.Text("Services", "Audio", "AudioMixer.cs"));
|
||||
Assert.Equal(0.25f, GainDb.MonoFold(0.5f, 0f));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user