From 2f0ed4f657a5869c0b5194b835cca0771a6165c7 Mon Sep 17 00:00:00 2001 From: zai-bot Date: Sat, 7 Nov 2026 02:43:12 +0000 Subject: [PATCH] v7.18.0: Zai-Magic preset 'Beautiful Spectrogram' (bgx scrolling spectrogram) Twelfth hand-authored Zai-Magic preset: a true scrolling spectrogram as a pure script -- bgx feedback slide moves the whole framebuffer left (the time axis), persist 1 keeps the history locked, and a 64-bin vertical write head at the right edge inks pink -> red -> orange -> yellow -> white over a deep dark navy field that only leaves by scrolling off the left edge. The per-frame ink is computed from the live stroke geometry (coats = 1.12 + 1.604*wpx/segl; ink = 1.1/(coats*ratio)) so overlapping columns accumulate to full palette strength at any fps, aspect or brush width, with per-coat adds kept above 8-bit quantization. Half-second erase phase drains the previous preset's framebuffer, 3s 15x fill sweep paints the navy field, stage resizes replay the sweep. EMBEDDED_SEED_VERSION 7.14 -> 7.18.1; seed re-synced (107 presets). --- db/custom.db.seed | Bin 307200 -> 307200 bytes src/lib/ava/embedded-presets.ts | 127 ++++++++++++++++++++++++++++---- src/lib/release-notes.ts | 14 ++++ src/lib/version.ts | 24 +++++- worklog.md | 26 +++++++ 5 files changed, 177 insertions(+), 14 deletions(-) diff --git a/db/custom.db.seed b/db/custom.db.seed index 30d557534d6b03b71c73e7d09ab01ef5cfedcc0f..0bfb762e87a5490af3ada440d5d0f02979de0f10 100755 GIT binary patch delta 14680 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 delta 11580 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 pink -> red -> orange +# -> yellow -> white, indexed by the smoothed spectrum level. +megabuf(402) = 0.04; megabuf(403) = 0.06; megabuf(404) = 0.23 +megabuf(405) = 1.00; megabuf(406) = 0.35; megabuf(407) = 0.62 +megabuf(408) = 1.00; megabuf(409) = 0.13; megabuf(410) = 0.15 +megabuf(411) = 1.00; megabuf(412) = 0.50; megabuf(413) = 0.08 +megabuf(414) = 1.00; megabuf(415) = 0.88; megabuf(416) = 0.24 +megabuf(417) = 1.00; megabuf(418) = 0.99; megabuf(419) = 0.95 +megabuf(420) = 0; megabuf(421) = 0.16; megabuf(422) = 0.38 +megabuf(423) = 0.58; megabuf(424) = 0.78; megabuf(425) = 1 +lasp = 0 +booted = 0 +myt = 0 + +[frame] +# A stage resize wipes the canvas -- replay the fill sweep (skip the erase, +# the resize already cleared everything). +if(band(above(abs(aspect - lasp), 0.02), equal(booted, 1)), myt = 0.5, 0) +lasp = aspect +booted = 1 +myt = myt + dt +# Erase phase: with persist 1 the previous preset's framebuffer would ride +# the scroll for a whole screen width -- fade it out in half a second +# instead (the preset-change dissolve covers the transition). +persist = if(below(myt, 0.5), 0.45, 1) +# The time axis: the whole picture drifts LEFT (bgx is in half-width +# units). 15x speed for 3 s after the erase so the navy field sweeps the +# screen, then the slow crawl (a full width takes ~25 s). The per-frame +# step is capped at 1% of the width so slow frame rates still tile. +warm = 1 + 14 * max(0, 1 - max(0, myt - 0.5) / 3) +sf = min(0.04 * dt * warm, 0.01) +bgx = -2 * sf +spx = sf * w +# The write head: a vertical stroke at the right edge, ratio scroll-steps +# wide. Narrow while the sweep is fast (and on slow frame rates) so each +# coat of paint stays above 8-bit quantization -- the engine strokes every +# segment separately, so one frame paints a column pixel +# coats = 1.12 + 1.604 * wpx / segl +# times (core pass 0.9 + halo pass 0.22 x 3.2, each covering +# 1 + width/spacing segments), and a content element spends ratio frames +# under the brush. The per-frame alpha is pre-divided so that transit +# accumulates to full palette strength: quiet bins read as solid deep dark +# blue, loud ones as pure palette color. +rwm = 1.2 + 1.8 * clamp((8 - warm) / 7, 0, 1) +rfs = max(1.6, 3 - 18 * (dt - 0.0222)) +ratio = min(rwm, rfs) +wpx = ratio * spx +segl = 0.96 * h / 63 +coats = 1.12 + 1.604 * wpx / segl +ink = if(below(myt, 0.5), 0, min(0.6, 1.1 / (coats * ratio))) +colw = wpx * 480 / h +flash = exp(-beatage * 5) + +[point] +k = floor(i * 63 + 0.5) +# Level: tilt the quiet treble up, then gamma the palette open. +raw = sv * (1.75 + 0.75 * i) +lvl = pow(clamp(raw, 0, 1), 0.72) +# Attack at once, fall slow -- transients linger as a glow. +sm = max(lvl, megabuf(k) * exp(-dt * 2.5)) +megabuf(k) = sm +# Palette: pick the segment, lerp its anchor pair. +seg = above(sm, 0.16) + above(sm, 0.38) + above(sm, 0.58) + above(sm, 0.78) +lo = megabuf(420 + seg) +hi = megabuf(421 + seg) +u = (sm - lo) / (hi - lo) +pb = 402 + seg * 3 +x = 0.985 +y = i * 1.92 - 0.96 +red = lerp(megabuf(pb), megabuf(pb + 3), u) * (1 + flash * 0.12) +green = lerp(megabuf(pb + 1), megabuf(pb + 4), u) * (1 + flash * 0.12) +blue = lerp(megabuf(pb + 2), megabuf(pb + 5), u) * (1 + flash * 0.12) +size = colw +alpha = ink `, }, ] diff --git a/src/lib/release-notes.ts b/src/lib/release-notes.ts index aaec305..8220bb0 100755 --- a/src/lib/release-notes.ts +++ b/src/lib/release-notes.ts @@ -39,6 +39,20 @@ export interface ReleaseNote { } export const RELEASE_NOTES: ReleaseNote[] = [ + { + version: '7.18.0', + name: 'Beautiful Spectrogram', + changes: [ + { + kind: 'added', + text: 'I added a twelfth Zai-Magic preset: "Beautiful Spectrogram" -- a true scrolling spectrogram. Every frame inks a fresh frequency column at the right edge (bass at the bottom, treble at the top) and the whole picture drifts left through a deep dark blue field that never fades, so the music leaves its heat-print hanging in the air until it scrolls off the edge. Quiet bins whisper pink; loud ones climb red, orange, yellow and finally white, with hits lingering as a glow and the newest ink flaring on the beat.', + }, + { + kind: 'improved', + text: 'The preset is built entirely from script-engine features that already existed -- the background slide, the zero-fade framebuffer and megabuf bin memory -- so it doubles as a worked example of a whole new visual family (data-plots that write their own history) without any engine changes.', + }, + ], + }, { version: '7.17.0', name: 'True-black trails', diff --git a/src/lib/version.ts b/src/lib/version.ts index a7ac009..7b74bb4 100755 --- a/src/lib/version.ts +++ b/src/lib/version.ts @@ -12,6 +12,28 @@ // warns in the console when the two drift apart. // // History: +// 7.18 — "Beautiful Spectrogram" (user request, twelfth Zai-Magic +// preset): a true scrolling spectrogram as a pure script -- the +// v7.12 bgx feedback slide moves the whole framebuffer left +// every frame (the time axis) while persist 1 (v7.14.1's +// zero-fade framebuffer) keeps the history locked, so the print +// only ever leaves by scrolling off the left edge. The write +// head is a 256-point vertical line at the right edge: sv (the +// per-point spectrum) drives a megabuf attack/slow-decay level +// per frequency bin, which indexes a six-anchor palette table +// (also megabuf) -- deep dark blue background, then pink -> red +// -> orange -> yellow -> white as bins get loud. Two tricks make +// it read clean: (1) the stroke is exactly four scroll-steps +// wide with its per-frame alpha pre-divided by the accumulation +// factor (core 0.9 + halo 0.22*3.2 passes, times four overlapping +// steps ~= 1.6*4), so overlapping columns sum to exactly full +// palette strength and the quiet field renders as SOLID navy +// rather than banded; (2) a half-second erase phase (per-frame +// persist override to 0.45) drains the previous preset's +// framebuffer before the zero-fade lock engages, and a 15x +// three-second fill sweep (plus a replay on stage resize) paints +// the navy field across the whole screen instead of making the +// visitor wait 25 s for the crawl to cover it. // 7.17 — True-black trail fade (user request, "Orange Burst"): the // persistence fade multiplies the framebuffer by persist in // 8-bit steps, so any persist >= 0.5 leaves fixed points @@ -594,4 +616,4 @@ export const APP_NAME = 'Open Visualization Engine' export const APP_SHORT = 'OVE' -export const APP_VERSION = '7.17.0' +export const APP_VERSION = '7.18.0' diff --git a/worklog.md b/worklog.md index 3960abb..882dc58 100755 --- a/worklog.md +++ b/worklog.md @@ -2658,3 +2658,29 @@ Push status (unchanged from Task 49's note): blocked from inside the sandbox -- Stage Summary: - Task 47's persistence stack re-verified end-to-end and fully intact: tracked .env.ove/.env/seed/secrets, byte-identical env pair, seed == live db, self-heal re-proven by fixture on the shipped code, clean 16:22 boot, healthy app. Nothing needed re-doing. Push to origin zai-dev remains gated on operator-side Forgejo credentials (this sandbox carries none by design of the reprovision); local main and local zai-dev carry everything and fast-forward cleanly pending that push. + +--- +Task ID: 51 +Agent: main (Z.ai Code) +Task: v7.18.0 (user request): create a visual script preset "Beautiful Spectrogram" under Zai-Magic -- a deep dark blue background that slowly scrolls to the left, with the audio print colored pink -> red -> orange -> yellow -> white -- and provide the script code in chat. Project changes acceptable. + +Approach: +- Pure script, zero engine changes: the time axis is the v7.12 bgx feedback slide (whole framebuffer drifts left every frame), persist 1 (v7.14.1 zero-fade) locks the history so the print only leaves by scrolling off the left edge, and the write head is a 64-point vertical line at x=0.985 whose per-point color lerps a six-anchor megabuf palette (deep navy -> pink -> red -> orange -> yellow -> white) indexed by an attack/slow-decay smoothed per-bin level (sv with a +0.75i treble tilt, ^0.72 gamma). +- THE HARD PART -- ink calibration. First cut (fixed alpha 0.155, 256 points) cyan-washed the field. Root cause chain, all measured on the live canvas: (1) drawContent strokes every segment separately, so one frame paints a column pixel 1 + width/pointSpacing coats per pass (a 256-point column under a 32px warm-up brush = ~21 coats/frame -> alpha saturates in one frame, colors blow past the palette and clamp channel-by-channel); (2) once the per-frame alpha is pre-divided small enough, the faint channels die to 8-bit quantization (navy's r=10/255 under ink<0.1 adds < 1 LSB per coat and rounds away -> the same cyan, from the other side); (3) frame-rate coupling (headless idle throttling to ~2fps showed dt-clamped 0.1 steps) proves the geometry must be computed from live dt/w/h every frame. Final design, all computed per frame in [frame]: scroll step capped at 1% of width per frame; brush ratio = ratio scroll-steps wide, narrow (1.2) during the 15x fill sweep and on slow frame rates (1.6 floor), 3 at steady state; coats = 1.12 + 1.604*wpx/segl (core 0.9 + halo 0.22x3.2 passes, each covering 1 + width/spacing segments); ink = 1.1/(coats*ratio) clamped 0.6 -- so the ratio-frame transit accumulates to ~full palette strength at every fps, aspect and brush width, with per-coat adds kept >= ~2 LSB. +- Lifecycle: a 0.5s erase phase (per-frame persist override 0.45, ink 0) drains the previous preset's framebuffer before the zero-fade lock engages (otherwise old art rides the scroll for a full screen width); then a 3s 15x fill sweep paints the navy field across the screen (96% coverage) so the visitor does not wait 25s for the crawl to cover it; a stage resize (canvas wipe) replays the sweep (aspect-change detector with a 0.02 deadband, booted flag so the first frame does not trigger); beat flare: newest ink brightens 12% on exp(-beatage*5). + +Work Log: +- src/lib/ava/embedded-presets.ts: twelfth Zai-Magic preset "Beautiful Spectrogram" appended (KEEP VERBATIM section); EMBEDDED_SEED_VERSION 7.14 -> 7.18.1 (bumped twice: 7.18 added the preset, 7.18.1 replaced the first cut's flawed ink math -- the fingerprint gate only re-seeds on version change since folder+name were unchanged); file header + Zai-Magic section comments updated (eleven -> twelve). +- src/lib/version.ts: APP_VERSION 7.18.0 + history entry (the full ink-math derivation). src/lib/release-notes.ts: 7.18.0 "Beautiful Spectrogram" (added + improved, first person, no em dashes). +- db/custom.db.seed re-synced after the library re-seed (107 presets incl. the new row, verified by direct SQLite read). + +BROWSER E2E (agent-browser, ALL PASS): +- Parse/compile: validateScript clean (lines/additive/persist 1); 64 points, megabuf palette + bins; offline simulation of [init]/[frame]/[point] across 10 scenarios (erase, wash t=1/2/3, steady 60/120/10fps, portrait, ultrawide, wash-at-10fps) -- every case ink 0.21-0.37, per-coat red add 1.9-3.4 LSB, accumulation 1.1x palette. +- Library: /api/presets re-seeded on both version bumps; Zai-Magic serves 12 presets with Beautiful Spectrogram sorted between Aurora Veil and Bass Bloom; tree double-click loads it (footer SCRIPT: Beautiful Spectrogram, PTS: 64). +- Canvas pixels (quiet passage): background rgb(5,13,54) = deep dark navy (palette anchor 10,15,59); palette census pink 5.2% / red 9.8% / orange 5.0% / yellow 3.5% / white 2.0% / green 0.00% / cyan 0.01% -- the first cut's cyan plague measured 23.5% white + green fields, now gone. +- Scroll: engine bgx verified independently with a burst probe (bgx -0.01 -> 216px/s measured vs 209 predicted); the spectrogram measured per-frame via high-pass Pearson cross-correlation -- steady state 0.483px/frame vs 0.526 design (8%, beat-stripe noise), warm-up ramp 1.82px/frame at warm~5.5 as designed; direction LEFT (r up to 0.997). +- VLM screenshot review (desktop, loud passage): "coherent scrolling spectrogram, sensible frequency-vs-time structure", ramp deep red -> orange -> golden yellow -> near-white, "no green or cyan anywhere"; portrait 420x800 renders at 60fps with the resize re-warm firing (harmonic stripe structure is real 64-bin resolution, not an artifact). +- App: title "OVE -- Open Visualization Engine (v7.18.0)"; What's New dialog leads with 7.18.0 "Beautiful Spectrogram"; console 0 errors / 0 warnings; bun run lint clean; dev.log 200s only. + +Stage Summary: +- v7.18.0 shipped: "Beautiful Spectrogram", the twelfth hand-authored Zai-Magic preset -- a true scrolling spectrogram as a pure script (bgx slide + persist 1 zero-fade + megabuf bin memory + palette table), with the per-frame ink computed from live stroke geometry so the accumulation lands on the palette at any fps/aspect/brush width. Browser-verified end to end: navy field, pink-to-white print, leftward crawl at design rate, no channel contamination, clean console.