refactor(12.A): rename Mix* visualizer engine to Waveform* abstraction
This commit is contained in:
@@ -29,7 +29,7 @@ public partial class AudioPlayerBar : ComponentBase, IAsyncDisposable
|
||||
// error banner.
|
||||
//
|
||||
// _miniDock is the minimized FAB container. We observe it in minimized state so
|
||||
// --player-height stays non-zero (the FAB's actual height) and the MixWaveformVisualizer
|
||||
// --player-height stays non-zero (the FAB's actual height) and the WaveformVisualizer
|
||||
// clips to the top of the FAB rather than extending to the viewport bottom (fix §1).
|
||||
// The player-spacer's .minimized class uses a hardcoded 60px and ignores the var,
|
||||
// so publishing the FAB height here does not regress the spacer.
|
||||
@@ -125,7 +125,7 @@ public partial class AudioPlayerBar : ComponentBase, IAsyncDisposable
|
||||
// The Fixed embed is already in normal flow — no spacer/clip needed.
|
||||
// For the docked player: we observe in BOTH expanded and minimized states
|
||||
// so --player-height always reflects the live height of whichever element
|
||||
// is visible. This keeps the MixWaveformVisualizer clipped to the top of
|
||||
// is visible. This keeps the WaveformVisualizer clipped to the top of
|
||||
// the footer in both states (fix §1).
|
||||
// expanded → observe _playerRoot (full player bar, reflows across breakpoints)
|
||||
// minimized → observe _miniDock (floating FAB container, ~56–60px)
|
||||
|
||||
+4
-4
@@ -1,16 +1,16 @@
|
||||
@namespace DeepDrftPublic.Client.Controls
|
||||
|
||||
@* Full-page scrolling Mix waveform background (Phase 9, 8.K). A windowed slice of the mix's loudness
|
||||
@* Full-page scrolling waveform background (Phase 9, 8.K). A windowed slice of the track's loudness
|
||||
datum scrolls bottom-to-top, coupled to playback; a zoom slider controls the visible time-span (and
|
||||
so the apparent scroll speed, Guitar-Hero style). Strictly read-only: it self-fetches its datum from
|
||||
ReleaseEntryKey, takes playback as one-way input only, and never seeks or writes back. The rAF loop and all
|
||||
scroll/zoom/compositing math live in the MixVisualizer.ts interop module; this component is a thin
|
||||
scroll/zoom/compositing math live in the WaveformVisualizer.ts interop module; this component is a thin
|
||||
bridge that feeds it datum + playback + zoom + theme. Deliberately NOT the player-bar peak-bar idiom. *@
|
||||
|
||||
<div class="mix-waveform-bg">
|
||||
<canvas @ref="_canvas" class="mix-waveform-canvas"></canvas>
|
||||
</div>
|
||||
|
||||
@* The viewing controls (resolution + the three Wave 2 controls) live in MixVisualizerControls,
|
||||
@* The viewing controls (resolution + the three Wave 2 controls) live in WaveformVisualizerControls,
|
||||
rendered in the mix-detail foreground row below the back button — NOT here. This component is now a
|
||||
pure backdrop bridge; it pushes uniforms in response to the shared MixVisualizerControlState. *@
|
||||
pure backdrop bridge; it pushes uniforms in response to the shared WaveformVisualizerControlState. *@
|
||||
+12
-12
@@ -8,10 +8,10 @@ using Microsoft.JSInterop;
|
||||
namespace DeepDrftPublic.Client.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Full-page scrolling Mix waveform background. Standalone and reusable: give it a
|
||||
/// Full-page scrolling waveform background. Standalone and reusable: give it a
|
||||
/// <see cref="ReleaseEntryKey"/> and it fetches its own loudness datum. The rendering itself — a windowed,
|
||||
/// bottom-to-top, playback-coupled scroll with a glassy theme-aware gradient — lives in the
|
||||
/// MixVisualizer.ts interop module; this component is the bridge that feeds it datum, playback
|
||||
/// WaveformVisualizer.ts interop module; this component is the bridge that feeds it datum, playback
|
||||
/// position, zoom, and theme, and owns the module lifecycle.
|
||||
///
|
||||
/// Strictly read-only (spec §D): no seek, no two-way write-back. <see cref="PlaybackPosition"/> is a
|
||||
@@ -20,12 +20,12 @@ namespace DeepDrftPublic.Client.Controls;
|
||||
/// <see cref="PlaybackPosition"/> parameter is the composability fallback for hosts that have no
|
||||
/// player cascade (e.g. an embed) and want to drive position themselves.
|
||||
/// </summary>
|
||||
public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
public partial class WaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
{
|
||||
[Inject] public required IReleaseDataService ReleaseData { get; set; }
|
||||
[Inject] public required IJSRuntime JS { get; set; }
|
||||
[Inject] public required MixVisualizerControlState ControlState { get; set; }
|
||||
[Inject] public required ILogger<MixWaveformVisualizer> Logger { get; set; }
|
||||
[Inject] public required WaveformVisualizerControlState ControlState { get; set; }
|
||||
[Inject] public required ILogger<WaveformVisualizer> Logger { get; set; }
|
||||
|
||||
// Live playback + the mix duration come from the cascaded streaming player when present. The
|
||||
// cascade is IsFixed, so we subscribe to its multicast StateChanged side-channel to learn about
|
||||
@@ -54,12 +54,12 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
/// </summary>
|
||||
[Parameter] public double PlaybackPosition { get; set; }
|
||||
|
||||
// Bridge-level diagnostics. Mirrors the JS-side DEBUG flag in MixVisualizer.ts: when true the
|
||||
// Bridge-level diagnostics. Mirrors the JS-side DEBUG flag in WaveformVisualizer.ts: when true the
|
||||
// datum-fetch / subscription / playback-coupling seams log to the browser console (prefixed
|
||||
// `[MixVisualizer]`, same as the JS logs so the two interleave into one timeline). These pinpoint
|
||||
// `[WaveformVisualizer]`, same as the JS logs so the two interleave into one timeline). These pinpoint
|
||||
// which upstream link is broken when the ribbon stays blank — set true temporarily to diagnose.
|
||||
private static readonly bool Debug = false;
|
||||
private const string Tag = "[MixVisualizer]";
|
||||
private const string Tag = "[WaveformVisualizer]";
|
||||
|
||||
private static void DebugLog(string message)
|
||||
{
|
||||
@@ -164,12 +164,12 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
try
|
||||
{
|
||||
_module = await JS.InvokeAsync<IJSObjectReference>(
|
||||
"import", "./js/visualizer/MixVisualizer.js");
|
||||
"import", "./js/visualizer/WaveformVisualizer.js");
|
||||
_handle = await _module.InvokeAsync<IJSObjectReference>("create", _canvas);
|
||||
}
|
||||
catch (JSException ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "MixWaveformVisualizer: failed to load the visualizer module; rendering a plain backdrop.");
|
||||
Logger.LogWarning(ex, "WaveformVisualizer: failed to load the visualizer module; rendering a plain backdrop.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
/// and to re-push when the controls bar signals a change. Each value is its own dedicated dial:
|
||||
/// <list type="bullet">
|
||||
/// <item>scroll speed [0,1] is mapped onto the useful zoom band via
|
||||
/// <see cref="MixZoomMapping.ScrollKnobToSeconds"/> and pushed through <c>setScrollSpeed</c>
|
||||
/// <see cref="WaveformZoomMapping.ScrollKnobToSeconds"/> and pushed through <c>setScrollSpeed</c>
|
||||
/// (higher speed → tighter window → faster scroll);</item>
|
||||
/// <item>gradient rotation speed → <c>setGradientRotationSpeed</c> (live OKLab anchor rotation);</item>
|
||||
/// <item>gravity / heat / collision strength → their dedicated lava-physics dials;</item>
|
||||
@@ -218,7 +218,7 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
|
||||
if (_handle is null) return;
|
||||
// Scroll speed is a normalized [0,1] axis; map it onto the useful zoom band (Phase 10 retune —
|
||||
// the knob's full travel now covers the 60%–100% zoom range, dropping the dead slow/wide end).
|
||||
var visibleSeconds = MixZoomMapping.ScrollKnobToSeconds(ControlState.ScrollSpeed);
|
||||
var visibleSeconds = WaveformZoomMapping.ScrollKnobToSeconds(ControlState.ScrollSpeed);
|
||||
await _handle.InvokeVoidAsync("setScrollSpeed", visibleSeconds);
|
||||
await _handle.InvokeVoidAsync("setGradientRotationSpeed", ControlState.GradientRotationSpeed);
|
||||
await _handle.InvokeVoidAsync("setLavaGravity", ControlState.LavaGravity);
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
@namespace DeepDrftPublic.Client.Controls
|
||||
@using DeepDrftPublic.Client.Services
|
||||
@inject MixVisualizerControlState ControlState
|
||||
@inject WaveformVisualizerControlState ControlState
|
||||
|
||||
@* The Mix visualizer controls. EIGHT continuous RadialKnobs — scroll speed, gradient rotation speed,
|
||||
@* The waveform visualizer controls. EIGHT continuous RadialKnobs — scroll speed, gradient rotation speed,
|
||||
lava gravity, lava heat, fluid amount, fluid viscosity, collision strength, waveform width — each its
|
||||
own dedicated control with a Material-icon caption. The single "bubbles" knob is split into
|
||||
fluid-amount + fluid-viscosity (Phase 10 §5).
|
||||
@@ -14,8 +14,8 @@
|
||||
convention) — the knobs are simply not rendered when hidden, while a min-height container holds the
|
||||
layout. No collapse animation, no glass surface, no CSS visibility-hiding of populated knobs.
|
||||
|
||||
It owns NO JS interop: it mutates the shared, session-scoped MixVisualizerControlState and raises its
|
||||
Changed event. The backdrop bridge (MixWaveformVisualizer) subscribes to that event and pushes the
|
||||
It owns NO JS interop: it mutates the shared, session-scoped WaveformVisualizerControlState and raises its
|
||||
Changed event. The backdrop bridge (WaveformVisualizer) subscribes to that event and pushes the
|
||||
affected dial to the WebGL module. That keeps the JS module handle single-owned by the bridge and
|
||||
this component purely presentational. None of these is a seek surface (read-only contract §D).
|
||||
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
namespace DeepDrftPublic.Client.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Pure mapping between the Mix visualizer's zoom slider position [0, 1] and the visible time-span in
|
||||
/// Pure mapping between the waveform 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
|
||||
public static class WaveformZoomMapping
|
||||
{
|
||||
/// <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;
|
||||
Reference in New Issue
Block a user