diff --git a/DeepDrftPublic.Client/Controls/AudioPlayerBar/AudioPlayerBar.razor.cs b/DeepDrftPublic.Client/Controls/AudioPlayerBar/AudioPlayerBar.razor.cs index 9c70361..d21f610 100644 --- a/DeepDrftPublic.Client/Controls/AudioPlayerBar/AudioPlayerBar.razor.cs +++ b/DeepDrftPublic.Client/Controls/AudioPlayerBar/AudioPlayerBar.razor.cs @@ -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) diff --git a/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor b/DeepDrftPublic.Client/Controls/WaveformVisualizer.razor similarity index 73% rename from DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor rename to DeepDrftPublic.Client/Controls/WaveformVisualizer.razor index a911279..a1a15fd 100644 --- a/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor +++ b/DeepDrftPublic.Client/Controls/WaveformVisualizer.razor @@ -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. *@
-@* 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. *@ diff --git a/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.cs b/DeepDrftPublic.Client/Controls/WaveformVisualizer.razor.cs similarity index 94% rename from DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.cs rename to DeepDrftPublic.Client/Controls/WaveformVisualizer.razor.cs index dbb4f0f..91ff5eb 100644 --- a/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.cs +++ b/DeepDrftPublic.Client/Controls/WaveformVisualizer.razor.cs @@ -8,10 +8,10 @@ using Microsoft.JSInterop; namespace DeepDrftPublic.Client.Controls; /// -/// Full-page scrolling Mix waveform background. Standalone and reusable: give it a +/// Full-page scrolling waveform background. Standalone and reusable: give it a /// 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. is a @@ -20,12 +20,12 @@ namespace DeepDrftPublic.Client.Controls; /// parameter is the composability fallback for hosts that have no /// player cascade (e.g. an embed) and want to drive position themselves. /// -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 Logger { get; set; } + [Inject] public required WaveformVisualizerControlState ControlState { get; set; } + [Inject] public required ILogger 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 /// [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( - "import", "./js/visualizer/MixVisualizer.js"); + "import", "./js/visualizer/WaveformVisualizer.js"); _handle = await _module.InvokeAsync("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: /// /// scroll speed [0,1] is mapped onto the useful zoom band via - /// and pushed through setScrollSpeed + /// and pushed through setScrollSpeed /// (higher speed → tighter window → faster scroll); /// gradient rotation speed → setGradientRotationSpeed (live OKLab anchor rotation); /// gravity / heat / collision strength → their dedicated lava-physics dials; @@ -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); diff --git a/DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.css b/DeepDrftPublic.Client/Controls/WaveformVisualizer.razor.css similarity index 100% rename from DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor.css rename to DeepDrftPublic.Client/Controls/WaveformVisualizer.razor.css diff --git a/DeepDrftPublic.Client/Controls/MixVisualizerControls.razor b/DeepDrftPublic.Client/Controls/WaveformVisualizerControls.razor similarity index 96% rename from DeepDrftPublic.Client/Controls/MixVisualizerControls.razor rename to DeepDrftPublic.Client/Controls/WaveformVisualizerControls.razor index b42e75f..3207b8b 100644 --- a/DeepDrftPublic.Client/Controls/MixVisualizerControls.razor +++ b/DeepDrftPublic.Client/Controls/WaveformVisualizerControls.razor @@ -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). diff --git a/DeepDrftPublic.Client/Controls/MixVisualizerControls.razor.css b/DeepDrftPublic.Client/Controls/WaveformVisualizerControls.razor.css similarity index 100% rename from DeepDrftPublic.Client/Controls/MixVisualizerControls.razor.css rename to DeepDrftPublic.Client/Controls/WaveformVisualizerControls.razor.css diff --git a/DeepDrftPublic.Client/Controls/MixZoomMapping.cs b/DeepDrftPublic.Client/Controls/WaveformZoomMapping.cs similarity index 95% rename from DeepDrftPublic.Client/Controls/MixZoomMapping.cs rename to DeepDrftPublic.Client/Controls/WaveformZoomMapping.cs index 1ff0f5e..25fc2cc 100644 --- a/DeepDrftPublic.Client/Controls/MixZoomMapping.cs +++ b/DeepDrftPublic.Client/Controls/WaveformZoomMapping.cs @@ -1,13 +1,13 @@ namespace DeepDrftPublic.Client.Controls; /// -/// 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. /// -public static class MixZoomMapping +public static class WaveformZoomMapping { /// Shortest span (max zoom): one quarter note at 180 BPM = 60/180 s. Hard anchor. public const double MinVisibleSeconds = 60.0 / 180.0; diff --git a/DeepDrftPublic.Client/Layout/DeepDrftFooter.razor.css b/DeepDrftPublic.Client/Layout/DeepDrftFooter.razor.css index b0b7fc4..ddd9f65 100644 --- a/DeepDrftPublic.Client/Layout/DeepDrftFooter.razor.css +++ b/DeepDrftPublic.Client/Layout/DeepDrftFooter.razor.css @@ -1,6 +1,6 @@ .deepdrft-footer { /* position:relative + z-index:1 creates a stacking context that paints above the - MixWaveformVisualizer backdrop (z-index:0), keeping footer text fully legible. */ + WaveformVisualizer backdrop (z-index:0), keeping footer text fully legible. */ position: relative; z-index: 1; background: var(--deepdrft-white); diff --git a/DeepDrftPublic.Client/Pages/MixDetail.razor b/DeepDrftPublic.Client/Pages/MixDetail.razor index 12a2e14..fdd5c7d 100644 --- a/DeepDrftPublic.Client/Pages/MixDetail.razor +++ b/DeepDrftPublic.Client/Pages/MixDetail.razor @@ -36,7 +36,7 @@ else @* Full-page waveform sits behind the scaffold content. The scaffold's container is positioned above it via the mix-detail-foreground stacking context. TrackId lets the visualizer couple to playback only when the player is on this mix's track. *@ - +
@@ -57,9 +57,9 @@ else Phase 10 §4: the control is ALWAYS rendered; the lava-lamp toggle feeds its Visible parameter, and the control itself @if-gates the knobs while holding the container's reserved height — so content below never pops on toggle. The band mutates the shared - MixVisualizerControlState; the backdrop bridge pushes the dials. A knob drag does not + WaveformVisualizerControlState; the backdrop bridge pushes the dials. A knob drag does not toggle it — the lamp's click does. *@ - + @* Lava-lamp button top-right, across from the back link. Toggles the knob band below the @@ -126,8 +126,8 @@ else } } - // Lava-lamp knob-band visibility. Pure presentation over MixVisualizerControlState — gates whether - // the seven-knob MixVisualizerControls is rendered into the TopContent band; toggling it touches no + // Lava-lamp knob-band visibility. Pure presentation over WaveformVisualizerControlState — gates whether + // the seven-knob WaveformVisualizerControls is rendered into the TopContent band; toggling it touches no // control value or bridge push. The lava-lamp button's filled/outline glyph is driven off this flag. private bool _controlsExpanded; diff --git a/DeepDrftPublic.Client/Services/MixVisualizerControlState.cs b/DeepDrftPublic.Client/Services/WaveformVisualizerControlState.cs similarity index 84% rename from DeepDrftPublic.Client/Services/MixVisualizerControlState.cs rename to DeepDrftPublic.Client/Services/WaveformVisualizerControlState.cs index 7477b12..65b6470 100644 --- a/DeepDrftPublic.Client/Services/MixVisualizerControlState.cs +++ b/DeepDrftPublic.Client/Services/WaveformVisualizerControlState.cs @@ -1,7 +1,7 @@ namespace DeepDrftPublic.Client.Services; /// -/// Holds the Mix visualizer's eight continuous-control positions for the lifetime of the WASM app +/// Holds the waveform visualizer's eight continuous-control positions for the lifetime of the WASM app /// instance. Scoped in DI, so it lives across SPA navigations within one listening session — open a /// second mix and the knobs keep where you left them — but a fresh page load (F5) constructs a new /// instance, resetting to defaults. That matches the spec's "persist within session, reset on fresh @@ -11,27 +11,27 @@ namespace DeepDrftPublic.Client.Services; /// parameters: this is a plain scoped value holder, so widening it (the Phase 10 split of the single /// density knob into fluid-amount + fluid-viscosity) adds fields + defaults only and never forces a /// consumer constructor to grow. Each C#-side default mirrors a TS-side tuning anchor in -/// MixVisualizer.ts; keep the two in sync, as the DefaultVisibleSeconds / +/// WaveformVisualizer.ts; keep the two in sync, as the DefaultVisibleSeconds / /// DEFAULT_VISIBLE_SECONDS pair does. /// /// /// is the decoupling seam between the controls bar and the visualizer bridge. /// The controls component (a sibling of the backdrop in the page tree) only mutates this shared state -/// and raises ; the bridge component (MixWaveformVisualizer) subscribes +/// and raises ; the bridge component (WaveformVisualizer) subscribes /// and pushes the affected uniform/dial to the JS module. This keeps the JS module handle single-owned /// by the bridge — no handle sharing, no service-locator, no cross-component interop. /// /// -public sealed class MixVisualizerControlState +public sealed class WaveformVisualizerControlState { // ── The eight control defaults (Phase 10). Each mirrors a DEFAULT_* anchor in - // MixVisualizer.ts; keep the two in sync, as the default-sync discipline requires. + // WaveformVisualizer.ts; keep the two in sync, as the default-sync discipline requires. // Feel-anchors only — Daniel tunes on screen; the ~20% gravity / ~100% heat pair is his stated // sweet spot (§4c). /// /// Default scroll-speed dial. Normalized [0,1] → mapped C#-side to a visible time-span in seconds - /// via , then sent to MixVisualizer.ts as a seconds value via + /// via , then sent to WaveformVisualizer.ts as a seconds value via /// setScrollSpeed. The TS-side anchor is DEFAULT_VISIBLE_SECONDS. Opens mid-range /// (0 = slow/wide window, 1 = fast/tight window). /// @@ -39,26 +39,26 @@ public sealed class MixVisualizerControlState /// /// Default gradient-rotation-speed dial. Mirrors DEFAULT_GRADIENT_ROTATION_SPEED in - /// MixVisualizer.ts. Normalized [0,1] → slow→fast anchor-rotation; drives the live OKLab + /// WaveformVisualizer.ts. Normalized [0,1] → slow→fast anchor-rotation; drives the live OKLab /// three-colour gradient. 0.45 opens with a clearly-visible ~7 s colour cycle (Phase 10 §3.2). /// public const double DefaultGradientRotationSpeed = 0.45; /// - /// Default lava-gravity dial. Mirrors DEFAULT_LAVA_GRAVITY in MixVisualizer.ts. Normalized + /// Default lava-gravity dial. Mirrors DEFAULT_LAVA_GRAVITY in WaveformVisualizer.ts. Normalized /// [0,1]; 0 = near-weightless float, 1 = wax falls + settles fast. Tuned to Daniel's ~20% sweet spot. /// public const double DefaultLavaGravity = 0.2; /// - /// Default lava-heat dial. Mirrors DEFAULT_LAVA_HEAT in MixVisualizer.ts. Normalized [0,1]; + /// Default lava-heat dial. Mirrors DEFAULT_LAVA_HEAT in WaveformVisualizer.ts. Normalized [0,1]; /// 0 = wax rests at the bottom (collision-only), 1 = many small turbulent rising bubbles. Tuned to /// Daniel's ~100% sweet spot. /// public const double DefaultLavaHeat = 1.0; /// - /// Default fluid-amount dial. Mirrors DEFAULT_FLUID_AMOUNT in MixVisualizer.ts. The first + /// Default fluid-amount dial. Mirrors DEFAULT_FLUID_AMOUNT in WaveformVisualizer.ts. The first /// half of the Phase 10 "bubbles" split. Normalized [0,1]; 0 = few small blobs, 1 = many larger /// blobs (more wax in the container — blob count + per-blob volume). /// @@ -66,26 +66,26 @@ public sealed class MixVisualizerControlState /// /// Default fluid-viscosity / cohesion dial. Mirrors DEFAULT_FLUID_VISCOSITY in - /// MixVisualizer.ts. The second half of the Phase 10 "bubbles" split. Normalized [0,1]; 1 = high + /// WaveformVisualizer.ts. The second half of the Phase 10 "bubbles" split. Normalized [0,1]; 1 = high /// cohesion (crisp spheres that snap back), 0 = low cohesion (deforms freely, stays gooey/merged). /// public const double DefaultFluidViscosity = 0.6; /// - /// Default collision-strength dial. Mirrors DEFAULT_COLLISION_STRENGTH in MixVisualizer.ts. + /// Default collision-strength dial. Mirrors DEFAULT_COLLISION_STRENGTH in WaveformVisualizer.ts. /// Normalized [0,1]; 0 = soft mush, 1 = hard elastic up-and-out throw. /// public const double DefaultCollisionStrength = 0.5; /// - /// Default waveform-width dial. Mirrors DEFAULT_WAVEFORM_WIDTH in MixVisualizer.ts. + /// Default waveform-width dial. Mirrors DEFAULT_WAVEFORM_WIDTH in WaveformVisualizer.ts. /// Normalized [0,1], mapped onto the useful 10%–95% ribbon-extent band (Phase 10 §3.7); 0.5 opens /// mid-band. Narrowing clears room for the lava. /// public const double DefaultWaveformWidth = 0.5; /// Apparent bottom-to-top scroll rate, normalized [0,1]. Bridge maps it to a visible - /// time-span via ; the standalone resolution/zoom control is gone. + /// time-span via ; the standalone resolution/zoom control is gone. public double ScrollSpeed { get; set; } = DefaultScrollSpeed; /// Gradient anchor-rotation rate, normalized [0,1]. Drives the live OKLab gradient. diff --git a/DeepDrftPublic.Client/Startup.cs b/DeepDrftPublic.Client/Startup.cs index 27f5f0b..7e193d4 100644 --- a/DeepDrftPublic.Client/Startup.cs +++ b/DeepDrftPublic.Client/Startup.cs @@ -26,9 +26,9 @@ public static class Startup services.AddScoped(); services.AddScoped(); - // Mix visualizer controls — scoped so the four slider positions persist across navigation - // within a session and reset on a fresh page load (see MixVisualizerControlState). - services.AddScoped(); + // Waveform visualizer controls — scoped so the eight slider positions persist across navigation + // within a session and reset on a fresh page load (see WaveformVisualizerControlState). + services.AddScoped(); } public static void ConfigureApiHttpClient(IServiceCollection services, string baseAddress) diff --git a/DeepDrftPublic/Interop/visualizer/MixVisualizer.ts b/DeepDrftPublic/Interop/visualizer/WaveformVisualizer.ts similarity index 99% rename from DeepDrftPublic/Interop/visualizer/MixVisualizer.ts rename to DeepDrftPublic/Interop/visualizer/WaveformVisualizer.ts index c244f9c..8f07c58 100644 --- a/DeepDrftPublic/Interop/visualizer/MixVisualizer.ts +++ b/DeepDrftPublic/Interop/visualizer/WaveformVisualizer.ts @@ -1,5 +1,5 @@ /** - * MixVisualizer — the scrolling Mix waveform background (Phase 10 + Lava Reframe). + * WaveformVisualizer — the scrolling waveform background (Phase 10 + Lava Reframe). * * What this renders: a *windowed* slice of a mix's loudness profile, scrolling * bottom-to-top, coupled to playback position. New audio enters at the bottom, @@ -60,7 +60,7 @@ export const MAX_VISIBLE_SECONDS = 30; export const DEFAULT_VISIBLE_SECONDS = 10; // ── Control tuning anchors. These mirror the C#-side defaults in ────────────────── -// MixVisualizerControlState.cs — keep the two in sync, exactly as the +// WaveformVisualizerControlState.ts — keep the two in sync, exactly as the // DEFAULT_VISIBLE_SECONDS / DefaultVisibleSeconds pair is kept in sync. All seven are // normalized [0,1] (scroll speed is mapped to a visible time-span on the C# side before it // reaches setScrollSpeed; it arrives here already in seconds). @@ -359,7 +359,7 @@ const PLAYHEAD_CORRECTION_SNAP_SECONDS = 0.0005; // ── Diagnostics ────────────────────────────────────────────────────────────────── // // Set true to surface the init/draw/datum/playback seams to the browser console -// (all prefixed `[MixVisualizer]`). The error/warn paths fire regardless of this +// (all prefixed `[WaveformVisualizer]`). The error/warn paths fire regardless of this // flag — they only trigger on the abnormal path. The verbose `log` paths (datum // received/uploaded, first-draw dimensions, GL error after first draw) are gated // here so they can be silenced once the renderer is confirmed healthy. Leave it on @@ -367,7 +367,7 @@ const PLAYHEAD_CORRECTION_SNAP_SECONDS = 0.0005; // NOTE: defaults to false; set true temporarily to surface verbose seams in-browser. const DEBUG = false; -const TAG = '[MixVisualizer]'; +const TAG = '[WaveformVisualizer]'; function debugLog(...args: unknown[]): void { if (DEBUG) console.log(TAG, ...args); } @@ -507,7 +507,7 @@ interface Playback { pushWallClockMs: number; } -export interface MixVisualizerHandle { +export interface WaveformVisualizerHandle { setDatum(samplesBase64: string, durationSeconds: number): void; setPlayback(positionSeconds: number, isPlaying: boolean): void; /** Visible time-span in seconds — the scroll-speed control, mapped from [0,1] on the C# side. */ @@ -1028,13 +1028,13 @@ void main() { /** Compile one shader stage, throwing with the info log on failure. */ function compileShader(gl: WebGL2RenderingContext, type: number, source: string): WebGLShader { const shader = gl.createShader(type); - if (!shader) throw new Error('MixVisualizer: gl.createShader returned null.'); + if (!shader) throw new Error('WaveformVisualizer: gl.createShader returned null.'); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { const log = gl.getShaderInfoLog(shader); gl.deleteShader(shader); - throw new Error(`MixVisualizer: shader compile failed: ${log}`); + throw new Error(`WaveformVisualizer: shader compile failed: ${log}`); } return shader; } @@ -1044,7 +1044,7 @@ function linkProgram(gl: WebGL2RenderingContext): WebGLProgram { const vert = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER); const frag = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER); const program = gl.createProgram(); - if (!program) throw new Error('MixVisualizer: gl.createProgram returned null.'); + if (!program) throw new Error('WaveformVisualizer: gl.createProgram returned null.'); gl.attachShader(program, vert); gl.attachShader(program, frag); gl.linkProgram(program); @@ -1054,13 +1054,13 @@ function linkProgram(gl: WebGL2RenderingContext): WebGLProgram { if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { const log = gl.getProgramInfoLog(program); gl.deleteProgram(program); - throw new Error(`MixVisualizer: program link failed: ${log}`); + throw new Error(`WaveformVisualizer: program link failed: ${log}`); } return program; } /** The no-op handle returned when WebGL2 is unavailable or setup fails. */ -function noopHandle(): MixVisualizerHandle { +function noopHandle(): WaveformVisualizerHandle { return { setDatum() {}, setPlayback() {}, @@ -1077,7 +1077,7 @@ function noopHandle(): MixVisualizerHandle { }; } -export function create(canvas: HTMLCanvasElement): MixVisualizerHandle { +export function create(canvas: HTMLCanvasElement): WaveformVisualizerHandle { // premultipliedAlpha so the translucent ribbon composites correctly over the // page; antialias off (the soft-edge smoothstep handles AA in-shader, and MSAA // would cost fill rate we don't need for a backdrop).