Files
LlamaCasty/ytLive.Tests/MeterScaleTests.cs
T
gramps 2607ecf210 fix(dock): TRAX ladder gets the mic's ballistics (and a 33 Hz beat)
Reported: the TRAX bar moves, but its sampling looks far slower than the mic meter.

Cause: the TRAX number was a raw instantaneous peak per metering block — a stutter sampled by the UI
timer, with no smoothing. The mic looks fluid because it is smoothed at audio-callback rate.

Fix: the player now smooths its measured level with the SAME curve the mic uses
(MeterScale.NextLevel: fast attack, gentle decay), and the dock's meter clock runs at ~30 Hz instead
of 20. Two ladders that move alike, because they are the same ballistics.

Guard: MeterScaleTests pins the attack/decay behaviour alongside peak-hold.
2026-10-30 13:28:32 -07:00

42 lines
2.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Xunit;
using ytLive.Helpers;
namespace ytLive.Tests;
/// <summary>A segment ladder is only useful if the band it paints is the level it measured. The
/// thresholds are DESIGN.md's (nominal / caution / peak), and peak-hold is what makes clipping
/// visible — a bar that follows the moment hides the one audio fault that cannot be fixed later.
/// </summary>
public class MeterScaleTests
{
[Fact]
public void Bands_peak_hold_and_the_display_scale_follow_the_standard()
{
// Bands at the documented thresholds.
Assert.Equal(MeterBand.Nominal, MeterScale.BandFor(-30f));
Assert.Equal(MeterBand.Nominal, MeterScale.BandFor(-12.1f));
Assert.Equal(MeterBand.Caution, MeterScale.BandFor(-12f));
Assert.Equal(MeterBand.Caution, MeterScale.BandFor(-6f));
Assert.Equal(MeterBand.Peak, MeterScale.BandFor(-3f));
Assert.Equal(MeterBand.Peak, MeterScale.BandFor(0f));
// Display fraction: −60 dBFS is empty, 0 dBFS is full, −30 is halfway, and nothing escapes.
Assert.Equal(0f, MeterScale.ToFraction(-60f));
Assert.Equal(1f, MeterScale.ToFraction(0f));
Assert.Equal(0.5f, MeterScale.ToFraction(-30f), 4);
Assert.Equal(1f, MeterScale.ToFraction(+12f));
Assert.Equal(0f, MeterScale.ToFraction(-120f));
// Level ballistics: a jump is followed quickly, a drop falls gently — the same curve that
// makes the mic meter look fluid. Raw peaks at a 30 Hz UI tick stutter without it.
Assert.Equal(0.6f, MeterScale.NextLevel(0f, 1f), 3); // attack
Assert.True(MeterScale.NextLevel(0.9f, 0.1f) > 0.8f); // decay is gentle
Assert.True(MeterScale.NextLevel(0.1f, 0.9f) > 0.5f); // rise is fast
// Peak hold rises instantly, then decays at the stated rate.
Assert.Equal(0.8f, MeterScale.NextPeak(0.2f, 0.8f, 0.05f));
Assert.Equal(0.7f, MeterScale.NextPeak(0.8f, 0.1f, 0.1f / 0.35f), 3); // 0.1 fall at 0.35/s
Assert.Equal(0f, MeterScale.NextPeak(0.1f, 0f, 10f)); // never negative
}
}