Files
deepdrft/DeepDrftPublic.Client/Controls/MixZoomMapping.cs
T

37 lines
1.7 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.
namespace DeepDrftPublic.Client.Controls;
/// <summary>
/// Pure mapping between the Mix visualizer's zoom slider position [0, 1] and the visible time-span in
/// seconds. The span range is wide (0.333 s … 30 s, ~90×), so the mapping is logarithmic — equal
/// slider travel changes the span by an equal *ratio*, which feels even to the hand. Slider
/// orientation: fraction 0 = most zoomed-out (longest span), fraction 1 = most zoomed-in (the
/// 0.333 s quarter-note-@-180-BPM anchor). Extracted from the component so the math is unit-testable.
/// </summary>
public static class MixZoomMapping
{
/// <summary>Shortest span (max zoom): one quarter note at 180 BPM = 60/180 s. Hard anchor.</summary>
public const double MinVisibleSeconds = 60.0 / 180.0;
/// <summary>Longest span (min zoom). Tunable.</summary>
public const double MaxVisibleSeconds = 30.0;
/// <summary>Slider position [0, 1] -> visible seconds. 0 = zoomed out, 1 = zoomed in.</summary>
public static double FractionToSeconds(double fraction)
{
fraction = Math.Clamp(fraction, 0, 1);
var logMax = Math.Log(MaxVisibleSeconds);
var logMin = Math.Log(MinVisibleSeconds);
// Interpolate in log space from out (frac 0 -> logMax) to in (frac 1 -> logMin).
return Math.Exp(logMax + (logMin - logMax) * fraction);
}
/// <summary>Visible seconds -> slider position [0, 1]. Inverse of <see cref="FractionToSeconds"/>.</summary>
public static double SecondsToFraction(double seconds)
{
seconds = Math.Clamp(seconds, MinVisibleSeconds, MaxVisibleSeconds);
var logMax = Math.Log(MaxVisibleSeconds);
var logMin = Math.Log(MinVisibleSeconds);
return (logMax - Math.Log(seconds)) / (logMax - logMin);
}
}