This release includes breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
ReleasePort's take
Light signalNewamp v1.5.3 adds Audio DNA Engine (11 perceptual vectors/track) with Sounds Like discovery, Living Tags automation, Bit-Perfect audio path, and Library Radio Brain HTTP server.
Why it matters: Audio DNA enables new Sounds Like and Living Tags discovery features. HTTP server provides programmatic library access; test endpoints in dev and plan production deployment.
Summary
AI summaryBroad release touches Deferred, Added — Bit-Perfect Path, Fixed — Wikipedia integration, and Added — Sounds Like.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Feature | Medium |
Added Sonic Atlas (new this release) for per-track Audio DNA projection and interaction. Added Sonic Atlas (new this release) for per-track Audio DNA projection and interaction. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added Bit-Perfect Path audio chain with sample rate selection and indicator. Added Bit-Perfect Path audio chain with sample rate selection and indicator. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added Audio DNA Engine extracting eleven perceptual feature vectors per track. Added Audio DNA Engine extracting eleven perceptual feature vectors per track. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added Living Tags DSL for user-authored derived tags with sandboxed evaluation. Added Living Tags DSL for user-authored derived tags with sandboxed evaluation. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added Sounds Like panel ranking tracks by cosine similarity over DNA vectors. Added Sounds Like panel ranking tracks by cosine similarity over DNA vectors. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added Spectral Cover Art procedural SVG fallback for albums without art. Added Spectral Cover Art procedural SVG fallback for albums without art. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added Library Radio Brain HTTP server exposing library streams and audio endpoints. Added Library Radio Brain HTTP server exposing library streams and audio endpoints. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Reorganized sidebar into six labeled groups with bordered Tools footer. Reorganized sidebar into six labeled groups with bordered Tools footer. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added native getDiscoverSurface API for deterministic local-first Living Library missions. Added native getDiscoverSurface API for deterministic local-first Living Library missions. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Introduced four UI shells (Retro, Modern, Liquid Glass, Concourse) selectable in Settings. Introduced four UI shells (Retro, Modern, Liquid Glass, Concourse) selectable in Settings. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added four compact deck skins (Bento, Record Player, Jukebox, Cassette Deck) with native window sizes. Added four compact deck skins (Bento, Record Player, Jukebox, Cassette Deck) with native window sizes. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Implemented 0–100 decimal track scoring alongside legacy rating system. Implemented 0–100 decimal track scoring alongside legacy rating system. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added master volume slider extending to 200% with limiter before gain. Added master volume slider extending to 200% with limiter before gain. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Introduced Home magazine layout with hero, rated highlight rail, news card, and listening stats. Introduced Home magazine layout with hero, rated highlight rail, news card, and listening stats. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Added draggable spectrum/side split in Now Playing side-panel with persistence. Added draggable spectrum/side split in Now Playing side-panel with persistence. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Feature | Medium |
Implemented first-run UX improvements including Empty Library hero and command palette tip toast. Implemented first-run UX improvements including Empty Library hero and command palette tip toast. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Performance | Medium |
Applied content-visibility:auto on long catalog rows to skip offscreen layout/paint. Applied content-visibility:auto on long catalog rows to skip offscreen layout/paint. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
| Performance | Medium |
Lazy-loaded album art in Home with reserved aspect ratios to prevent layout reflow. Lazy-loaded album art in Home with reserved aspect ratios to prevent layout reflow. Source: granite4.1:8b-q6_K@2026-05-21 Confidence: high |
— |
Full changelog
Changelog
All notable changes to NewAmp will be documented here.
This project adheres to Semantic Versioning.
[1.5.3] - 2026-05-20
Bug-fix and review-followup pass. Six review-flagged blockers, nine high-priority issues, and ten nice-to-haves resolved, plus durable regression smokes for the algorithmic surfaces (seed-vibe similarity, Sonic Atlas region playback, random album sort).
Fixed — Volume past 100% no longer clips the limiter
- The audio graph was source → eq → replayGain → masterGain (volume) → limiter → destination, so anything above 1.0× volume amplified the post-limiter signal and pushed the device into clipping. Volume now lives upstream of the limiter and the analyser tap is parallel to the master/limiter chain, so the visualizer stays reactive even at silent volume.
Fixed — DNA cosine similarity returned [0.5, 1] instead of [0, 1]
dnaCosineSimilaritywas remapping cos via(cos + 1) / 2, which made sense only if vectors could be anti-aligned. Audio DNA vectors are non-negative, so cos already sits in [0, 1]; the remap collapsed the seed-vibe gate's discriminative power into a flat half-range.
Fixed — Random album sort crashed every call
albumSortOrder('random', …)emittedMIN(id) ^ xorMask, but SQLite has no^operator. Every shuffle, every Random sort, every random-album quick-pick was an SQL parse error since 1.5.2. Replaced with a bounded three-term polynomial seeded by Knuth multiplicative hashing.normalizeAlbumRandomSeedclamped any seed above 2^31-1 to the same ceiling, so consecutiveDate.now()values collapsed to a single normalized seed and the "random" sort was deterministic across the session. Replaced clamp with modulo so the low 31 bits of entropy survive.
Fixed — Sonic Atlas crashed when empty
- AtlasView dereferenced
atlas.points[…]before the projection finished. Now falls back to no-center when the atlas is empty.
Fixed — Close-button behavior reset on settings patch
- A
closeButtonBehavior: undefinedpatch (sent by every other settings save) overwrote the user's preference back to the default. Now preserves the stored value when the patch field is missing.
Fixed — useEffect shadowed window.performance
- The fullscreen visualizer's local state variable named
performanceshadowedwindow.performancein some closures and broke frame-rate measurement on cold boot. Renamed toperfTier.
Fixed — Long-session float drift on visualizer accumulators
radialRotation,tunnelTwist,orbitalRotation, andmercuryHueDriftaccumulated monotonically and lost trig precision after roughly thirty minutes. Wrapped with explicit modulo.
Improved — Audio analyzer sample-rate awareness
- Kick-band, bass, low-mid, mid, and treble bins are now derived from sample rate plus FFT size instead of hardcoded for 48 kHz. The visualizer now reads correct bands on 44.1 kHz devices.
- Dedicated unsmoothed
AnalyserNodefor kick onset detection so the smoothed analyser can keep its visual smoothing without lying about transients.
Improved — DNA index caching
LibraryStore.buildDnaIndexcached and invalidated on writes. Harmonic and taste mix calls used to re-parse the entire DNA table per invocation.
Improved — Seed-vibe scoring hoisted out of the per-candidate loop
createSeedVibeContextprecomputes genre tokens, normalized artist/album, and the seed-side DNA snapshot once per mix call instead of per candidate.
Improved — Wikipedia client extracted to a shared helper
src/lib/wiki.tsnow owns the user-agent, response shape, and search/lookup helpers. Artist and album fact paths share the implementation and surface non-OK responses viaconsole.warninstead of silently failing.
Tests
- New:
scripts/seed-vibe-smoke.mjscovers identical DNA, genre+era branch, same-artist floor, all-null inputs, BPM half/double match, and theapplySeedVibeGateformula. - New:
scripts/album-random-sort-smoke.mjsreproduces the^parse failure, asserts close seeds decorrelate, and stresses int64 bounds at MIN(id) ≈ 2^30. - Tightened:
scripts/sonic-atlas-smoke.mjsnow assertsnearestAtlasPointsclamp bounds, monotonic distance ordering, and floor behavior. - Tightened:
scripts/ui-visualizer-smoke.mjsrequires a positivemilkdropMounteddata attribute (set afterbutterchurn.createVisualizersucceeds) instead of only checking the absence of an eval error.
Deferred
- Butterchurn CSP iframe sandbox. Splitting the audio graph across an iframe boundary is the right fix but breaks the live analyser path. Tracked in
docs/butterchurn-csp-iframe-plan.md.
[1.5.2] - 2026-05-20
Production-readiness pass. A long autonomous run resolving real-world bug reports plus a complete visualizer reactivity overhaul, deck art improvements, smarter Mixes, and in-app navigation from Now Playing.
Added — Liquid Mercury visualizer (new preset)
- Twelve metaball blobs that each couple to a distinct frequency band. Beat-driven attractor flips collapse and explode the cluster on every kick; bass drives a slow palette wheel rotation so the whole field cycles color with the music.
- Connection lines fuse between overlapping blobs for a true metaball look without per-pixel sampling cost. Center caustic flare on each kick gives the bass a physical compression effect.
- Available in fullscreen preset list and Auto VJ rotation.
Added — In-app navigation from Now Playing
- Clicking the artist name in Now Playing now jumps to the Artists view filtered to that artist (instead of opening a Wikipedia search).
- Clicking the album name jumps to the Albums view with that album pre-selected.
- External Wikipedia search moved behind a small ↗ icon next to each name.
- Backed by a
pendingNavigationaction on the player store consumed by AlbumsView/ArtistsView on next render.
Added — Sonic Atlas region playback
- Click any atlas point to pin it (warn-colored halo + crosshair stays put through panning).
- New footer: pick 6/12/24/48 nearest tracks, then PLAY REGION / QUEUE NEXT. The cluster is hydrated via the new bulk
getTracksByIdsIPC, preserving atlas-neighborhood order so the result reads as a smooth journey through sound space. - Hover overlay now shows album + year + genre alongside the DNA breakdown.
Added — Living Tags in Now Playing
- The "NewAmp Notes" filler is replaced with a Living Tags chip panel that shows every DSL-derived tag currently assigned to the playing track. Empty-state hint points the user at the Living Tags view to write their first rule.
Added — First-visit onboarding cards
- Discover, Mixes, Living Tags, and Sonic Atlas each show an inline explainer card on first visit. Dismissed state persists per view via
localStorage. The cards explain what each surface does, what to expect, and where to click next.
Added — Spectral-art fallback in the transport bar
- Bottom transport bar falls back to a deterministic SVG cover (FNV-1a hashed from artist+album) whenever the embedded art URL 404s. No more music-note placeholder for tagless tracks; every track in the library gets a distinct visual identity.
Added — Visualizer auto-hide top nav + working volume slider
- Cursor near the top edge (≤110 px) reveals the toolbar; moving away hides it after 1.4 s. Keyboard shortcuts also reveal briefly. Fullscreen no longer feels cluttered.
- Right-side volume meter is now a real volume slider (native
appearance: slider-vertical+writing-mode: vertical-lr). Drag or scroll to set volume. The animated RMS fill bar remains visible behind the input.
Added — Deck art pan + TV static
- Jukebox + Retro TV decks now slowly pan the album cover up→center→down on a 14 s loop instead of showing a static crop. Honors
prefers-reduced-motion. - Retro TV deck overlays animated SVG snow noise that intensifies when no track is tuned in, becomes subtle film grain during playback.
Changed — Mixes seed coherence
- Both Harmonic Mix and Taste Match now gate candidate tracks by audio DNA cosine + genre Jaccard + era proximity + artist match before scoring. A Lykke Li track no longer shows up in a mix seeded from Everclear ('90s alt-rock) just because it's heavily played; seed-vibe similarity becomes a multiplicative gate on top of the existing taste score.
- New
shared/seed-vibe.tsexportsseedVibeSimilarity(track, seed, ...)returning 0–1.
Changed — Visualizer reactivity overhaul
- Beat decay tightened from
0.76to0.5so kicks read as discrete events instead of one smeared envelope. Fixes Tempo Pulse lag. - New
kick,beatEdge, andfluxfeatures onAudioFeatures.kickis unsmoothed narrow-band (0–140 Hz) energy.beatEdgeis true exactly on the frame a transient fires.fluxis positive-only spectral delta. - Galaxy: hue now coupled to
bass + beat + time; bass ring color cycles instead of staying accent-colored. Beat edges trigger a 14-particle burst. - Radial: beat-driven rotation accumulator; consumes
features.bands[i]per spoke; maxR pumps with beat. - Tunnel: accumulator twist (silent → frozen, kick → accelerate); polygon side count modulates with beat; per-ring radius scales with bass + beat.
- Orbital Rings: outer-bar count cut from
96+ring*18to48+ring*10. The expensiveshadowBluris now gated onfeatures.beat > 0.42— only fires during transients. Rotation derives fromorbitalRotationaccumulator. - Tempo Pulse: rising-edge trigger via
features.beatEdge; debounce drops from 110 ms to 70 ms. - Confetti: alpha + size pulse on beat; angle accelerates with beat; hue shifts on edges.
- Burning Cloud (shader): swapped hardcoded red→orange→amber ramp for palette()-driven hues so the cloud actually cycles color with the music. Palette mix factor raised from 0.16 to 0.55+bass*0.4.
- Plasma Grid (shader): tile frequency cut from 10–20× to 3–5× per axis so we see flowing plasma cells instead of "a wall of tiny windows". Plasma now dominates over the grid lines.
- Neon Ribbons (shader): replaced raw
atan(p.y, p.x)with periodiccos(theta*n)— eliminates the broken seam along the negative x-axis.
Fixed — Wikipedia integration (Blood Orange + similar artists)
- Added
Api-User-Agentheader per Wikipedia's UA policy; anonymous browser UAs were getting throttled which made lookups silently fail. MUSIC_DISAMBIGUATORSextended withmusical project,music producer,producer,artistso artist aliases (Blood Orange = Devonté Hynes) resolve directly toPage (musical project)etc.- Album panel in Now Playing falls back to the artist's Wikipedia entry when no album-specific page exists, with a "showing the artist instead" note. No more empty panel for off-catalog releases.
- Fetch errors no longer kill the candidate chain — failure on one disambiguator continues to the next.
Fixed — Album rating overlapping Play Album buttons
- Album rating widget was rendering wider than its 230 px container and crashing into the action buttons row. Now lives on a dedicated full-width row beneath the action buttons, no overlap at any viewport.
Fixed — Rating a song no longer "rates the album"
- Album Context panel in Now Playing was showing an averageScore that updated whenever the user rated a single song, making it look like the album received a rating. Now only displays the average when 3+ tracks (or ≥50%) of the album are actually rated; otherwise shows
(N of M tracks rated)to make it clear it's an aggregate.
Fixed — Random album reshuffle producing identical orderings
- The polynomial random sort could occasionally hit near-identical orderings when two Date.now() seeds shared the same
% 991or% 7919residue. New formula XORsMIN(id)against the seed before the polynomial mix so tiny seed deltas always produce visibly distinct orders.
Fixed — Vintage Computer (terminal) theme legibility
- Ink, ink-2, muted darkened to pass AA contrast against the
#c4c1aabeige panel. Accent, accent-dim, warn, and error similarly darkened. The whole theme now reads cleanly instead of fading into the background.
Fixed — Milkdrop (Butterchurn) visualizer actually renders
- Root cause:
script-src 'self'in the renderer CSP blocked butterchurn-presets from compiling preset shader math via the Function constructor (used by butterchurn at preset load). The catch instartButterchurnfell back to the placeholder fallback without surfacing the EvalError. Added'unsafe-eval'to script-src — the compiled code only comes from the locally-bundled butterchurn-presets package (connect-src still restricts what can be fetched). electron/settings.ts.normalizeVisualizerPresetwhitelist now includesliquid-mercuryso the new preset persists across sessions instead of silently reverting to default.ui-visualizer-smokeextended end-to-end: clicks the Milkdrop button, waits for canvas mount, asserts no CSP/eval errors fire. Also covers Liquid Mercury with full pixel-output validation.- Probe timeout extended from 20s to 60s to fit the new battery + butterchurn shader compilation time.
Fixed — Engine tick re-rendering NowPlayingView 60× per second
- The audio engine's RAF tick was notifying state listeners on every frame. Each
notify()fired re-renders of every Zustand-subscribed component including the 1900-line NowPlayingView. Throttled to 10Hz integer buckets — seek + duration changes still fire immediately — for a 6× cut in per-second React work. Largest contributor to the "gets heavier after an hour" report.
Fixed — Folders view capped at 7 visible folders
- The
grid-rows-[minmax(180px,0.42fr)_minmax(0,1fr)]layout kept the folder list at most 42% of available height even when no folder was selected. Now the layout adapts: full height for the folder list when nothing is selected (~25 folders on an 800px window), split layout when a folder IS opened so tracks have room.
Community feedback round
- Sidebar scrolls when the window is too short to show all nav + tools (outer
<aside>now owns the scroll; inner nav drops its own overflow for a single unified scrollbar). - New
closeButtonBehaviorsetting in Settings > Shell/Layout: choose between minimize-to-tray (default) or close-the-app for the X button. - Albums view (artist sort) gets a vertical A-Z letter rail on the right edge for quick jump-to-letter scrolling. Letters with no matching artist render dimmed. Skips leading articles so "The Beatles" jumps to B.
[1.5.1] - 2026-05-19
Removed
- Hotdog Deck skin and assets. The compact-deck registry, CompactPlayer case, CSS block, mask + shell PNGs, and ui-deck/skin/discover smoke entries all gone. The shape-changing decks lineup is now Windowshade, Winamp Classic + Industrial, Record Player, Jukebox, Cassette, Discman, Retro TV.
[1.5.0] - 2026-05-19
Living Library — a content-aware, programmable upgrade to the library.
This release adds six new surfaces (Audio DNA, Sounds Like, Living Tags DSL + workshop, Sonic Atlas, Library Radio Brain, Spectral Cover Art) plus a Bit-Perfect Path through the audio chain and a sidebar redesign. Performance regression smoke detects 5× drops on a synthetic 60 000-track library; current numbers are 5–12× under budget.
Added — Sonic Atlas (new this release)
- 2D projection of the library's per-track Audio DNA via zero-deps PCA (power iteration + Hotelling deflation, deterministic across runs). Pan, zoom, click to play, Shift-click to queue next. Hover for the DNA breakdown.
- Axis hints surface the dominant DNA dimensions per axis ("+brightness & +rolloff" / "+rms & +dynRng") so the user can read what the axes actually mean.
atlasPointColorkeys an HSL palette on brightness (hue) + dynamic range (saturation) + low-band energy (lightness) so adjacent dots read as adjacent colors at a glance.- Smoke
smoke:sonic-atlassynthesizes three sonic clusters, asserts each cluster's centroid stays > 0.15 apart in the projection, verifies determinism, hit-testing, axis hints, and color formatting.
Added — Bit-Perfect Path (new this release)
AppSettings.audioBitPerfectPath+audioPreferredSampleRate(44.1 / 48 / 88.2 / 96 / 176.4 / 192 / 352.8 / 384 kHz). When enabled, the Web Audio AudioContext is created at the preferred rate so Chromium's resampler is a pass-through on matching sources.AudioEngine.setPreferredSampleRatehonors the setting at next AudioContext boot; falls back to the device default if Chromium rejects the rate.- Settings → Audio gains a Bit-Perfect row: toggle, rate picker, live "Live AudioContext rate" indicator showing whether the requested rate is actually active, and a collapsible setup guide that documents WASAPI Exclusive on Windows + ALSA
hw:/ PipeWire bit-perfect on Linux. - Honest copy: true kernel streaming (WASAPI Exclusive, ASIO, ALSA
hw:direct) requires a native PortAudio addon — tracked as Phase 2.
Added — Audio DNA Engine
- Per-track perceptual feature vectors extracted via ffmpeg → 22 050 Hz mono PCM → hand-rolled FFT. Eleven dimensions per track: RMS, dynamic range, spectral centroid (brightness), spectral flatness, 85th-percentile rolloff, onset density, and five normalized band energies (low → high).
tracks.dna_json+dna_analyzed_atcolumns persist the vectors.setTrackDna/getTrackDna/getTrackIdsMissingDna/getAllTrackDna/getDnaStatsround-trip them.- Background batch analysis runs three concurrent ffmpeg workers so library-wide DNA fills 2.5× faster on multi-core machines without contending with active playback.
- Smoke
smoke:dnacovers pure-math determinism, FFmpeg-driven analyzer round-trip on real FLAC fixtures, persistence, similarity math, and source-link assertions across the IPC, preload, types, and renderer surface.
Added — Living Tags DSL (the moonshot)
Added — Audio DNA Engine
- Per-track perceptual feature vectors extracted via ffmpeg → 22 050 Hz mono PCM → hand-rolled FFT. Eleven dimensions per track: RMS, dynamic range, spectral centroid (brightness), spectral flatness, 85th-percentile rolloff, onset density, and five normalized band energies (low → high).
tracks.dna_json+dna_analyzed_atcolumns persist the vectors.setTrackDna/getTrackDna/getTrackIdsMissingDna/getAllTrackDna/getDnaStatsround-trip them.- Smoke
smoke:dnacovers pure-math determinism, FFmpeg-driven analyzer round-trip on real FLAC fixtures, persistence, similarity math, and source-link assertions across the IPC, preload, types, and renderer surface.
Added — Living Tags DSL (moonshot)
- A tiny embedded expression language for user-authored derived tags. Tags are named expressions over track metadata, audio DNA, listening behavior, and time context. Editing a rule retroactively re-tags every track in the library.
- Grammar:
tag(name) when <expr> [boost N]. Operators:and / or / not,== != < <= > >=,matches,contains,in, ranges (90..120), arithmetic. Identifiers:track.*+dna.*plus bareword shortcuts. Functions:weekday() / hour() / month() / season() / now() / daysSince(),matches,contains,lower / upper / length,abs / min / max,tag(other)for composition. - Sandboxed eval: hand-rolled AST walker, whitelisted function table guarded by
hasOwnPropertyso the prototype chain is unreachable. Three-valued null logic: missing fields fail comparisons rather than poisoning the boolean. Topological-sort cycle detection rejects circular tag references at definition time. Tag names locked to[a-z_][a-z0-9_-]*, ≤48 chars; rule bodies ≤4 000 chars. - New tables
tag_rules(definition + boost + enabled +last_error) andtrack_tags(materialized with cascade on track deletion). Library power-search gainstag:<name>anduntagged:true. saveTagRule/deleteTagRule/setTagRuleEnabled/recomputeTags/previewTagRule/getTagsForTrack/getTagSummaries/getTrackIdsByTag. Saving or toggling a rule auto-recomputes.- Living Tags workshop view (
/tagsin the sidebar): three-column UI — rule list, expression editor with boost slider and inline parse-error caret, live preview pane that runs the candidate rule against a 2 000-track sample on every keystroke (350 ms debounce). One-click Play sample, recompute-all action, tag-summary chip strip. - Smoke
smoke:tags: parser correctness, sandbox escape attempts (constructor("alert(1)"),__proto__lookup, chainedf()()), three-valued null behaviour, range filters, composition + cycle detection, and end-to-end persistence including disabled-rule cleanup.
Added — Sounds Like
findSimilarTracks(trackId, limit)ranks the library by cosine similarity over DNA vectors and returns hydrated tracks with their score.- Now Playing gains a Sounds Like panel under the Signal Bay. If the track has no DNA, the panel offers an inline "Analyze DNA" button that calls
analyzeTracksDna([id])and reloads. Otherwise the top five matches show with cosine percentages and a "Play set" action that queues the full result.
Added — Spectral Cover Art
- Deterministic procedural SVG cover for albums without embedded or sidecar art. Seeded by FNV-1a hash of
artist::albumso the same library renders the same artwork across launches. - Three-stop OKLCH-ish gradient over a 14-bar spectrogram-style figure with offset accent circles. Lower band stamps
ARTIST + ALBUMin monospace small caps (HTML escaped). Wired intoAlbumArtandFolderArtas the no-real-art fallback. - Reference gallery captured at
assets/screenshots/spectral-art-gallery.png. - Smoke
smoke:spectral-art: byte-stable output, palette diversity, valid SVG structure, data-URL round-trip, edge cases.
Added — Library Radio Brain
- Toggleable HTTP server (
Settings → Library Radio Brain) that turns NewAmp into a tunable station on the local network. Default port17117, configurable (1024–65535). - Endpoints:
GET /(HTML status page),GET /library.m3u,GET /random.m3u(200 shuffled tracks per fetch),GET /tag/<name>.m3u(Living-Tag stream),GET /audio/<trackId>(raw audio for native formats; WAV-via-ffmpeg transcode for legacy codecs, reusing the engine's transcoder). - Aborts on client disconnect propagate to the underlying ffmpeg process.
syncRadioBrainreacts tosettings:setso flipping the toggle starts / stops / rebinds the server automatically and the renderer status row pollsgetRadioBrainStatusevery 4 s. - Smoke
smoke:radio-brain: validates endpoint surface, M3U content, audio Content-Type, 405-on-POST, 404 paths, and clean shutdown.
Changed
- Library power-search grammar gains
taganduntaggedfield tokens. AlbumArtandFolderArtno longer show a single♫placeholder when art is missing — every album/folder gets a unique spectral cover instead.- Sidebar nav reorganised from a 17-item flat list into six labeled groups (Main / Explore / Discovery / Yours / Streaming / App) with a bordered Tools footer that anchors EQ / VIZ / DECK + the keyboard chip cheat sheet. Row padding compressed so all groups fit a 900 px window without scroll.
- Logo: shipped raster + ICO + new SVG vector wrapper rebuilt from a clean alpha pipeline — no more transparent-hair / ghost-eyes on light GitHub-mobile pages.
- README screenshot grid swapped to higher-density contributed captures with section headers; added a Shape-changing decks row (Record Player / Jukebox / Hotdog / Windowshade) and a Reactive tagging row (Living Tags / Sonic Atlas).
Performance
recomputeTagsandpreviewTagRulebuild a single in-memory DNA index viabuildDnaIndex()instead of running one SQLite query per track.bulkInsertTrackTagsbatches the result writes 500 pairs per multi-row INSERT. Result: full library re-tag on 60 000 tracks × 2 rules drops from ~3.9 s projected to 743 ms measured.- Spectral SVG renderer gets a bounded LRU memo (512 entries) for both SVG strings and data URLs. Scrolling album grids no longer rebuild every cover on every React re-render.
analyzeTracksDnaruns a three-worker pool over the input ids; ffmpeg-bound decode parallelises ~2.5× on multi-core machines.- New
smoke:perf-bench: synthetic 60 000-track regression detector that asserts every hot path under per-step budgets and prints the live headroom ratio (current run lands at 5–12× under budget).
Fixed
- Reverted accidental ASCII downgrades of UI glyphs in
RecordPlayerDeck(brand dot, close, play/pause/stop, vinyl-label fallbacks) andformatDuration's em-dash. Kept the tonearm-angle correction. profileForinshared/archive-compass.tsno longer reportsLossless Libraryfor an empty library; it returnsEmpty Shelfso Home's grade tile matches the headline.- Two unprefixed debug
console.loglines in theos:pick-folderIPC handler that printed dialog results on every folder pick. - Living Tags DSL ReDoS hardening:
matchesandmatches()route throughsafeRegexTestthat pre-screens for nested-quantifier and alternation-of-equivalents patterns; input is sliced to 4 096 chars. Without the screener,title matches "(a+)+b"on 28 'a's locked the recompute thread for 17 s — that's library-wide pause. - Living Tags DSL parser depth guard (
>256nested parens rejected with a clean compile error) and boost-product cap (1e6) so a careless rule pack can't drift the running shuffle-bag weight toward Infinity. - Living Tags DSL
daysSince()was unreachable from user rules because the function-table key was mixedCase while the dispatcher lowercases the lookup. Caught by review pass; smoke now asserts the regression. saveTagRulenow runstopologicalSortacross the full enabled rule set before writing, so cross-rule cycles (tag(a) when tag(b)+tag(b) when tag(a)) are rejected at save with a clear "would form a cycle" message instead of silently zeroing out the recompute.- Radio Brain's
respondAudiodestroys the socket when an error fires after headers are sent so a mid-stream error can't chimera audio bytes with error text. M3U#EXTINFlines strip\r\nfrom artist/title so a malformed tag can't inject playlist entries. - TagsView preview pane race condition: each keystroke now carries a sequence number; slow responses to old keystrokes are discarded when a newer edit has already queried.
[Unreleased]
[1.2.0] - 2026-05-17
Living Library release.
Added
- Added Discover, a local-first Living Library view that builds playable crate-digging missions from fresh imports, forgotten favorites, deep album candidates, underplayed corners, and visual-night sets.
- Added a native
getDiscoverSurfaceAPI with deterministic seeds, low-end visual preset safety, deck/visualizer plans, and saveable mission payloads. - Added Discover navigation in the sidebar and command palette.
- Added
smoke:discoverandsmoke:ui-discover, and wired both into the release gate.
Changed
- Broadened README coverage for Discover, current deck skins, release artifact names, architecture, and smoke-test count.
[1.1.1] - 2026-05-17
Release polish for the first broader test build.
Fixed
- Restored the compact deck sizing path and tightened the Winamp-style deck to a locked 550x232 shell with in-deck skin switching still accessible.
- Hardened artist facts so ambiguous names resolve to musicians, bands, singers, composers, or record producers instead of species or unrelated pages.
- Regenerated package naming around NewAmp casing for the app, installer, portable build, file associations, release bundle, and publication helper.
Added
- Added theme-colored logo rendering, longer startup logo animation, an About screen, user text scaling, Now Playing spectrum styles, and an Album context panel.
[1.1.0] — 2026-05-16
First public release. Major feature drop across UI shells, deck skins, scoring,
audiophile audio chain, and home experience.
Added — Shells (chrome / layout)
- Four UI shells selectable from Settings → Shell · Layout, independent of color skin:
- Retro — Bloomberg-density Winamp 2 homage (default)
- Modern — rounded panels, soft shadows, pill buttons
- Liquid Glass — translucent stacked panes with
backdrop-filter: blur(28px),
triple-radial OKLCH backdrop, SVG noise overlay, frosted sidebar + transport - Concourse — zero-radius operator-console split-cells with
CELLlabels
on tagged sections
- Shell selection persists via
localStorageand is reflected via
data-shellon<html>so CSS can re-skin chrome without React knowing.
Added — Deck (compact-window) skins
- Four deck skins with native window sizes — no letterbox borders:
- Bento — the original 720×168 horizontal deck
- Record Player — 540×540, spinning vinyl with the album-art label,
tonearm swings with playback progress - Jukebox — 420×560 Wurlitzer-style arch with animated bubble tubes,
chrome selection numerals fallback for tracks without trackNo - Cassette Deck — 760×320 with twin rotating reels, TYPE-IV embossed
strip, frosted front-load door, reels rotate only whenisPlaying
- IPC
win:set-compact-sizesizes the OS window to each deck's native aspect. - Deck → full-window transition now restores the maximized state correctly
even when DECK mode was entered from a maximized window. - DeckSkinPicker overlay lets you switch deck shape from inside any deck.
Added — Rating
- 0–100 decimal track scoring via new
tracks.rating_score REALcolumn
alongside the legacyrating INTEGER (0–5). Stars stay in sync
(round(score / 20)) so existing sorts and smart rules keep working. ScoreRatingwidget — drag/click to scrub, scroll-wheel ±0.1
(Shift = ±1.0), arrow keys (Alt = ±10), double-click to type an exact
score, right-click to clear. Tier label updates fromskipto
desert island.
Added — Volume / audio
- Master volume slider extends to 200% with a red-zone past unity, just
like VLC. EnginesetVolumeclamps to[0, 2]. Limiter sits before the
master gain so the boost amplifies without clipping.0 dBand+6 dB
tick labels render under the slider in addition to percentage readout. - Settings → Audio shows a live "Output engine" readout: AudioContext
sample rate + bit depth, styled like a hi-fi component panel. - ReplayGain status pill in the Now Playing header strip when active.
Added — Home (magazine layout)
HomeHerowith greeting, blurred album-art backdrop, library counts,
current track + progress bar, transport buttons, and Today's Pick
card with a reason chip (smart-pick logic: high-rated, never played OR
not played in 30+ days, not currently playing; falls back to top rated).RatedHighlightRail— 8 album-art cards sorted by rating score, with
decimal score badges.NewsCard- compact field report for the most recent import.ListeningStatsThisWeek— total minutes, distinct artists, top genre.- Fresh Imports rail subtitle shows the date of the newest file
mtime.
Added — Now Playing
- Side-panel tab strip: On Air (default - Liner Notes / sonic vitals / lyric hot lines / file credits), Album
(Tempo Trainer / Practice Loop / Track Bookmarks musician tools),
Lyrics. - Draggable spectrum/side split with
localStoragepersistence
(newamp:np:spectrumFrac).
Added — First-run UX
- Rebuilt Empty Library view as an inviting hero (themed logo + headline +
one-CTA folder scan) instead of a text-heavy onboarding wall. FirstRunHintsshows a one-timeCtrl+Kcommand palette tip toast on
first launch (tracked vialocalStorage).
Added — Other
- Music field-report copy delivered in-product without requiring a network account.
- Score-aware sort and
data.ratedrail inHomeView.
Performance
content-visibility: autoon long catalog rows (.newamp-library-row,
.newamp-albums-row, etc.) — the browser skips offscreen layout/paint
entirely. Single biggest scroll-frame improvement on 60k-track libraries.- Lazy-load album art in Home with reserved aspect ratios to prevent
layout reflow.
Build / release
appIdneutralized toio.newamp.player.package.jsonrepository/homepage/bugsfields set so
electron-builder can compute publish info without warnings.- Logo asset moved from repo root to
build/logo.png(the root*.png
glob in.gitignorewas hiding it from tracking). packagescript produces both NSIS installer and portable EXE,
signs them with signtool, writesSHA256SUMS.txt.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About Evilander/newamp
All releases →Related context
Related tools
Earlier breaking changes
- v1.5.7 IPC argument order standardized to (albumArtist, album) across all call sites
- v1.5.7 Breaking: IPC argument order aligned to (albumArtist, album) everywhere
- v1.5.7 Breaking: setAlbumRatingScore and getAlbumRating throw on missing input
- v1.5.6 Milkdrop broken on 1.5.4 and 1.5.5 builds; upgrade recommended.
- v1.5.5 Upgrade strongly recommended; version 1.5.4 cannot display albums.
Beta — feedback welcome: [email protected]