Files
LlamaCasty/ytLive.Tests/MasterStripTests.cs
T
gramps 5889d71db6 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.
2026-10-30 13:18:23 -07:00

42 lines
2.0 KiB
C#

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));
}
}