a132a822-8297-48ee-a813-68dcaf906c8b
This commit is contained in:
parent
a97d5a17ad
commit
9b76dcc208
49 changed files with 515 additions and 460 deletions
|
|
@ -1 +1 @@
|
|||
1107
|
||||
1198
|
||||
|
|
|
|||
BIN
db/custom.db
BIN
db/custom.db
Binary file not shown.
BIN
public/demo-track.mp3 → public/demo-tracks/demo-01.mp3
Executable file → Normal file
BIN
public/demo-track.mp3 → public/demo-tracks/demo-01.mp3
Executable file → Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-02.mp3
Normal file
BIN
public/demo-tracks/demo-02.mp3
Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-03.mp3
Normal file
BIN
public/demo-tracks/demo-03.mp3
Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-04.mp3
Normal file
BIN
public/demo-tracks/demo-04.mp3
Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-05.mp3
Normal file
BIN
public/demo-tracks/demo-05.mp3
Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-06.mp3
Normal file
BIN
public/demo-tracks/demo-06.mp3
Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-07.mp3
Normal file
BIN
public/demo-tracks/demo-07.mp3
Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-08.mp3
Normal file
BIN
public/demo-tracks/demo-08.mp3
Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-09.mp3
Normal file
BIN
public/demo-tracks/demo-09.mp3
Normal file
Binary file not shown.
BIN
public/demo-tracks/demo-10.mp3
Normal file
BIN
public/demo-tracks/demo-10.mp3
Normal file
Binary file not shown.
|
|
@ -636,7 +636,7 @@ function answerYtdlpFailure(
|
|||
if (result.code === 0) return null
|
||||
const cleanedStderr = stripControlChars(result.stderr).trim()
|
||||
if (UNSUPPORTED_RE.test(cleanedStderr)) {
|
||||
return fail(422, 'That site is not supported — try YouTube, SoundCloud, or a direct MP3 link.')
|
||||
return fail(422, 'That site is not supported -- try YouTube, SoundCloud, or a direct MP3 link.')
|
||||
}
|
||||
if (BOT_WALL_RE.test(cleanedStderr)) {
|
||||
// v6.8: code'd bot-wall answer — the client pairs it with an
|
||||
|
|
@ -802,7 +802,7 @@ export async function POST(request: NextRequest) {
|
|||
return fail(500, 'Could not stage the login cookie on the server.')
|
||||
}
|
||||
if (!cookie) {
|
||||
return fail(400, 'Could not read that cookie data — paste the Cookie header value or a cookies.txt export.')
|
||||
return fail(400, 'Could not read that cookie data -- paste the Cookie header value or a cookies.txt export.')
|
||||
}
|
||||
} else if (linkService !== null && houseText !== null) {
|
||||
try {
|
||||
|
|
@ -821,7 +821,7 @@ export async function POST(request: NextRequest) {
|
|||
try {
|
||||
held = await semaphore.acquire()
|
||||
if (!held) {
|
||||
return fail(503, 'The resolver is busy right now — try again in a moment.')
|
||||
return fail(503, 'The resolver is busy right now -- try again in a moment.')
|
||||
}
|
||||
const result = await runYtDlp(target.href, cookie ? ['--cookies', cookie.filePath] : [])
|
||||
// v7.5: shared classifier — same signatures, same answers as v6.8, now
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export async function GET() {
|
|||
const files = await collectFiles(root, zip, 'rust-agent')
|
||||
if (files === 0) {
|
||||
return NextResponse.json(
|
||||
{ error: 'rust-agent scaffold is empty — nothing to zip' },
|
||||
{ error: 'rust-agent scaffold is empty -- nothing to zip' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,17 +27,17 @@ const SITE_URL = "https://openvisengine.com";
|
|||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL(SITE_URL),
|
||||
title: `${APP_SHORT} — ${APP_NAME} (v${APP_VERSION})`,
|
||||
title: `${APP_SHORT} -- ${APP_NAME} (v${APP_VERSION})`,
|
||||
description:
|
||||
"Open Visualization Engine: audio-reactive visuals for clubs — 3-band spectrum detection, predictive beat tracking and AVS-style visualization scripting.",
|
||||
"Open Visualization Engine: audio-reactive visuals for clubs -- 3-band spectrum detection, predictive beat tracking and AVS-style visualization scripting.",
|
||||
keywords: ["OVE", "visualization", "VJ", "audio-reactive", "beat detection", "AVS", "Winamp"],
|
||||
openGraph: {
|
||||
type: "website",
|
||||
url: SITE_URL,
|
||||
siteName: APP_NAME,
|
||||
title: `${APP_SHORT} — ${APP_NAME}`,
|
||||
title: `${APP_SHORT} -- ${APP_NAME}`,
|
||||
description:
|
||||
"Audio-reactive visuals for clubs: link a track and OVE paints it — 3-band spectrum detection, predictive beat tracking and 95+ AVS-style presets.",
|
||||
"Audio-reactive visuals for clubs: link a track and OVE paints it -- 3-band spectrum detection, predictive beat tracking and 95+ AVS-style presets.",
|
||||
images: [
|
||||
{
|
||||
// ?v=2 cache-bust: Facebook caches og:image per-URL — when the image
|
||||
|
|
@ -47,15 +47,15 @@ export const metadata: Metadata = {
|
|||
url: "/og-image.jpg?v=2",
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: "Open Visualization Engine title card — gradient wordmark over spiral, particle and wireframe-sphere visualizations",
|
||||
alt: "Open Visualization Engine title card -- gradient wordmark over spiral, particle and wireframe-sphere visualizations",
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: `${APP_SHORT} — ${APP_NAME}`,
|
||||
title: `${APP_SHORT} -- ${APP_NAME}`,
|
||||
description:
|
||||
"Audio-reactive visuals for clubs: link a track and OVE paints it — spectrum detection, beat tracking, 95+ presets.",
|
||||
"Audio-reactive visuals for clubs: link a track and OVE paints it -- spectrum detection, beat tracking, 95+ presets.",
|
||||
images: ["/og-image.jpg?v=2"],
|
||||
},
|
||||
icons: {
|
||||
|
|
@ -91,7 +91,7 @@ export default function RootLayout({
|
|||
<script dangerouslySetInnerHTML={{ __html: themeBootScript }} />
|
||||
{/* class strategy: next-themes puts the base theme on <html>
|
||||
pre-paint. v7.2 default for new visitors: "outline" (Black +
|
||||
Purple Outline stage) — visitors who already picked a base have
|
||||
Purple Outline stage) -- visitors who already picked a base have
|
||||
it stored and never see this default; globals.css remaps the
|
||||
palettes per base + data-accent */}
|
||||
<ThemeProvider
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ export default function Home() {
|
|||
return (
|
||||
<div className="flex min-h-screen flex-col bg-zinc-950 text-zinc-100 lg:h-screen lg:overflow-hidden">
|
||||
<AppHeader />
|
||||
{/* playlist queue strip — only renders while a queue is active */}
|
||||
{/* playlist queue strip -- only renders while a queue is active */}
|
||||
<QueueBar />
|
||||
<main className="flex min-h-0 flex-1 flex-col gap-4 p-4 lg:flex-row">
|
||||
<VisualStage className="min-h-[45vh] lg:min-h-0 lg:flex-1" />
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { getEngine } from '@/lib/ava/engine'
|
|||
import type { TapResult } from '@/lib/ava/beat'
|
||||
import { validateScript } from '@/lib/ava/script'
|
||||
import type { ScriptError } from '@/lib/ava/script'
|
||||
import { DEMO_TRACK_COUNT, demoTrackTitle } from '@/lib/ava/audio'
|
||||
import { useAvaStore } from '@/lib/store'
|
||||
import { toast, useToast } from '@/hooks/use-toast'
|
||||
|
||||
|
|
@ -174,7 +175,7 @@ export async function resolveLink(
|
|||
): Promise<LinkResolveResult> {
|
||||
const trimmed = url.trim()
|
||||
if (!/^https?:\/\/\S+$/i.test(trimmed)) {
|
||||
return { ok: false, error: 'Paste a full http(s) link — e.g. https://www.youtube.com/watch?v=…' }
|
||||
return { ok: false, error: 'Paste a full http(s) link -- e.g. https://www.youtube.com/watch?v=…' }
|
||||
}
|
||||
|
||||
let data: ResolveResponse | null = null
|
||||
|
|
@ -194,7 +195,7 @@ export async function resolveLink(
|
|||
toast({
|
||||
title: 'Updating in Background',
|
||||
description:
|
||||
'YouTube changed how it serves audio — OVE is updating its audio engine on the server and will retry this song automatically.',
|
||||
'YouTube changed how it serves audio -- OVE is updating its audio engine on the server and will retry this song automatically.',
|
||||
})
|
||||
}
|
||||
await sleep(attempt === 0 ? UPDATING_FIRST_WAIT_MS : UPDATING_NEXT_WAIT_MS)
|
||||
|
|
@ -213,7 +214,7 @@ export async function resolveLink(
|
|||
if (sawUpdating && data?.ok) {
|
||||
toast({
|
||||
title: 'Audio engine updated',
|
||||
description: 'The server update finished — playing your song now.',
|
||||
description: 'The server update finished -- playing your song now.',
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -293,7 +294,7 @@ export async function resolveAndPlayLink(
|
|||
const result = await resolveLink(url, auth)
|
||||
if (!result.ok) return { ok: false, error: result.error }
|
||||
if (result.kind === 'playlist') {
|
||||
return { ok: false, error: 'That link is a playlist — load it to queue its tracks, then pick where to start.' }
|
||||
return { ok: false, error: 'That link is a playlist -- load it to queue its tracks, then pick where to start.' }
|
||||
}
|
||||
return playResolvedTrack(result, url)
|
||||
}
|
||||
|
|
@ -312,7 +313,7 @@ function micErrorMessage(err: unknown): string {
|
|||
function fileErrorMessage(err: unknown): string {
|
||||
const name = (err as DOMException | null)?.name ?? ''
|
||||
if (name === 'NotSupportedError') {
|
||||
return 'This browser cannot decode that file — try a WAV or MP3.'
|
||||
return 'This browser cannot decode that file -- try a WAV or MP3.'
|
||||
}
|
||||
return 'Could not play that audio file.'
|
||||
}
|
||||
|
|
@ -377,6 +378,34 @@ function retireDemoShowcase(): void {
|
|||
if (s.sequenceMode) s.setSequenceMode(false)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// v7.10 — the ten-track demo collection's place-keeper
|
||||
// ---------------------------------------------------------------------------
|
||||
// The visitor's place in the demo collection (which track the NEXT Demo
|
||||
// click plays) persists in localStorage, so returning later resumes where
|
||||
// they left off. The stored index advances when a pass truly ends — the
|
||||
// track played through ('ended') or the visitor clicked Stop ('stop') — and
|
||||
// wraps 10 → 1. Merely switching to another audio source keeps the place.
|
||||
|
||||
const DEMO_NEXT_KEY = 'ove.demoTrack.next'
|
||||
|
||||
function readDemoNext(): number {
|
||||
try {
|
||||
const v = Number.parseInt(localStorage.getItem(DEMO_NEXT_KEY) ?? '', 10)
|
||||
return Number.isInteger(v) && v >= 0 && v < DEMO_TRACK_COUNT ? v : 0
|
||||
} catch {
|
||||
return 0 // private mode -- the place lives for this visit only
|
||||
}
|
||||
}
|
||||
|
||||
function writeDemoNext(i: number): void {
|
||||
try {
|
||||
localStorage.setItem(DEMO_NEXT_KEY, String(((i % DEMO_TRACK_COUNT) + DEMO_TRACK_COUNT) % DEMO_TRACK_COUNT))
|
||||
} catch {
|
||||
/* private mode — see above */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Source lifecycle hook. Every method catches errors (mic permission, decode
|
||||
* failures) → destructive toast, and syncs the store with the engine's
|
||||
|
|
@ -396,15 +425,22 @@ export function useAudioSource() {
|
|||
const startDemo = useCallback(async () => {
|
||||
sourceRetireListener?.()
|
||||
const engine = getEngine()
|
||||
// v7.10: play the visitor's place in the ten-track collection (persisted
|
||||
// per visitor — filename order 1→10, wrapping back to track 1 after 10).
|
||||
const index = readDemoNext()
|
||||
try {
|
||||
await engine.audio.startDemo()
|
||||
// v7.3: single pass — when the track runs out (or is stopped, or
|
||||
await engine.audio.startDemo(index)
|
||||
// v7.3/v7.10: single pass — when the track runs out (or is stopped, or
|
||||
// replaced by another source) the engine fires onDemoEnded exactly
|
||||
// once: sync the store to idle (the landing overlay returns) and
|
||||
// uncheck the randomizer the showcase had checked.
|
||||
engine.audio.onDemoEnded = () => {
|
||||
// once, WITH the reason: sync the store to idle (the landing overlay
|
||||
// returns), uncheck the randomizer the showcase had checked, and —
|
||||
// when the pass truly ENDED (natural finish or the Stop button) —
|
||||
// advance the collection place so the next Demo click plays the next
|
||||
// track. A source switch keeps the visitor's place.
|
||||
engine.audio.onDemoEnded = (reason) => {
|
||||
syncSource()
|
||||
retireDemoShowcase()
|
||||
if (reason === 'ended' || reason === 'stop') writeDemoNext(index + 1)
|
||||
}
|
||||
syncSource()
|
||||
// showcase flow (v7.2/v7.4): nothing active → Bass Bloom, then the
|
||||
|
|
@ -414,8 +450,7 @@ export function useAudioSource() {
|
|||
startShowcaseMix()
|
||||
toast({
|
||||
title: 'Demo track playing',
|
||||
description:
|
||||
'Neural Mecha Pulse · Zai-Magic preset sequence — every preset in order, 20 s each, one play-through.',
|
||||
description: `${demoTrackTitle(index)} (${index + 1} of ${DEMO_TRACK_COUNT}) · Zai-Magic preset sequence -- every preset in order, 20 s each, one play-through.`,
|
||||
})
|
||||
} catch (err) {
|
||||
syncSource()
|
||||
|
|
@ -434,7 +469,7 @@ export function useAudioSource() {
|
|||
await engine.audio.startMic()
|
||||
syncSource()
|
||||
ensureDefaultPreset()
|
||||
toast({ title: 'Microphone live', description: 'Analyzing the mic input — it is never routed to the speakers.' })
|
||||
toast({ title: 'Microphone live', description: 'Analyzing the mic input -- it is never routed to the speakers.' })
|
||||
} catch (err) {
|
||||
syncSource()
|
||||
toast({ title: 'Microphone unavailable', description: micErrorMessage(err), variant: 'destructive' })
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ export function BeatDot({ size = 44, className }: BeatDotProps) {
|
|||
role="img"
|
||||
aria-label={
|
||||
idle
|
||||
? 'Beat indicator — paused, no audio playing'
|
||||
: `Beat indicator — ${bpm > 0 ? `${bpm.toFixed(1)} BPM` : 'no tempo'}${flashSource === 'predicted' ? ', predicted' : ''}`
|
||||
? 'Beat indicator -- paused, no audio playing'
|
||||
: `Beat indicator -- ${bpm > 0 ? `${bpm.toFixed(1)} BPM` : 'no tempo'}${flashSource === 'predicted' ? ', predicted' : ''}`
|
||||
}
|
||||
>
|
||||
{/* phase progress ring */}
|
||||
|
|
@ -79,7 +79,7 @@ export function BeatDot({ size = 44, className }: BeatDotProps) {
|
|||
/>
|
||||
</svg>
|
||||
|
||||
{/* filled pulse dot (audio / tap beats) — dimmed while no source is
|
||||
{/* filled pulse dot (audio / tap beats) -- dimmed while no source is
|
||||
playing/loaded, since beat detection is suspended (v6.4) */}
|
||||
<div
|
||||
className={cn(
|
||||
|
|
@ -108,7 +108,7 @@ export function BeatDot({ size = 44, className }: BeatDotProps) {
|
|||
/>
|
||||
)}
|
||||
|
||||
{/* PRED badge — visible while a predicted pulse is showing */}
|
||||
{/* PRED badge -- visible while a predicted pulse is showing */}
|
||||
{predicted && (
|
||||
<span
|
||||
className="absolute left-1/2 -translate-x-1/2 rounded border border-emerald-400/40 bg-zinc-950/90 px-1 py-px font-mono text-emerald-300"
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ export function BeatTab() {
|
|||
|
||||
const tapFeedback =
|
||||
source === 'idle'
|
||||
? 'No audio playing — start a source, then tap along'
|
||||
? 'No audio playing -- start a source, then tap along'
|
||||
: lastTap
|
||||
? lastTap.locked
|
||||
? `Locked: ${lastTap.bpm.toFixed(1)} BPM`
|
||||
: `Tap ${lastTap.tapCount}… keep tapping`
|
||||
: 'Tap along with the music — Space works too'
|
||||
: 'Tap along with the music -- Space works too'
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
|
|
@ -54,7 +54,7 @@ export function BeatTab() {
|
|||
<BeatDot size={80} />
|
||||
<div className="min-w-0">
|
||||
<div className="font-mono text-4xl font-bold leading-none tabular-nums text-emerald-400">
|
||||
{bpm > 0 ? bpm.toFixed(1) : '—'}
|
||||
{bpm > 0 ? bpm.toFixed(1) : '--'}
|
||||
<span className="ml-1.5 align-baseline font-sans text-sm font-medium text-zinc-500">BPM</span>
|
||||
</div>
|
||||
<div className="mt-2.5 flex flex-wrap items-center gap-2">
|
||||
|
|
@ -123,7 +123,7 @@ export function BeatTab() {
|
|||
className="py-1.5"
|
||||
/>
|
||||
<p className="mt-1.5 text-[11px] leading-relaxed text-zinc-500">
|
||||
How strongly periodic the music's attacks must be before the tempo locks — lower = locks easier.
|
||||
How strongly periodic the music's attacks must be before the tempo locks -- lower = locks easier.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ export function BeatTab() {
|
|||
className="py-1.5"
|
||||
/>
|
||||
<p className="mt-1.5 text-[11px] leading-relaxed text-zinc-500">
|
||||
Fastest allowed beat rate — raise it to ignore double-hits and rolls.
|
||||
Fastest allowed beat rate -- raise it to ignore double-hits and rolls.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -164,12 +164,12 @@ export function BeatTab() {
|
|||
|
||||
<p className="text-[11px] leading-relaxed text-zinc-500">
|
||||
<span className="font-semibold text-zinc-400">How it works:</span> the detector listens to the music's{' '}
|
||||
<span className="text-zinc-400">attacks</span> — the frame-to-frame jump of energy across the whole
|
||||
<span className="text-zinc-400">attacks</span> -- the frame-to-frame jump of energy across the whole
|
||||
spectrum (onsets). Every ~100 ms those onsets are autocorrelated over 300–1000 ms lags: a strong, consistent
|
||||
periodicity locks the tempo (the confidence meter), and a comb filter aligns a beat grid to it. Beats fire on
|
||||
that grid — <span className="text-zinc-400">PRED</span> when the grid carries the beat through a passage with
|
||||
that grid -- <span className="text-zinc-400">PRED</span> when the grid carries the beat through a passage with
|
||||
no clear attacks. This works on real mastered music, where a loud sustained sub-bass hides the kick from any
|
||||
level-based detector. Detection only runs while a source is playing — it pauses (and the BPM resets) whenever
|
||||
level-based detector. Detection only runs while a source is playing -- it pauses (and the BPM resets) whenever
|
||||
no music is loaded. <span className="font-semibold text-zinc-400">Set Beat</span> teaches the tempo
|
||||
directly: tap along and two or more taps lock the period and phase to your rhythm.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ function BandCard({ spec, levels }: { spec: BandSpec; levels: BandLevels | null
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* live VU meter — instant fill + smoothed peak-hold tick */}
|
||||
{/* live VU meter -- instant fill + smoothed peak-hold tick */}
|
||||
<div className="mt-4">
|
||||
<div className="relative h-2 overflow-hidden rounded-full bg-zinc-800/80">
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
// OVE — sticky footer status bar: micro-stats + maker credit + version stamp
|
||||
// + engine health.
|
||||
// OVE -- sticky footer status bar: micro-stats + maker credit + version
|
||||
// stamp. (v7.10: the engine-health dot is gone -- compile errors already
|
||||
// toast, so the always-green "engine ok" badge was pure noise.)
|
||||
//
|
||||
// v7.9 credit block: "© {year} · Site Created & Deployed by Sum'ting White" +
|
||||
// a "View my portfolio at zcreations.dev" link, centered in the footer's
|
||||
// blank area. Flex choreography: from xl the credit sits INLINE between the
|
||||
// stats and the right-hand stamp — its xl:mx-auto splits the free space so
|
||||
// stats and the right-hand stamp -- its xl:mx-auto splits the free space so
|
||||
// it centers in the blank area while the right group (xl:ml-0) hugs the edge.
|
||||
// Below xl there isn't room, so the credit is order-last + w-full: it drops
|
||||
// to its own centered row under the stats row (the stats + health stay on
|
||||
// row one via the right group's ml-auto). All zinc-* utilities follow the
|
||||
// visitor's base theme (each base remaps the ramp — globals.css).
|
||||
// to its own centered row under the stats row (the stats stay on row one
|
||||
// via the right group's ml-auto). All zinc-* utilities follow the visitor's
|
||||
// base theme (each base remaps the ramp -- globals.css).
|
||||
|
||||
'use client'
|
||||
|
||||
import { useAvaStore } from '@/lib/store'
|
||||
import { APP_NAME, APP_VERSION } from '@/lib/version'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
export function FooterBar() {
|
||||
const stats = useAvaStore((s) => s.stats)
|
||||
|
|
@ -25,8 +25,7 @@ export function FooterBar() {
|
|||
const fps = stats?.fps ?? 0
|
||||
const points = stats?.points ?? 0
|
||||
const bpm = stats?.beat.bpm ?? 0
|
||||
const scriptName = stats?.scriptName ?? '—'
|
||||
const error = stats?.error ?? null
|
||||
const scriptName = stats?.scriptName ?? '--'
|
||||
|
||||
return (
|
||||
<footer className="mt-auto border-t border-zinc-800/80 bg-zinc-950/90 backdrop-blur">
|
||||
|
|
@ -51,17 +50,17 @@ export function FooterBar() {
|
|||
PTS: <span className="text-zinc-300">{points}</span>
|
||||
</span>
|
||||
<span>
|
||||
BPM: <span className="text-zinc-300">{bpm > 0 ? bpm.toFixed(1) : '—'}</span>
|
||||
BPM: <span className="text-zinc-300">{bpm > 0 ? bpm.toFixed(1) : '--'}</span>
|
||||
</span>
|
||||
<span className="hidden min-w-0 items-center md:flex">
|
||||
SCRIPT: <span className="ml-1 truncate text-zinc-300">{scriptName}</span>
|
||||
</span>
|
||||
|
||||
{/* maker credit (v7.9) — centered in the blank area from xl; on
|
||||
{/* maker credit (v7.9) -- centered in the blank area from xl; on
|
||||
narrower screens it drops to its own centered row */}
|
||||
<div className="order-last flex w-full shrink-0 flex-wrap items-center justify-center gap-x-4 gap-y-1 xl:order-none xl:mx-auto xl:w-auto">
|
||||
{/* copyright span wraps at a word boundary on very narrow phones
|
||||
(the link stays on one line — a URL must never break) */}
|
||||
(the link stays on one line -- a URL must never break) */}
|
||||
<span className="max-w-full">
|
||||
© <span suppressHydrationWarning>{new Date().getFullYear()}</span> · Site Created & Deployed
|
||||
by Sum’ting White
|
||||
|
|
@ -77,26 +76,14 @@ export function FooterBar() {
|
|||
</a>
|
||||
</div>
|
||||
|
||||
{/* version stamp (left of the engine-health dot) + engine health */}
|
||||
{/* version stamp (v7.10: the engine-health dot beside it is gone) */}
|
||||
<div className="ml-auto flex shrink-0 items-center gap-3 sm:gap-4 xl:ml-0">
|
||||
<span
|
||||
className="text-zinc-600"
|
||||
title={`${APP_NAME} — version ${APP_VERSION}`}
|
||||
title={`${APP_NAME} -- version ${APP_VERSION}`}
|
||||
>
|
||||
version {APP_VERSION}
|
||||
</span>
|
||||
<span className={cn('flex items-center gap-1.5', error ? 'text-rose-400' : 'text-emerald-400')}>
|
||||
<span
|
||||
className={cn(
|
||||
'size-1.5 rounded-full',
|
||||
error
|
||||
? 'animate-pulse bg-rose-400 shadow-[0_0_8px_rgba(251,113,133,0.8)]'
|
||||
: 'glow-status bg-emerald-400',
|
||||
)}
|
||||
aria-hidden
|
||||
/>
|
||||
<span className="text-zinc-400">{error ? 'script error' : 'engine ok'}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ function SourceSegmentButton({
|
|||
)}
|
||||
>
|
||||
<Icon className="size-3.5 shrink-0" />
|
||||
{/* under 400px the five-button segment row exceeds the viewport — the
|
||||
{/* under 400px the five-button segment row exceeds the viewport -- the
|
||||
labels collapse to screen-reader-only (icon + tooltip carries the
|
||||
meaning, same shortening pattern as What's New! → New) */}
|
||||
<span className="max-[400px]:sr-only">{label}</span>
|
||||
|
|
@ -76,7 +76,7 @@ function SourceControls() {
|
|||
onClick={() => void startDemo()}
|
||||
icon={Disc3}
|
||||
label="Demo"
|
||||
title="Built-in demo track — Neural Mecha Pulse (mastered industrial EDM, plays once through)"
|
||||
title="Built-in demo tracks -- one of ten mastered recordings, plays once through. Each finished play-through (or Stop) advances to the next track."
|
||||
/>
|
||||
<SourceSegmentButton
|
||||
active={source === 'mic'}
|
||||
|
|
@ -105,7 +105,7 @@ function SourceControls() {
|
|||
{source === 'demo' && (
|
||||
<div
|
||||
className="flex h-11 max-w-[240px] items-center gap-2 rounded-lg border border-zinc-800 bg-zinc-900/60 px-3"
|
||||
title="The demo track is a real mastered recording — its tempo is detected live, not synthesized. Watch the BPM readout lock on."
|
||||
title="The demo track is a real mastered recording -- its tempo is detected live, not synthesized. Watch the BPM readout lock on."
|
||||
>
|
||||
<Music2 className="size-3.5 shrink-0 text-emerald-400/80" aria-hidden />
|
||||
<span className="truncate font-mono text-[11px] tracking-wide text-zinc-300">
|
||||
|
|
@ -134,7 +134,7 @@ function BpmReadout() {
|
|||
return (
|
||||
<div className="text-right leading-none">
|
||||
<div className="font-mono text-xl font-bold tabular-nums text-emerald-400 sm:text-2xl">
|
||||
{bpm > 0 ? bpm.toFixed(1) : '—'}
|
||||
{bpm > 0 ? bpm.toFixed(1) : '--'}
|
||||
</div>
|
||||
<div className="mt-0.5 font-mono text-[9px] tracking-[0.2em] text-zinc-500">BPM</div>
|
||||
</div>
|
||||
|
|
@ -158,7 +158,7 @@ function ThemeToggle() {
|
|||
return (
|
||||
<div
|
||||
className="flex h-11 items-center gap-1.5 rounded-lg border border-zinc-800 bg-zinc-900/60 px-2.5"
|
||||
title={isLight ? 'Theme: light — flip left for dark' : 'Theme: dark — flip right for light'}
|
||||
title={isLight ? 'Theme: light -- flip left for dark' : 'Theme: dark -- flip right for light'}
|
||||
>
|
||||
<Moon className="size-3.5 shrink-0 text-zinc-500" aria-hidden />
|
||||
<Switch
|
||||
|
|
@ -189,12 +189,12 @@ export function AppHeader() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* source controls — full row on mobile, after logo on desktop */}
|
||||
{/* source controls -- full row on mobile, after logo on desktop */}
|
||||
<div className="order-3 basis-full md:order-2 md:basis-auto">
|
||||
<SourceControls />
|
||||
</div>
|
||||
|
||||
{/* what's new + theme switch + BPM readout + beat indicator — always visible */}
|
||||
{/* what's new + theme switch + BPM readout + beat indicator -- always visible */}
|
||||
<div className="order-2 ml-auto flex items-center gap-2.5 md:order-3 sm:gap-3">
|
||||
<WhatsNew />
|
||||
<ThemeToggle />
|
||||
|
|
|
|||
|
|
@ -6,22 +6,22 @@
|
|||
import type { ReactNode } from 'react'
|
||||
|
||||
const FRAME_VARS: [string, string][] = [
|
||||
['n', 'point count (4–4096, default 400 — set in [init] or [frame])'],
|
||||
['n', 'point count (4–4096, default 400 -- set in [init] or [frame])'],
|
||||
['t', 'your own counter (do with it whatever you want)'],
|
||||
['time', 'seconds since the script started'],
|
||||
['dt', 'frame delta in seconds'],
|
||||
['frame', 'frame number'],
|
||||
['bass / mid / treb', 'instant band levels, 0..1 and above'],
|
||||
['bass_att / mid_att / treb_att', 'smoothed bands (fast attack, slow release) — use these for beat detection logic'],
|
||||
['bass_att / mid_att / treb_att', 'smoothed bands (fast attack, slow release) -- use these for beat detection logic'],
|
||||
['vol / vol_att', 'overall level, instant + smoothed'],
|
||||
['beat', '1 on the frame a beat fired, else 0'],
|
||||
['bpm', 'detected tempo'],
|
||||
['beatphase', '0..1 position within the beat period'],
|
||||
['beatconf', '0..1 confidence of the tempo lock'],
|
||||
['beats', 'total beat count since load'],
|
||||
['beatage', 'seconds since the last beat (0 on the beat frame) — exp(-beatage*4) is a kick envelope'],
|
||||
['beatage', 'seconds since the last beat (0 on the beat frame) -- exp(-beatage*4) is a kick envelope'],
|
||||
['w / h', 'canvas size in pixels'],
|
||||
['aspect', 'canvas width / height — divide x by it for perfect circles'],
|
||||
['aspect', 'canvas width / height -- divide x by it for perfect circles'],
|
||||
['persist', 'motion-trail persistence 0..0.98 (writable per frame)'],
|
||||
]
|
||||
|
||||
|
|
@ -42,21 +42,21 @@ const FUNCS: [string, string][] = [
|
|||
['abs sqrt sqr pow(x, y) exp log log10', 'powers, roots & logs'],
|
||||
['floor ceil round int frac sign', 'rounding & sign'],
|
||||
['min max', 'pairwise extrema'],
|
||||
['rand(seed)', 'deterministic per-seed random 0..1 — rand(i) is stable per point'],
|
||||
['hsvr(h, s?, v?) hsvg hsvb', 'HSV→RGB channels (hue wraps 0..1; s, v default 1) — red = hsvr(hue) + green = hsvg(hue) + blue = hsvb(hue) paints the rainbow'],
|
||||
['rand(seed)', 'deterministic per-seed random 0..1 -- rand(i) is stable per point'],
|
||||
['hsvr(h, s?, v?) hsvg hsvb', 'HSV→RGB channels (hue wraps 0..1; s, v default 1) -- red = hsvr(hue) + green = hsvg(hue) + blue = hsvb(hue) paints the rainbow'],
|
||||
['smoothstep(e0, e1, x)', 'hermite-smooth 0..1 step between e0 and e1'],
|
||||
['lerp(a, b, t) clamp(x, lo, hi)', 'interpolate & constrain'],
|
||||
['inrange(x, lo, hi)', '1 when lo ≤ x ≤ hi'],
|
||||
['above(a, b) below(a, b) equal(a, b)', 'comparisons returning 1/0'],
|
||||
['band(a, b) bor(a, b) bnot(a)', 'logical and / or / not (also && || !)'],
|
||||
['sigmoid(x, y)', '1 / (1 + exp(-x·y))'],
|
||||
['if(cond, a, b)', 'lazy conditional — only the taken branch runs, so if(beat, flash=1, 0) works'],
|
||||
['if(cond, a, b)', 'lazy conditional -- only the taken branch runs, so if(beat, flash=1, 0) works'],
|
||||
]
|
||||
|
||||
const EXAMPLES: [string, string][] = [
|
||||
['hue = frac(hue + beat * 0.125)', 'rotate the color wheel 1/8 turn on every beat'],
|
||||
['red = hsvr(hue); green = hsvg(hue); blue = hsvb(hue)', 'full rainbow from one hue variable'],
|
||||
['flash = exp(-beatage * 5)', 'kick envelope — 1 on the beat, fades fast'],
|
||||
['flash = exp(-beatage * 5)', 'kick envelope -- 1 on the beat, fades fast'],
|
||||
['if(equal(beats % 4, 0), hue = frac(hue + 0.25), 0)', 'shift color once per 4-beat bar'],
|
||||
['rad = 0.2 + bass * 0.6', 'bass pulse'],
|
||||
['rot = rot + dt * 1.2 + beat * 0.4', 'beat kick'],
|
||||
|
|
@ -109,15 +109,15 @@ export function HelpPanel() {
|
|||
<span className="font-mono text-emerald-400/90">bass</span>,{' '}
|
||||
<span className="font-mono text-emerald-400/90">beat</span> and <span className="font-mono text-emerald-400/90">v</span>.
|
||||
</li>
|
||||
<li>Hit Apply ▶ — errors are flagged next to the exact line.</li>
|
||||
<li>Hit Apply ▶ -- errors are flagged next to the exact line.</li>
|
||||
</ol>
|
||||
</HelpSection>
|
||||
|
||||
<HelpSection title="Variables — everywhere">
|
||||
<HelpSection title="Variables -- everywhere">
|
||||
<HelpTable rows={FRAME_VARS} />
|
||||
</HelpSection>
|
||||
|
||||
<HelpSection title="Variables — [point] only">
|
||||
<HelpSection title="Variables -- [point] only">
|
||||
<HelpTable rows={POINT_VARS} />
|
||||
</HelpSection>
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { ArrowLeft, Link2, Loader2, ListMusic, Play, Settings2, ShieldCheck } from 'lucide-react'
|
||||
import { ArrowLeft, Link2, Loader2, Play, Settings2, ShieldCheck } from 'lucide-react'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
|
|
@ -221,7 +221,7 @@ function LinkDialogBody() {
|
|||
setOpen(false)
|
||||
toast({
|
||||
title: 'Queue started',
|
||||
description: `${playlist.title} — ${playlist.entries.length} tracks, streamed one at a time.`,
|
||||
description: `${playlist.title} -- ${playlist.entries.length} tracks, streamed one at a time.`,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ function LinkDialogBody() {
|
|||
Stream a music link
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
A track plays immediately; a playlist becomes a queue that streams one song at a time —
|
||||
A track plays immediately; a playlist becomes a queue that streams one song at a time --
|
||||
each is fetched only right before it plays. YouTube, SoundCloud, Bandcamp and direct
|
||||
files work today; Spotify and Apple Music arrive in a later update.
|
||||
</DialogDescription>
|
||||
|
|
@ -264,10 +264,10 @@ function LinkDialogBody() {
|
|||
className="h-8 w-full gap-1.5 bg-emerald-400 font-semibold text-emerald-950 hover:bg-emerald-300"
|
||||
>
|
||||
<Play className="size-3.5" aria-hidden />
|
||||
Play all — lazy queue
|
||||
Play all -- lazy queue
|
||||
</Button>
|
||||
<p className="text-[10px] leading-snug text-zinc-500">
|
||||
Starting anywhere queues the whole list behind it. Only one song is ever being fetched —
|
||||
Starting anywhere queues the whole list behind it. Only one song is ever being fetched --
|
||||
the next one resolves just before it plays, so the source is never spammed.
|
||||
</p>
|
||||
<div className={cn('max-h-64 space-y-1 overflow-y-auto pr-1', thinScrollbar)}>
|
||||
|
|
@ -279,7 +279,7 @@ function LinkDialogBody() {
|
|||
type="button"
|
||||
onClick={() => startQueueFrom(i)}
|
||||
disabled={busy}
|
||||
title={`${e.title} — start the queue from this track`}
|
||||
title={`${e.title} -- start the queue from this track`}
|
||||
className="group flex w-full items-center gap-2 rounded-md border border-zinc-800 bg-zinc-900/60 px-2.5 py-1.5 text-left text-xs text-zinc-300 transition-colors hover:border-emerald-500/40 hover:text-zinc-100 disabled:opacity-50"
|
||||
>
|
||||
<span className="w-4 shrink-0 text-right font-mono text-[10px] tabular-nums text-zinc-600">
|
||||
|
|
@ -337,7 +337,7 @@ function LinkDialogBody() {
|
|||
|
||||
{busy && (
|
||||
<p className="text-[11px] leading-relaxed text-zinc-500" role="status">
|
||||
Downloading the audio and converting it to MP3 on the server — this
|
||||
Downloading the audio and converting it to MP3 on the server -- this
|
||||
can take a little while on longer tracks.
|
||||
</p>
|
||||
)}
|
||||
|
|
@ -360,7 +360,7 @@ function LinkDialogBody() {
|
|||
style={{ background: comingSoon.brandColor }}
|
||||
aria-hidden
|
||||
/>
|
||||
{comingSoon.name} — coming in a later update
|
||||
{comingSoon.name} -- coming in a later update
|
||||
</p>
|
||||
<p className="text-amber-200/80">{comingSoon.comingSoonNote ?? comingSoon.note}</p>
|
||||
<button
|
||||
|
|
@ -398,7 +398,7 @@ function LinkDialogBody() {
|
|||
)}
|
||||
{!usingLogin && errorCode !== 'bot-wall' && errorCode !== 'backend-error' && (
|
||||
<p className="text-rose-300/70">
|
||||
Tip: log in to the service from the Settings tab — links then resolve with your own
|
||||
Tip: log in to the service from the Settings tab -- links then resolve with your own
|
||||
account and usually skip this.
|
||||
</p>
|
||||
)}
|
||||
|
|
@ -432,12 +432,6 @@ function LinkDialogBody() {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className="flex items-start gap-1.5 text-[11px] leading-relaxed text-zinc-500">
|
||||
<ListMusic className="mt-0.5 size-3.5 shrink-0" aria-hidden />
|
||||
Everything after the link resolves — FFT analysis, beat tracking and rendering — runs
|
||||
locally in your browser. Log in from the Settings tab to use your own playlists.
|
||||
</p>
|
||||
</DialogContent>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export function NativeTab() {
|
|||
|
||||
<blockquote className="rounded-lg border border-emerald-400/20 bg-emerald-400/5 p-3 text-[11px] leading-relaxed text-emerald-700/90 dark:text-emerald-200/80">
|
||||
The <span className="font-mono">.ava</span> scripts you write here run on both the web edition and the native
|
||||
Rust engine — the script language is identical.
|
||||
Rust engine -- the script language is identical.
|
||||
</blockquote>
|
||||
|
||||
<Separator className="bg-zinc-800" />
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ function TreeFolder({ node }: { node: FolderNode }) {
|
|||
<button
|
||||
type="button"
|
||||
onClick={() => useAvaStore.getState().selectFolder(node.path)}
|
||||
title={readOnly ? `${node.path} — read-only (shipped with OVE)` : node.path}
|
||||
title={readOnly ? `${node.path} -- read-only (shipped with OVE)` : node.path}
|
||||
className="flex h-9 min-w-0 flex-1 items-center gap-1.5 py-1 pr-1 text-left"
|
||||
>
|
||||
{isOpen ? (
|
||||
|
|
@ -234,7 +234,7 @@ function TreeFolder({ node }: { node: FolderNode }) {
|
|||
</span>
|
||||
{readOnly && (
|
||||
<span
|
||||
title="Read-only — the shipped library is the same for every visitor"
|
||||
title="Read-only -- the shipped library is the same for every visitor"
|
||||
aria-label="Read-only folder"
|
||||
className="shrink-0 text-zinc-600"
|
||||
>
|
||||
|
|
@ -267,7 +267,7 @@ function TreeFolder({ node }: { node: FolderNode }) {
|
|||
style={{ paddingLeft: (node.depth + 1) * 10 + 18 }}
|
||||
>
|
||||
{node.path === USER_ROOT
|
||||
? 'yours — create or import presets (stored in this browser)'
|
||||
? '(Created and imported presets are stored in this browser.)'
|
||||
: '(empty)'}
|
||||
</p>
|
||||
)}
|
||||
|
|
@ -302,7 +302,7 @@ function TreePreset({ preset, depth }: { preset: PresetItem; depth: number }) {
|
|||
type="button"
|
||||
onClick={() => useAvaStore.getState().selectPreset(preset.id)}
|
||||
onDoubleClick={() => loadPreset(preset)}
|
||||
title={`${preset.name} (double-click to run)${own ? ' — yours (this browser)' : ''}`}
|
||||
title={`${preset.name} (double-click to run)${own ? ' -- yours (this browser)' : ''}`}
|
||||
className="flex h-9 min-w-0 flex-1 items-center gap-1.5 py-1 pr-1 text-left"
|
||||
>
|
||||
{running ? (
|
||||
|
|
@ -315,7 +315,7 @@ function TreePreset({ preset, depth }: { preset: PresetItem; depth: number }) {
|
|||
</span>
|
||||
{preset.approx && (
|
||||
<span
|
||||
title="Approximation — the original preset relies on effects the script engine can't run, so this is a uniquely generated stand-in"
|
||||
title="Approximation -- the original preset relies on effects the script engine can't run, so this is a uniquely generated stand-in"
|
||||
className="shrink-0 rounded border border-amber-300/30 bg-amber-300/10 px-1 font-mono text-[9px] leading-4 text-amber-300/90"
|
||||
>
|
||||
≈
|
||||
|
|
@ -323,7 +323,7 @@ function TreePreset({ preset, depth }: { preset: PresetItem; depth: number }) {
|
|||
)}
|
||||
{own && (
|
||||
<span
|
||||
title="Your preset — stored in this browser only"
|
||||
title="Your preset -- stored in this browser only"
|
||||
aria-label="Your preset, stored in this browser"
|
||||
className="shrink-0 text-emerald-400/60"
|
||||
>
|
||||
|
|
@ -530,7 +530,7 @@ export function PresetsTab() {
|
|||
st.setTab('script')
|
||||
toast({
|
||||
title: 'Preset created',
|
||||
description: `"${res.preset.name}" created in this browser — now edit and Save.`,
|
||||
description: `"${res.preset.name}" created in this browser -- now edit and Save.`,
|
||||
})
|
||||
return true
|
||||
} finally {
|
||||
|
|
@ -673,7 +673,7 @@ export function PresetsTab() {
|
|||
st.selectPreset(res.preset.id)
|
||||
toast({
|
||||
title: 'Copied to your presets',
|
||||
description: `"${res.preset.name}" is now yours to edit — stored in this browser only.`,
|
||||
description: `"${res.preset.name}" is now yours to edit -- stored in this browser only.`,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
|
@ -684,7 +684,7 @@ export function PresetsTab() {
|
|||
}
|
||||
toast({
|
||||
title: 'Copy failed',
|
||||
description: 'A preset with that name already exists — rename it in "user created" first.',
|
||||
description: 'A preset with that name already exists -- rename it in "user created" first.',
|
||||
variant: 'destructive',
|
||||
})
|
||||
}
|
||||
|
|
@ -716,7 +716,7 @@ export function PresetsTab() {
|
|||
useAvaStore.getState().toggleFolder(USER_ROOT, true)
|
||||
let summary = `Imported ${res.imported} presets into your browser library`
|
||||
if ((res.skipped ?? 0) > 0) summary += `, ${res.skipped} duplicates skipped`
|
||||
if ((res.foldersCreated ?? 0) > 0) summary += ` — ${res.foldersCreated} folders created`
|
||||
if ((res.foldersCreated ?? 0) > 0) summary += ` -- ${res.foldersCreated} folders created`
|
||||
toast({ title: 'Import complete', description: `${summary}.` })
|
||||
} catch {
|
||||
toast({ title: 'Import failed', description: 'Could not read that zip.', variant: 'destructive' })
|
||||
|
|
@ -756,7 +756,7 @@ export function PresetsTab() {
|
|||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3 sm:flex-row">
|
||||
{/* LEFT — folder/file tree */}
|
||||
{/* LEFT -- folder/file tree */}
|
||||
<div className="min-w-0 flex-1 rounded-lg border border-zinc-800/80 bg-zinc-950/40 p-2 sm:w-[58%] sm:shrink-0">
|
||||
<div
|
||||
role="tree"
|
||||
|
|
@ -772,7 +772,7 @@ export function PresetsTab() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT — management panel */}
|
||||
{/* RIGHT -- management panel */}
|
||||
<div className="flex min-w-0 flex-1 flex-col rounded-lg border border-zinc-800/80 bg-zinc-950/40 p-3">
|
||||
<div className="flex items-start gap-2">
|
||||
{selectedPreset ? (
|
||||
|
|
@ -802,7 +802,7 @@ export function PresetsTab() {
|
|||
{(folderReadOnly || (selectedPreset && !presetOwn)) && (
|
||||
<span
|
||||
className="flex shrink-0 items-center gap-1 rounded-full border border-zinc-700/70 bg-zinc-900/60 px-1.5 py-0.5 font-mono text-[9px] uppercase tracking-wide text-zinc-500"
|
||||
title="Read-only — identical for every visitor. Copy it to 'user created' to remix."
|
||||
title="Read-only -- identical for every visitor. Copy it to 'user created' to remix."
|
||||
>
|
||||
<Lock className="size-2.5" aria-hidden /> read-only
|
||||
</span>
|
||||
|
|
@ -842,37 +842,26 @@ export function PresetsTab() {
|
|||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => copyToMyPresets(selectedPreset)}
|
||||
title="Save an editable copy of this preset into your browser's 'user created' folder"
|
||||
className="h-9 w-full gap-1.5 border-zinc-700"
|
||||
>
|
||||
<CopyPlus className="size-3.5" /> Copy to my presets
|
||||
</Button>
|
||||
<p className="text-[11px] leading-relaxed text-zinc-500">
|
||||
Embedded presets are read-only — identical for every visitor. Copy it to make it yours
|
||||
(stored in this browser only).
|
||||
</p>
|
||||
</>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => copyToMyPresets(selectedPreset)}
|
||||
title="Save an editable copy of this preset into your browser's 'user created' folder"
|
||||
className="h-9 w-full gap-1.5 border-zinc-700"
|
||||
>
|
||||
<CopyPlus className="size-3.5" /> Copy to my presets
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
) : folderReadOnly ? (
|
||||
<>
|
||||
<p className="text-[11px] leading-relaxed text-zinc-500">
|
||||
The embedded library is <span className="text-zinc-300">read-only</span> — the same for every
|
||||
visitor, safe from edits, renames and deletion. Your own presets live under{' '}
|
||||
<span className="font-mono text-zinc-400">user created</span>, stored in this browser.
|
||||
</p>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={busy || folderPresetCount === 0}
|
||||
onClick={() => void exportZip()}
|
||||
title="Download this folder (with subfolders) as a .zip preserving the tree — built in your browser"
|
||||
title="Download this folder (with subfolders) as a .zip preserving the tree -- built in your browser"
|
||||
className="h-8 shrink-0 gap-1 whitespace-nowrap text-xs has-[>svg]:px-2 border-zinc-700"
|
||||
>
|
||||
<Download className="size-3.5" /> Export .zip
|
||||
|
|
@ -882,7 +871,7 @@ export function PresetsTab() {
|
|||
variant="outline"
|
||||
disabled={busy}
|
||||
onClick={() => importInputRef.current?.click()}
|
||||
title="Import a .zip of .ava presets — they land in your browser's 'user created' folder"
|
||||
title="Import a .zip of .ava presets -- they land in your browser's 'user created' folder"
|
||||
className="h-8 shrink-0 gap-1 whitespace-nowrap text-xs has-[>svg]:px-2 border-zinc-700"
|
||||
>
|
||||
<Upload className="size-3.5" /> Import .zip
|
||||
|
|
@ -915,7 +904,7 @@ export function PresetsTab() {
|
|||
variant="outline"
|
||||
disabled={folderProtected}
|
||||
onClick={() => openDialog('rename', folderName)}
|
||||
title={folderProtected ? '"user created" is the root of your library' : `Rename ${folderName} — everything inside moves with it`}
|
||||
title={folderProtected ? '"user created" is the root of your library' : `Rename ${folderName} -- everything inside moves with it`}
|
||||
className="h-8 shrink-0 gap-1 whitespace-nowrap text-xs has-[>svg]:px-2 border-zinc-700"
|
||||
>
|
||||
<Pencil className="size-3.5" /> Rename
|
||||
|
|
@ -937,7 +926,7 @@ export function PresetsTab() {
|
|||
variant="outline"
|
||||
disabled={busy || folderPresetCount === 0}
|
||||
onClick={() => void exportZip()}
|
||||
title="Download this folder (with subfolders) as a .zip preserving the tree — built in your browser"
|
||||
title="Download this folder (with subfolders) as a .zip preserving the tree -- built in your browser"
|
||||
className="h-8 shrink-0 gap-1 whitespace-nowrap text-xs has-[>svg]:px-2 border-zinc-700"
|
||||
>
|
||||
<Download className="size-3.5" /> Export .zip
|
||||
|
|
@ -947,7 +936,7 @@ export function PresetsTab() {
|
|||
variant="outline"
|
||||
disabled={busy}
|
||||
onClick={() => importInputRef.current?.click()}
|
||||
title={`Import a .zip of .ava presets into ${selectedFolder} — the tree inside the zip is preserved`}
|
||||
title={`Import a .zip of .ava presets into ${selectedFolder} -- the tree inside the zip is preserved`}
|
||||
className="h-8 shrink-0 gap-1 whitespace-nowrap text-xs has-[>svg]:px-2 border-zinc-700"
|
||||
>
|
||||
<Upload className="size-3.5" /> Import .zip
|
||||
|
|
@ -957,7 +946,7 @@ export function PresetsTab() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* preset mixing (club mode) — Random or Sequence, one timer in the store */}
|
||||
{/* preset mixing (club mode) -- Random or Sequence, one timer in the store */}
|
||||
<div className="mt-4 border-t border-zinc-800/80 pt-3">
|
||||
<div className="flex flex-wrap items-center gap-x-3 gap-y-2">
|
||||
<span className="flex items-center gap-2">
|
||||
|
|
@ -1002,12 +991,7 @@ export function PresetsTab() {
|
|||
<p className="mt-2 text-[11px] leading-relaxed text-zinc-500">
|
||||
{sequenceMode ? 'Sequence from:' : 'Random from:'}{' '}
|
||||
<span className="font-mono text-zinc-400">{scopeLabel}</span>
|
||||
{scopeCount === 0 && <span className="ml-1 text-amber-300/80">— no presets in this folder yet</span>}
|
||||
</p>
|
||||
<p className="mt-1 text-[11px] leading-relaxed text-zinc-600">
|
||||
{sequenceMode
|
||||
? 'Cycles the folder top-to-bottom, wraps back to the first preset.'
|
||||
: 'Shuffles the folder — never the same preset twice in a row.'}
|
||||
{scopeCount === 0 && <span className="ml-1 text-amber-300/80">-- no presets in this folder yet</span>}
|
||||
</p>
|
||||
{(randomize || sequenceMode) && (
|
||||
<div className="mt-2">
|
||||
|
|
@ -1026,7 +1010,7 @@ export function PresetsTab() {
|
|||
open={dialog === 'createPreset'}
|
||||
onOpenChange={(o) => setDialog(o ? 'createPreset' : null)}
|
||||
title="Create preset"
|
||||
description={`New preset from the starter template inside ${selectedFolder} — saved in this browser.`}
|
||||
description={`New preset from the starter template inside ${selectedFolder} -- saved in this browser.`}
|
||||
placeholder="Preset name"
|
||||
value={nameValue}
|
||||
onChange={setNameValue}
|
||||
|
|
@ -1040,7 +1024,7 @@ export function PresetsTab() {
|
|||
open={dialog === 'newFolder'}
|
||||
onOpenChange={(o) => setDialog(o ? 'newFolder' : null)}
|
||||
title="New subfolder"
|
||||
description={`Created inside ${selectedFolder} — saved in this browser.`}
|
||||
description={`Created inside ${selectedFolder} -- saved in this browser.`}
|
||||
placeholder="Folder name"
|
||||
value={nameValue}
|
||||
onChange={setNameValue}
|
||||
|
|
@ -1057,7 +1041,7 @@ export function PresetsTab() {
|
|||
description={
|
||||
selectedPreset
|
||||
? `Currently "${selectedPreset.name}" in ${selectedPreset.folderPath}.`
|
||||
: `Currently "${folderName}" — everything inside moves with it.`
|
||||
: `Currently "${folderName}" -- everything inside moves with it.`
|
||||
}
|
||||
placeholder="New name"
|
||||
value={nameValue}
|
||||
|
|
|
|||
|
|
@ -158,12 +158,12 @@ export function QueueBar() {
|
|||
{status === 'done' ? (
|
||||
<p className="flex items-center gap-1.5 text-xs text-zinc-400">
|
||||
<RotateCcw className="size-3.5 shrink-0 text-emerald-400" aria-hidden />
|
||||
Queue finished — {entries.length} track{entries.length === 1 ? '' : 's'} played.
|
||||
Queue finished -- {entries.length} track{entries.length === 1 ? '' : 's'} played.
|
||||
</p>
|
||||
) : status === 'blocked' ? (
|
||||
<p className="flex items-center gap-1.5 text-xs text-amber-300">
|
||||
<PauseCircle className="size-3.5 shrink-0" aria-hidden />
|
||||
The browser blocked auto-advance — press Resume to keep the queue going.
|
||||
The browser blocked auto-advance -- press Resume to keep the queue going.
|
||||
</p>
|
||||
) : status === 'error' ? (
|
||||
<p className="flex items-center gap-1.5 truncate text-xs text-rose-300" title={lastError ?? undefined}>
|
||||
|
|
@ -173,7 +173,7 @@ export function QueueBar() {
|
|||
) : status === 'loading' && updating ? (
|
||||
<p className="flex items-center gap-1.5 text-xs text-amber-300">
|
||||
<Loader2 className="size-3.5 shrink-0 animate-spin" aria-hidden />
|
||||
Updating in Background — the audio engine on the server is updating itself; your
|
||||
Updating in Background -- the audio engine on the server is updating itself; your
|
||||
music resumes in a moment.
|
||||
</p>
|
||||
) : (
|
||||
|
|
@ -267,7 +267,7 @@ export function QueueBar() {
|
|||
>
|
||||
<div className="mt-2 border-t border-zinc-800/80 pt-2">
|
||||
<p className="mb-1.5 font-mono text-[10px] tracking-[0.2em] text-zinc-500">
|
||||
QUEUE — CLICK A TRACK TO JUMP
|
||||
QUEUE -- CLICK A TRACK TO JUMP
|
||||
</p>
|
||||
<ul className={cn('max-h-64 space-y-1 overflow-y-auto pr-1', thinScrollbar)} role="listbox" aria-label="Queue tracks">
|
||||
{entries.map((e, i) => {
|
||||
|
|
@ -307,7 +307,7 @@ export function QueueBar() {
|
|||
</AnimatePresence>
|
||||
|
||||
<p className="mt-1.5 hidden text-[10px] leading-snug text-zinc-600 sm:block">
|
||||
Lazy queue — each track is fetched from the source only right before it plays, one at a time, so
|
||||
Lazy queue -- each track is fetched from the source only right before it plays, one at a time, so
|
||||
playlist hosts are never hit with bulk requests.
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ export function ScriptTab() {
|
|||
const v = validateScript(scriptText)
|
||||
toast({
|
||||
title: 'Script applied',
|
||||
description: `mode: ${v.meta?.mode ?? '?'}, n=${initN ?? '?'} — running "${v.meta?.name ?? 'Untitled'}".`,
|
||||
description: `mode: ${v.meta?.mode ?? '?'}, n=${initN ?? '?'} -- running "${v.meta?.name ?? 'Untitled'}".`,
|
||||
})
|
||||
} else if (result.error) {
|
||||
toast({
|
||||
|
|
@ -136,7 +136,7 @@ export function ScriptTab() {
|
|||
toast({
|
||||
title: 'Embedded presets are read-only',
|
||||
description:
|
||||
'Use "Save As…" — it stores your copy under "user created" in this browser, leaving the shared library untouched.',
|
||||
'Use "Save As…" -- it stores your copy under "user created" in this browser, leaving the shared library untouched.',
|
||||
variant: 'destructive',
|
||||
})
|
||||
return
|
||||
|
|
@ -231,7 +231,7 @@ export function ScriptTab() {
|
|||
} else if (result.error) {
|
||||
toast({
|
||||
title: 'Loaded with errors',
|
||||
description: `[${result.error.section}] line ${result.error.line}: ${result.error.message} — fix and Apply.`,
|
||||
description: `[${result.error.section}] line ${result.error.line}: ${result.error.message} -- fix and Apply.`,
|
||||
variant: 'destructive',
|
||||
})
|
||||
}
|
||||
|
|
@ -265,14 +265,14 @@ export function ScriptTab() {
|
|||
return { ok: false, text: `✘ runtime: ${runtimeError}` }
|
||||
}
|
||||
if (validation?.ok) {
|
||||
return { ok: true, text: `✔ Compiled OK — mode: ${validation.meta?.mode}, n=${initN ?? 400}` }
|
||||
return { ok: true, text: `✔ Compiled OK -- mode: ${validation.meta?.mode}, n=${initN ?? 400}` }
|
||||
}
|
||||
return { ok: null, text: '…' }
|
||||
})()
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
{/* save-target chip — which preset "Save" writes into */}
|
||||
{/* save-target chip -- which preset "Save" writes into */}
|
||||
{editTarget && (
|
||||
<div className="flex min-h-9 items-center gap-1.5 rounded-lg border border-emerald-400/25 bg-emerald-400/5 py-0.5 pl-2.5 pr-0.5 font-mono text-[11px] text-emerald-300/90">
|
||||
<FolderOpen className="size-3.5 shrink-0" aria-hidden />
|
||||
|
|
@ -355,7 +355,7 @@ export function ScriptTab() {
|
|||
variant="outline"
|
||||
onClick={() => setShareOutOpen(true)}
|
||||
className="h-9 gap-1.5 border-zinc-700"
|
||||
title="Turn this script into one short shareable string — post it anywhere"
|
||||
title="Turn this script into one short shareable string -- post it anywhere"
|
||||
>
|
||||
<Share2 className="size-3.5 text-emerald-400/90" /> Script⇢Hash
|
||||
</Button>
|
||||
|
|
@ -486,7 +486,7 @@ export function ScriptTab() {
|
|||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* v7.7 — share-string dialogs */}
|
||||
{/* v7.7 -- share-string dialogs */}
|
||||
<ScriptToHashDialog open={shareOutOpen} onOpenChange={setShareOutOpen} scriptText={scriptText} />
|
||||
<HashToScriptDialog
|
||||
open={shareInOpen}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ function LoginDialogBody({
|
|||
Log in to a music service
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Use your own account from the Link button — your playlists, liked music, and no
|
||||
Use your own account from the Link button -- your playlists, liked music, and no
|
||||
"confirm you're not a bot" walls.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
|
@ -221,7 +221,7 @@ function LoginDialogBody({
|
|||
{houseServices?.[service] && (
|
||||
<p className="flex items-start gap-1.5 rounded-md border border-emerald-500/25 bg-emerald-500/10 px-2.5 py-1.5 text-[10px] leading-relaxed text-emerald-300">
|
||||
<Check className="mt-0.5 size-3 shrink-0" aria-hidden />
|
||||
A built-in account is already active for this service — links play for everyone. Your
|
||||
A built-in account is already active for this service -- links play for everyone. Your
|
||||
own login adds your playlists, liked music and uploads on top.
|
||||
</p>
|
||||
)}
|
||||
|
|
@ -236,7 +236,7 @@ function LoginDialogBody({
|
|||
))}
|
||||
</ol>
|
||||
<p className="mt-1.5 text-[10px] leading-relaxed text-zinc-500">
|
||||
Tip: the box also accepts a Cookie-Editor “Export → JSON” — paste, drop or
|
||||
Tip: the box also accepts a Cookie-Editor “Export → JSON” -- paste, drop or
|
||||
import whichever you have.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -277,7 +277,7 @@ function LoginDialogBody({
|
|||
{dragOver && (
|
||||
<div className="pointer-events-none absolute inset-0 grid place-items-center rounded-lg border border-emerald-400/50 bg-zinc-950/85 p-3 text-center">
|
||||
<p className="text-[11px] font-medium text-emerald-300">
|
||||
Drop the exported cookies.txt / JSON file — it fills this box automatically.
|
||||
Drop the exported cookies.txt / JSON file -- it fills this box automatically.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -308,7 +308,7 @@ function LoginDialogBody({
|
|||
Import the exported file…
|
||||
</Button>
|
||||
<p className="text-[10px] leading-relaxed text-zinc-500">
|
||||
or just drag & drop it onto the box above — no opening, no copying.
|
||||
or just drag & drop it onto the box above -- no opening, no copying.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -328,13 +328,13 @@ function LoginDialogBody({
|
|||
{validation.looksGood ? (
|
||||
<span className="flex items-start gap-1.5">
|
||||
<Check className="mt-0.5 size-3 shrink-0" aria-hidden />
|
||||
{validation.count} cookies detected ({FORMAT_LABEL[validation.format]}) — looks
|
||||
{validation.count} cookies detected ({FORMAT_LABEL[validation.format]}) -- looks
|
||||
like a complete {def.name.split(' / ')[0]} login.
|
||||
</span>
|
||||
) : validation.format === 'unknown' ? (
|
||||
<span className="flex items-start gap-1.5">
|
||||
<AlertTriangle className="mt-0.5 size-3 shrink-0" aria-hidden />
|
||||
No cookies detected in that text — it looks like a single cookie’s value. A login
|
||||
No cookies detected in that text -- it looks like a single cookie’s value. A login
|
||||
needs the whole set: copy the full “cookie:” request-header row (or a cookies.txt /
|
||||
JSON export) exactly as the steps above describe.
|
||||
</span>
|
||||
|
|
@ -344,12 +344,12 @@ function LoginDialogBody({
|
|||
{validation.count} cookie{validation.count === 1 ? '' : 's'} detected, but a
|
||||
working {def.name.split(' / ')[0]} login is still missing:{' '}
|
||||
{validation.missingCritical.join(', ')}. Copy the whole thing again while logged
|
||||
in — a single cookie on its own can’t log you in.
|
||||
in -- a single cookie on its own can’t log you in.
|
||||
</span>
|
||||
) : (
|
||||
<span className="flex items-start gap-1.5">
|
||||
<AlertTriangle className="mt-0.5 size-3 shrink-0" aria-hidden />
|
||||
Only {validation.count} cookie{validation.count === 1 ? '' : 's'} detected — too
|
||||
Only {validation.count} cookie{validation.count === 1 ? '' : 's'} detected -- too
|
||||
few for a saved login. Copy the whole thing (all cookies) as the steps above
|
||||
describe.
|
||||
</span>
|
||||
|
|
@ -396,7 +396,7 @@ function LoginDialogBody({
|
|||
<ShieldCheck className="mt-0.5 size-3.5 shrink-0 text-zinc-400" aria-hidden />
|
||||
Your cookie is encrypted (AES-GCM) with a key that never leaves this browser's key
|
||||
store, and is saved on this computer only. It is sent to this site's server solely
|
||||
to resolve links you play — used transiently, never stored there. “Log out” removes
|
||||
to resolve links you play -- used transiently, never stored there. “Log out” removes
|
||||
it instantly; signing out of YouTube in your browser invalidates it everywhere.
|
||||
</p>
|
||||
</DialogContent>
|
||||
|
|
|
|||
|
|
@ -153,10 +153,6 @@ export function SettingsTab() {
|
|||
<Palette className="size-4 text-emerald-400" aria-hidden />
|
||||
Appearance
|
||||
</h3>
|
||||
<p className="mt-2 text-xs leading-relaxed text-zinc-400">
|
||||
Pick the chrome theme and the highlight color. Saved per visitor in this browser — nothing is
|
||||
stored on the server.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
|
@ -180,7 +176,7 @@ export function SettingsTab() {
|
|||
: 'border-zinc-800 bg-zinc-900/40 hover:border-zinc-700 hover:bg-zinc-800/40',
|
||||
)}
|
||||
>
|
||||
{/* mini preview — static base swatch + live accent chip */}
|
||||
{/* mini preview -- static base swatch + live accent chip */}
|
||||
<div
|
||||
className="h-14 w-full rounded-lg border p-1.5"
|
||||
style={{ background: b.swatch.bg, borderColor: b.swatch.border }}
|
||||
|
|
@ -218,10 +214,6 @@ export function SettingsTab() {
|
|||
<h4 className="text-xs font-semibold uppercase tracking-[0.14em] text-zinc-500">
|
||||
Highlight color
|
||||
</h4>
|
||||
<p className="mt-1.5 text-[11px] leading-relaxed text-zinc-500">
|
||||
Drives buttons, the BPM readout and the beat glow — and the panel outlines of the Black +
|
||||
Purple Outline theme.
|
||||
</p>
|
||||
<div className="mt-3 grid grid-cols-6 gap-1">
|
||||
{ACCENTS.map((a) => {
|
||||
const selected = accent === a.id
|
||||
|
|
@ -270,7 +262,7 @@ export function SettingsTab() {
|
|||
Music services
|
||||
</h4>
|
||||
<p className="mt-1.5 text-[11px] leading-relaxed text-zinc-500">
|
||||
Log in to your own accounts — the Link button then opens your playlists and liked music
|
||||
Log in to your own accounts -- the Link button then opens your playlists and liked music
|
||||
with your account, so you never get stuck behind bot-detection walls. Login cookies are
|
||||
encrypted and stored on this computer only.
|
||||
</p>
|
||||
|
|
@ -278,7 +270,7 @@ export function SettingsTab() {
|
|||
{houseNames.length > 0 && (
|
||||
<p className="mt-2 flex items-start gap-1.5 rounded-md border border-emerald-500/25 bg-emerald-500/10 px-2.5 py-1.5 text-[10px] leading-relaxed text-emerald-300">
|
||||
<Check className="mt-0.5 size-3 shrink-0" aria-hidden />
|
||||
Built-in account active — {houseNames.join(', ')} links play for everyone, no login
|
||||
Built-in account active -- {houseNames.join(', ')} links play for everyone, no login
|
||||
needed. Log in only to reach your own playlists, liked music and uploads.
|
||||
</p>
|
||||
)}
|
||||
|
|
@ -294,7 +286,7 @@ export function SettingsTab() {
|
|||
setChipService(s.id)
|
||||
setLoginOpen(true)
|
||||
}}
|
||||
title={active ? `${s.name} — logged in. Click to manage.` : `${s.name} — click to log in`}
|
||||
title={active ? `${s.name} -- logged in. Click to manage.` : `${s.name} -- click to log in`}
|
||||
className={cn(
|
||||
'flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-[11px] font-medium transition-colors',
|
||||
active
|
||||
|
|
@ -317,7 +309,7 @@ export function SettingsTab() {
|
|||
<Check className="size-3 text-emerald-300" aria-hidden />
|
||||
) : (
|
||||
<span className="text-[9px] text-zinc-600" aria-hidden>
|
||||
—
|
||||
--
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
|
|
@ -360,10 +352,7 @@ export function SettingsTab() {
|
|||
|
||||
<Separator />
|
||||
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<p className="max-w-[60%] text-[11px] leading-snug text-zinc-500">
|
||||
The Native engine scaffold tab is parked and returns when the project nears completion.
|
||||
</p>
|
||||
<div className="flex flex-wrap items-center justify-end gap-3">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ export function ScriptToHashDialog({
|
|||
Script ⇢ Hash
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Your script as ONE shareable string — post it anywhere (chat, social, forums). Anyone
|
||||
Your script as ONE shareable string -- post it anywhere (chat, social, forums). Anyone
|
||||
pastes it back with Hash⇢Script and gets your script exactly as it is now.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
|
@ -130,9 +130,9 @@ export function ScriptToHashDialog({
|
|||
<span className="font-mono text-zinc-300">
|
||||
{SHARE_LEGEND.map((l) => `${l.symbol} = ${l.meaning}`).join(' · ')}
|
||||
</span>
|
||||
) — longer ones additionally pack ~15 bits of script into every
|
||||
) -- longer ones additionally pack ~15 bits of script into every
|
||||
character, which is why they read as dense CJK. Either way the string
|
||||
works even if the script doesn't compile — perfect for asking for
|
||||
works even if the script doesn't compile -- perfect for asking for
|
||||
help or sharing work in progress.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -210,9 +210,9 @@ export function HashToScriptDialog({
|
|||
lines,
|
||||
compiles,
|
||||
compileNote: v.ok
|
||||
? `Compiles OK — mode: ${meta?.mode ?? '?'}`
|
||||
? `Compiles OK -- mode: ${meta?.mode ?? '?'}`
|
||||
: v.error
|
||||
? `Doesn't compile (yet) — [${v.error.section}] line ${v.error.line}: ${v.error.message}`
|
||||
? `Doesn't compile (yet) -- [${v.error.section}] line ${v.error.line}: ${v.error.message}`
|
||||
: "Doesn't compile (yet)",
|
||||
})
|
||||
}
|
||||
|
|
@ -223,7 +223,7 @@ export function HashToScriptDialog({
|
|||
onOpenChange(false)
|
||||
toast({
|
||||
title: 'Script loaded from share string',
|
||||
description: `"${decoded.name ?? 'Untitled'}" — ${decoded.lines} lines in the editor.${
|
||||
description: `"${decoded.name ?? 'Untitled'}" -- ${decoded.lines} lines in the editor.${
|
||||
decoded.compiles ? ' Hit Apply to run it.' : ' Fix the errors, then Apply.'
|
||||
}`,
|
||||
})
|
||||
|
|
@ -238,7 +238,7 @@ export function HashToScriptDialog({
|
|||
Hash ⇢ Script
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Paste a share string someone posted — the script it carries reappears in the editor,
|
||||
Paste a share string someone posted -- the script it carries reappears in the editor,
|
||||
exactly as they wrote it, ready to test or save.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export function VisualStage({ className }: { className?: string }) {
|
|||
{isFullscreen ? <Minimize className="size-4" /> : <Maximize className="size-4" />}
|
||||
</Button>
|
||||
|
||||
{/* idle overlay — pick a source */}
|
||||
{/* idle overlay -- pick a source */}
|
||||
<AnimatePresence>
|
||||
{source === 'idle' && (
|
||||
<motion.div
|
||||
|
|
@ -92,36 +92,39 @@ export function VisualStage({ className }: { className?: string }) {
|
|||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.25 }}
|
||||
className="absolute inset-0 z-20 grid place-items-center bg-zinc-950/60 backdrop-blur-sm"
|
||||
className="absolute inset-0 z-20 flex justify-center overflow-y-auto bg-zinc-950/60 backdrop-blur-sm"
|
||||
>
|
||||
{/* my-auto (not items-center on the parent) — when the card is
|
||||
taller than the stage it scrolls from the top instead of
|
||||
clipping both ends (v7.10: on short phone viewports the stage
|
||||
is ~300 px and the card needs to scroll / compact to fit) */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.96, y: 8 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, ease: 'easeOut' }}
|
||||
className="mx-4 max-w-sm rounded-2xl border border-zinc-800 bg-zinc-900/70 p-6 text-center shadow-2xl backdrop-blur-md sm:p-8"
|
||||
className="my-auto mx-4 max-w-sm rounded-2xl border border-zinc-800 bg-zinc-900/70 p-4 text-center shadow-2xl backdrop-blur-md sm:p-8"
|
||||
>
|
||||
<AudioWaveform className="mx-auto mb-3 size-8 text-emerald-400" aria-hidden />
|
||||
<h2 className="text-lg font-semibold">Select an audio source to begin</h2>
|
||||
<p className="mb-5 mt-1 text-xs text-zinc-500">
|
||||
Demo track, live microphone, your own audio file — or paste a link.
|
||||
</p>
|
||||
<div className="grid gap-2.5">
|
||||
{/* v7.2 showcase entry point — the shimmering Demo Track
|
||||
<AudioWaveform className="mx-auto mb-1.5 size-7 text-emerald-400 sm:mb-3 sm:size-8" aria-hidden />
|
||||
<h2 className="mb-3 mt-0.5 text-base font-semibold sm:mb-5 sm:mt-1 sm:text-lg">
|
||||
Select an audio source to begin
|
||||
</h2>
|
||||
<div className="grid gap-1.5 sm:gap-2.5">
|
||||
{/* v7.2 showcase entry point -- the shimmering Demo Track
|
||||
button: one click starts the music AND the Zai-Magic
|
||||
club mix (random preset every 20 s) */}
|
||||
<Button
|
||||
onClick={() => void startDemo()}
|
||||
className="shimmer-cta h-12 gap-2 bg-emerald-400 text-emerald-950 hover:bg-emerald-300"
|
||||
className="shimmer-cta h-11 gap-2 bg-emerald-400 text-emerald-950 hover:bg-emerald-300 sm:h-12"
|
||||
>
|
||||
<Disc3 className="size-4" /> Demo Track
|
||||
</Button>
|
||||
<Button onClick={() => void startMic()} variant="secondary" className="h-12 gap-2">
|
||||
<Button onClick={() => void startMic()} variant="secondary" className="h-11 gap-2 sm:h-12">
|
||||
<Mic className="size-4" /> Microphone
|
||||
</Button>
|
||||
<Button onClick={() => fileInputRef.current?.click()} variant="secondary" className="h-12 gap-2">
|
||||
<Button onClick={() => fileInputRef.current?.click()} variant="secondary" className="h-11 gap-2 sm:h-12">
|
||||
<FileAudio className="size-4" /> Audio File
|
||||
</Button>
|
||||
<Button onClick={() => openLinkDialog(true)} variant="secondary" className="h-12 gap-2">
|
||||
<Button onClick={() => openLinkDialog(true)} variant="secondary" className="h-11 gap-2 sm:h-12">
|
||||
<Link2 className="size-4" /> Stream a Link
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -23,12 +23,11 @@ import { Sparkles } from 'lucide-react'
|
|||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { RELEASE_NOTES, type ChangeKind, type ReleaseNote } from '@/lib/release-notes'
|
||||
import { APP_SHORT, APP_VERSION } from '@/lib/version'
|
||||
import { APP_VERSION } from '@/lib/version'
|
||||
import { thinScrollbar } from '@/components/ava/shared'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
|
|
@ -136,8 +135,8 @@ export function WhatsNew() {
|
|||
<button
|
||||
type="button"
|
||||
onClick={() => handleOpenChange(true)}
|
||||
aria-label="What's New! — release notes"
|
||||
title="What's New! — everything shipped to OVE, newest first"
|
||||
aria-label="What's New! -- release notes"
|
||||
title="What's New! -- everything shipped to OVE, newest first"
|
||||
className="relative flex h-11 items-center gap-1.5 rounded-lg border border-zinc-800 bg-zinc-900/60 px-3 text-xs font-medium text-zinc-300 transition-colors hover:border-emerald-500/40 hover:text-zinc-100"
|
||||
>
|
||||
<Sparkles className="size-3.5 text-emerald-400" aria-hidden />
|
||||
|
|
@ -152,16 +151,12 @@ export function WhatsNew() {
|
|||
</button>
|
||||
|
||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||
<DialogContent className="max-h-[85vh] sm:max-w-lg">
|
||||
<DialogContent aria-describedby={undefined} className="max-h-[85vh] sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<Sparkles className="size-4 text-emerald-400" aria-hidden />
|
||||
What’s New!
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Every update shipped to {APP_SHORT} — {RELEASE_NOTES.length} releases and
|
||||
counting, newest first.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div
|
||||
className={cn('max-h-[min(60vh,520px)] space-y-5 overflow-y-auto pr-2', thinScrollbar)}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
// AVA — audio input + 3-band spectrum analysis + onset (flux) envelope
|
||||
//
|
||||
// Sources:
|
||||
// demo — the built-in demo TRACK: "Neural Mecha Pulse", a mastered
|
||||
// industrial-EDM banger that exercises the whole spectrum (deep
|
||||
// sub, mid basslines, crisp highs) — the honest end-to-end test
|
||||
// for the beat engine. Plays ONCE through (v7.3 — it is a demo
|
||||
// pass, not a radio station): when the buffer runs out the engine
|
||||
// goes idle and fires onDemoEnded so the UI can unwind the
|
||||
// showcase state and return to the landing overlay.
|
||||
// demo — the built-in demo TRACKS (v7.10): a ten-track collection in
|
||||
// public/demo-tracks/ (demo-01.mp3 … demo-10.mp3, filename
|
||||
// order 1→10). Each plays ONCE through; whoever tears down an
|
||||
// active demo reports WHY via onDemoEnded('ended' | 'stop' |
|
||||
// 'switch') so the UI can decide whether the visitor's place in
|
||||
// the collection advances (natural end + Stop button do, a
|
||||
// source switch keeps the place — audio-source.ts).
|
||||
// mic — live microphone / line-in (club audio feed into an interface)
|
||||
// file — drop any audio file (mp3/wav/…) and loop it
|
||||
// link — remote stream (YouTube / SoundCloud / direct MP3 …) resolved via
|
||||
|
|
@ -28,9 +28,16 @@ const FFT_SIZE = 8192
|
|||
const ATTACK_TAU = 0.035 // seconds
|
||||
const RELEASE_TAU = 0.22 // seconds
|
||||
|
||||
/** The embedded demo track (public/demo-track.mp3). */
|
||||
const DEMO_TRACK_URL = '/demo-track.mp3'
|
||||
const DEMO_TRACK_TITLE = 'Neural Mecha Pulse'
|
||||
/** The embedded demo track collection (public/demo-tracks/), in filename
|
||||
* order 1→10. Only ONE buffer is decoded at a time (~50–60 MB of PCM per
|
||||
* track — caching all ten would be half a gigabyte), so the cache is keyed
|
||||
* to the track index: switching tracks drops the old PCM and decodes the
|
||||
* new one (the HTTP fetch itself stays in the browser cache). */
|
||||
export const DEMO_TRACK_COUNT = 10
|
||||
const demoTrackUrl = (i: number) => `/demo-tracks/demo-${String(i + 1).padStart(2, '0')}.mp3`
|
||||
/** Header-chip / footer label for a demo track (matches the operator's
|
||||
* file naming, minus the redundant "OVE -" prefix). */
|
||||
export const demoTrackTitle = (i: number) => `Demo Track ${i + 1}`
|
||||
|
||||
export class AudioEngine {
|
||||
kind: AudioSourceKind = 'idle'
|
||||
|
|
@ -44,12 +51,15 @@ export class AudioEngine {
|
|||
onTrackEnded: (() => void) | null = null
|
||||
/**
|
||||
* Fired exactly once when the single-pass demo track ends — however it
|
||||
* ends: natural play-through, the Stop button, or switching to another
|
||||
* source (stopSources kills the demo and fires this). The UI hook
|
||||
* (audio-source.ts) unwinds the showcase state — randomize back off —
|
||||
* and returns the visitor to the landing overlay. (v7.3)
|
||||
* ends. The REASON distinguishes the cases (v7.10):
|
||||
* 'ended' — the buffer ran out (natural play-through)
|
||||
* 'stop' — the visitor clicked the Stop button
|
||||
* 'switch' — another source replaced the demo (mic/file/link/demo
|
||||
* restart) — a teardown, not a "finished listening" event
|
||||
* The UI hook (audio-source.ts) advances the visitor's place in the
|
||||
* ten-track collection on 'ended' and 'stop', and keeps it on 'switch'.
|
||||
*/
|
||||
onDemoEnded: (() => void) | null = null
|
||||
onDemoEnded: ((reason: 'ended' | 'stop' | 'switch') => void) | null = null
|
||||
|
||||
private ctx: AudioContext | null = null
|
||||
private analyser: AnalyserNode | null = null
|
||||
|
|
@ -64,8 +74,10 @@ export class AudioEngine {
|
|||
|
||||
private demoSource: AudioBufferSourceNode | null = null
|
||||
private demoBus: GainNode | null = null
|
||||
/** Decoded demo track, cached so restarting Demo is instant. */
|
||||
/** Decoded demo track, cached so re-playing the SAME track is instant
|
||||
* (keyed by index — v7.10). */
|
||||
private demoBuffer: AudioBuffer | null = null
|
||||
private demoBufferIndex = -1
|
||||
/** Previous frame's frequency bytes — the flux (onset) envelope is the
|
||||
* mean positive frame-to-frame change across the spectrum. Null after a
|
||||
* stop/source switch so the first active frame seeds instead of spiking. */
|
||||
|
|
@ -109,7 +121,7 @@ export class AudioEngine {
|
|||
return this.ctx
|
||||
}
|
||||
|
||||
private stopSources(): void {
|
||||
private stopSources(reason: 'ended' | 'stop' | 'switch' = 'switch'): void {
|
||||
const wasDemo = this.kind === 'demo' // the demo retires along with its nodes
|
||||
if (this.demoSource) {
|
||||
try {
|
||||
|
|
@ -151,39 +163,41 @@ export class AudioEngine {
|
|||
this.sourceLabel = null
|
||||
this.levels = { ...ZERO_LEVELS }
|
||||
this.prevFreqData = null // next source seeds the flux baseline cleanly
|
||||
// v7.3: whoever tears down an ACTIVE demo (Stop button, source switch,
|
||||
// natural end via the 'ended' listener below) reports it exactly once —
|
||||
// the UI unwinds the showcase state on this signal.
|
||||
// v7.3/v7.10: whoever tears down an ACTIVE demo (Stop button, source
|
||||
// switch, natural end via the 'ended' listener below) reports it exactly
|
||||
// once, WITH the reason — the UI unwinds the showcase state on this
|
||||
// signal and advances the collection place when the pass truly ended.
|
||||
if (wasDemo && this.onDemoEnded) {
|
||||
const cb = this.onDemoEnded
|
||||
this.onDemoEnded = null
|
||||
cb()
|
||||
cb(reason)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Built-in demo track — "Neural Mecha Pulse" (public/demo-track.mp3), a
|
||||
* mastered industrial-EDM track chosen to exercise the whole engine: deep
|
||||
* sub for the bass bands, driving mid basslines, crisp hats for the highs,
|
||||
* and a kick that genuinely tests the beat detector (dense sustained
|
||||
* sub-bass — the exact case the v7.1 autocorrelation detector was built
|
||||
* for). v7.3: ONE play-through — the demo ends, the engine goes idle and
|
||||
* onDemoEnded fires (see the 'ended' listener). Decoded once, cached.
|
||||
* Built-in demo track — one of the ten mastered recordings in
|
||||
* public/demo-tracks/ (v7.10), chosen by the caller (audio-source.ts
|
||||
* tracks the visitor's place in the collection and passes the index).
|
||||
* ONE play-through: when the buffer runs out the engine goes idle and
|
||||
* onDemoEnded fires with the teardown reason. The decoded buffer is
|
||||
* cached per index so re-playing the same track is instant.
|
||||
*/
|
||||
async startDemo(): Promise<void> {
|
||||
async startDemo(index = 0): Promise<void> {
|
||||
const ctx = this.ensureCtx()
|
||||
await ctx.resume()
|
||||
|
||||
if (!this.demoBuffer) {
|
||||
const res = await fetch(DEMO_TRACK_URL)
|
||||
const track = ((index % DEMO_TRACK_COUNT) + DEMO_TRACK_COUNT) % DEMO_TRACK_COUNT
|
||||
if (this.demoBufferIndex !== track || !this.demoBuffer) {
|
||||
const res = await fetch(demoTrackUrl(track))
|
||||
if (!res.ok) throw new Error(`demo track fetch failed (${res.status})`)
|
||||
const bytes = await res.arrayBuffer()
|
||||
this.demoBuffer = await ctx.decodeAudioData(bytes)
|
||||
this.demoBufferIndex = track
|
||||
}
|
||||
|
||||
this.stopSources()
|
||||
this.stopSources() // 'switch' -- a demo restart is a teardown, not an end
|
||||
this.kind = 'demo'
|
||||
this.sourceLabel = DEMO_TRACK_TITLE
|
||||
this.sourceLabel = demoTrackTitle(track)
|
||||
|
||||
this.demoBus = ctx.createGain()
|
||||
this.demoBus.gain.value = 0.9
|
||||
|
|
@ -199,7 +213,7 @@ export class AudioEngine {
|
|||
// can retire the engine (a replaced source's late 'ended' is ignored).
|
||||
src.addEventListener('ended', () => {
|
||||
if (this.demoSource !== src) return
|
||||
this.stopSources()
|
||||
this.stopSources('ended')
|
||||
})
|
||||
src.connect(this.demoBus)
|
||||
src.start()
|
||||
|
|
@ -218,7 +232,7 @@ export class AudioEngine {
|
|||
this.sourceLabel = null
|
||||
this.micStream = stream
|
||||
this.micSource = ctx.createMediaStreamSource(stream)
|
||||
this.micSource.connect(this.analyser!) // analysis only — no destination
|
||||
this.micSource.connect(this.analyser!) // analysis only -- no destination
|
||||
}
|
||||
|
||||
/** Audio file playback (loops). The file audio is audible. */
|
||||
|
|
@ -276,7 +290,7 @@ export class AudioEngine {
|
|||
}
|
||||
|
||||
stop(): void {
|
||||
this.stopSources()
|
||||
this.stopSources('stop')
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export interface Blueprint {
|
|||
export const BLUEPRINT: Blueprint = {
|
||||
title: 'Rust / Vulkan Native Export',
|
||||
intro:
|
||||
'This web edition is the reference implementation of the AVA engine. The native edition (rust-agent/) shares the architecture and speaks the exact same .ava script language — every preset you write here runs unmodified on the Rust/Vulkan build, and the engine math (band smoothing, beat prediction, expression semantics) was verified value-for-value against this implementation.',
|
||||
'This web edition is the reference implementation of the AVA engine. The native edition (rust-agent/) shares the architecture and speaks the exact same .ava script language -- every preset you write here runs unmodified on the Rust/Vulkan build, and the engine math (band smoothing, beat prediction, expression semantics) was verified value-for-value against this implementation.',
|
||||
downloadNote:
|
||||
'Download the complete cargo project (scaffold + all six presets) as a zip and build it on Linux, Windows or macOS. Button above, or GET /api/rust-scaffold.',
|
||||
sections: [
|
||||
|
|
@ -39,29 +39,29 @@ export const BLUEPRINT: Blueprint = {
|
|||
'One cargo crate, one binary: ava-agent. Every module of the web engine has a native counterpart with the same responsibilities and the same constants:',
|
||||
],
|
||||
bullets: [
|
||||
'src/lib/ava/audio.ts (WebAudio AnalyserNode) ↔ rust src/audio.rs + src/spectrum.rs — cpal capture, ring buffer, rustfft 8192-point FFT, band averaging',
|
||||
'src/lib/ava/beat.ts ↔ rust src/beat.rs — statement-for-statement port: same history/interval/tap constants, same EMA tempo lock, same phase-locked predictor',
|
||||
'src/lib/ava/expression.ts + script.ts ↔ rust src/script/{lexer,parser,env,mod}.rs — the same AVS-eel flavored grammar and the full 39-function set',
|
||||
'src/lib/ava/engine.ts (rAF loop + Canvas2D) ↔ rust src/engine.rs + src/render/* — the same band → beat → [frame] → [beat] → [point] × n pipeline on a wgpu frame loop',
|
||||
'src/lib/ava/presets.ts ↔ rust presets/*.ava — the five scene classics plus the starter template, byte-identical files on both engines',
|
||||
'src/lib/ava/audio.ts (WebAudio AnalyserNode) ↔ rust src/audio.rs + src/spectrum.rs -- cpal capture, ring buffer, rustfft 8192-point FFT, band averaging',
|
||||
'src/lib/ava/beat.ts ↔ rust src/beat.rs -- statement-for-statement port: same history/interval/tap constants, same EMA tempo lock, same phase-locked predictor',
|
||||
'src/lib/ava/expression.ts + script.ts ↔ rust src/script/{lexer,parser,env,mod}.rs -- the same AVS-eel flavored grammar and the full 39-function set',
|
||||
'src/lib/ava/engine.ts (rAF loop + Canvas2D) ↔ rust src/engine.rs + src/render/* -- the same band → beat → [frame] → [beat] → [point] × n pipeline on a wgpu frame loop',
|
||||
'src/lib/ava/presets.ts ↔ rust presets/*.ava -- the five scene classics plus the starter template, byte-identical files on both engines',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Why wgpu (and the Vulkan story)',
|
||||
body: [
|
||||
'The target graphics API is Vulkan. wgpu is the Rust GPU abstraction that speaks native Vulkan on Linux and Windows — and keeps one codebase running everywhere:',
|
||||
'On Linux and Windows the agent requests a Vulkan adapter first; if the machine has no Vulkan loader it falls back to the other primary backends with a warning. On macOS — which has no native Vulkan — wgpu translates to Metal automatically, so the default build just works. For strict Vulkan on macOS, install the Vulkan SDK and build with --features vulkan-force: the agent then requests a genuine Vulkan adapter through MoltenVK instead of Metal.',
|
||||
'The target graphics API is Vulkan. wgpu is the Rust GPU abstraction that speaks native Vulkan on Linux and Windows -- and keeps one codebase running everywhere:',
|
||||
'On Linux and Windows the agent requests a Vulkan adapter first; if the machine has no Vulkan loader it falls back to the other primary backends with a warning. On macOS -- which has no native Vulkan -- wgpu translates to Metal automatically, so the default build just works. For strict Vulkan on macOS, install the Vulkan SDK and build with --features vulkan-force: the agent then requests a genuine Vulkan adapter through MoltenVK instead of Metal.',
|
||||
'One codebase, three platforms, Vulkan-first. The backend is chosen at startup in render/mod.rs (backend_attempts), and the chosen adapter is printed to the console.',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Audio pipeline',
|
||||
body: [
|
||||
'cpal captures the default input device (48 kHz mono preferred, any channel count averaged to mono) on its own callback thread into a lock-guarded ring buffer. Once per rendered frame, AudioProcessor::poll() windows the last 8192 samples, applies a Hann window, runs rustfft, and averages the magnitudes over the user-tunable band ranges — bass 20–100 Hz, mid 700–2000 Hz, high 7000–16000 Hz — with the same fast-attack (tau 35 ms) / slow-release (tau 220 ms) smoothing that produces the *_att variables and feeds the beat detector. Magnitudes are unit-normalized by a fixed calibration constant so band gains and thresholds transfer 1:1 from the web engine.',
|
||||
'cpal captures the default input device (48 kHz mono preferred, any channel count averaged to mono) on its own callback thread into a lock-guarded ring buffer. Once per rendered frame, AudioProcessor::poll() windows the last 8192 samples, applies a Hann window, runs rustfft, and averages the magnitudes over the user-tunable band ranges -- bass 20–100 Hz, mid 700–2000 Hz, high 7000–16000 Hz -- with the same fast-attack (tau 35 ms) / slow-release (tau 220 ms) smoothing that produces the *_att variables and feeds the beat detector. Magnitudes are unit-normalized by a fixed calibration constant so band gains and thresholds transfer 1:1 from the web engine.',
|
||||
],
|
||||
code: [
|
||||
{
|
||||
label: 'rust-agent/src/spectrum.rs — Hz ranges → band levels',
|
||||
label: 'rust-agent/src/spectrum.rs -- Hz ranges → band levels',
|
||||
language: 'rust',
|
||||
content: `/// Calibration: a full-scale sinusoid through the Hann window lands at a
|
||||
/// magnitude of ≈ FFT_SIZE/4 (≈ 2048). Dividing by this constant maps it to
|
||||
|
|
@ -92,11 +92,11 @@ pub fn band_level(mags: &[f32], lo_hz: f32, hi_hz: f32, sample_rate: f32) -> f32
|
|||
{
|
||||
title: 'Beat detection & prediction',
|
||||
body: [
|
||||
'Identical algorithm to the web edition, ported statement for statement into beat.rs. Detection: the smoothed bass must exceed threshold × the rolling 60-frame average, gated by a minimum interval and an absolute floor. Learning: consecutive beat intervals (200–2500 ms) build a median + spread estimate; when the spread is under 0.3 the period locks with an EMA (0.6/0.4 blend) and confidence rises. Prediction: a phase accumulator advances by dt/period every frame — when the bass drops out for longer than period × 1.4, the predictor keeps firing beats on the learned grid (confidence-gated, slowly spending confidence at 0.02 per predicted beat and decaying at 0.06/s) so the visuals never lose the beat. Tap tempo: the Space bar taps into an 8-tap median, re-phasing the predictor and teaching the interval learner.',
|
||||
'Identical algorithm to the web edition, ported statement for statement into beat.rs. Detection: the smoothed bass must exceed threshold × the rolling 60-frame average, gated by a minimum interval and an absolute floor. Learning: consecutive beat intervals (200–2500 ms) build a median + spread estimate; when the spread is under 0.3 the period locks with an EMA (0.6/0.4 blend) and confidence rises. Prediction: a phase accumulator advances by dt/period every frame -- when the bass drops out for longer than period × 1.4, the predictor keeps firing beats on the learned grid (confidence-gated, slowly spending confidence at 0.02 per predicted beat and decaying at 0.06/s) so the visuals never lose the beat. Tap tempo: the Space bar taps into an 8-tap median, re-phasing the predictor and teaching the interval learner.',
|
||||
],
|
||||
code: [
|
||||
{
|
||||
label: 'rust-agent/src/beat.rs — the phase-locked predictor',
|
||||
label: 'rust-agent/src/beat.rs -- the phase-locked predictor',
|
||||
language: 'rust',
|
||||
content: ` // --- predictor (phase-locked grid) -------------------------------------
|
||||
if self.period_ms > 50.0 {
|
||||
|
|
@ -125,26 +125,26 @@ pub fn band_level(mags: &[f32], lo_hz: f32, hi_hz: f32, sample_rate: f32) -> f32
|
|||
{
|
||||
title: 'The script engine',
|
||||
body: [
|
||||
'The .ava format and the expression language are the portability contract — parse once per section, run per frame. Grammar summary (identical to expression.ts):',
|
||||
'The .ava format and the expression language are the portability contract -- parse once per section, run per frame. Grammar summary (identical to expression.ts):',
|
||||
],
|
||||
bullets: [
|
||||
'statements separated by ";" or newlines (newlines inside parens are not separators); comments with # or //',
|
||||
'operators + - * / % ^ (power, right-associative, 2^-3 works), == != < <= > >=, && || ! (short-circuit), ternary',
|
||||
'assignment is an expression and is valid inside call args and ternary branches: if(cond, x = 1, x = 2)',
|
||||
'if(c, a, b) and the ternary are lazy — only the taken branch evaluates (AVS semantics)',
|
||||
'if(c, a, b) and the ternary are lazy -- only the taken branch evaluates (AVS semantics)',
|
||||
'constants pi, tau, e; the full function set: sin cos tan asin acos atan atan2 abs sqrt sqr pow exp log log10 floor ceil round int frac sign min max rand lerp clamp inrange above below equal band bor bnot sigmoid if',
|
||||
'rand(seed) is the same deterministic hash on both engines — sin(x*127.1 + 311.7) * 43758.5453, fractional part — so per-point randomness is stable',
|
||||
'rand(seed) is the same deterministic hash on both engines -- sin(x*127.1 + 311.7) * 43758.5453, fractional part -- so per-point randomness is stable',
|
||||
'sections: [init] once, [frame] per frame, [beat] on beat frames, [point] n times per frame; headers name/author/description/mode/blend/persist/linewidth; errors report section + line',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Rendering',
|
||||
body: [
|
||||
'The Canvas2D renderer maps onto three wgpu pipelines sharing one uniform block (time, dt, bass/mid/treb + _att, vol + _att, beat flash, bpm, beatphase, aspect, resolution, persist): a fullscreen fade pass (persistence trails toward black, alpha = 1 − persist), an audio-reactive background pass (bass → warm amber center glow, treble → neon-green edge shimmer, beat → decaying flash), and the content pass — a line-list or point-list point cloud with per-vertex color and additive blending, the equivalent of the web engine\'s \'lighter\' composite mode. Persistence v0 uses the fade pass; an offscreen feedback texture for true motion trails is the marked next step (TODO(avb) in render/mod.rs).',
|
||||
'The Canvas2D renderer maps onto three wgpu pipelines sharing one uniform block (time, dt, bass/mid/treb + _att, vol + _att, beat flash, bpm, beatphase, aspect, resolution, persist): a fullscreen fade pass (persistence trails toward black, alpha = 1 − persist), an audio-reactive background pass (bass → warm amber center glow, treble → neon-green edge shimmer, beat → decaying flash), and the content pass -- a line-list or point-list point cloud with per-vertex color and additive blending, the equivalent of the web engine\'s \'lighter\' composite mode. Persistence v0 uses the fade pass; an offscreen feedback texture for true motion trails is the marked next step (TODO(avb) in render/mod.rs).',
|
||||
],
|
||||
code: [
|
||||
{
|
||||
label: 'rust-agent/src/render/shader.wgsl — audio-reactive background',
|
||||
label: 'rust-agent/src/render/shader.wgsl -- audio-reactive background',
|
||||
language: 'wgsl',
|
||||
content: `@fragment
|
||||
fn fs_bg(@builtin(position) frag: vec4<f32>) -> @location(0) vec4<f32> {
|
||||
|
|
@ -175,22 +175,22 @@ fn fs_bg(@builtin(position) frag: vec4<f32>) -> @location(0) vec4<f32> {
|
|||
{
|
||||
title: 'Building for each platform',
|
||||
body: [
|
||||
'The scaffold is a single cargo crate with no build scripts — the only platform dependencies are the system audio (ALSA) and Vulkan headers on Linux.',
|
||||
'The scaffold is a single cargo crate with no build scripts -- the only platform dependencies are the system audio (ALSA) and Vulkan headers on Linux.',
|
||||
],
|
||||
code: [
|
||||
{
|
||||
label: 'Linux (Debian / Ubuntu) — native Vulkan',
|
||||
label: 'Linux (Debian / Ubuntu) -- native Vulkan',
|
||||
language: 'bash',
|
||||
content: `sudo apt install libasound2-dev libvulkan-dev
|
||||
cargo run --release -- --preset presets/gap-the-mind.ava`,
|
||||
},
|
||||
{
|
||||
label: 'Windows (VS Build Tools + Rust MSVC) — Vulkan, DX12 fallback',
|
||||
label: 'Windows (VS Build Tools + Rust MSVC) -- Vulkan, DX12 fallback',
|
||||
language: 'powershell',
|
||||
content: `cargo run --release -- --preset presets/gap-the-mind.ava`,
|
||||
},
|
||||
{
|
||||
label: 'macOS — Metal by default, strict Vulkan via MoltenVK',
|
||||
label: 'macOS -- Metal by default, strict Vulkan via MoltenVK',
|
||||
language: 'bash',
|
||||
content: `# default: wgpu auto-selects Metal
|
||||
cargo run --release -- --preset presets/gap-the-mind.ava
|
||||
|
|
@ -204,12 +204,12 @@ cargo run --release --features vulkan-force -- --preset presets/gap-the-mind.ava
|
|||
title: 'Roadmap',
|
||||
body: ['What the scaffold grows into, roughly in order:'],
|
||||
bullets: [
|
||||
'multi-scope composition — AVS-style effect lists with per-effect blend/persist (the [point] scope becomes one effect type among several)',
|
||||
'sprite/Texer-style particles — instanced quad rendering with textures and per-point size (the scaffold\'s point-list pass is the placeholder)',
|
||||
'offscreen feedback trails — render-to-texture ping-pong so persistence becomes a real feedback shader instead of a fade pass',
|
||||
'output to NDI / Syphon — feed club rigs and media servers directly from the native engine',
|
||||
'MIDI / HID controllers — map knobs to band gains, threshold, persist and script parameters',
|
||||
'preset hot-swap on beat — load the next .ava exactly on a beat boundary for seamless transitions',
|
||||
'multi-scope composition -- AVS-style effect lists with per-effect blend/persist (the [point] scope becomes one effect type among several)',
|
||||
'sprite/Texer-style particles -- instanced quad rendering with textures and per-point size (the scaffold\'s point-list pass is the placeholder)',
|
||||
'offscreen feedback trails -- render-to-texture ping-pong so persistence becomes a real feedback shader instead of a fade pass',
|
||||
'output to NDI / Syphon -- feed club rigs and media servers directly from the native engine',
|
||||
'MIDI / HID controllers -- map knobs to band gains, threshold, persist and script parameters',
|
||||
'preset hot-swap on beat -- load the next .ava exactly on a beat boundary for seamless transitions',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@
|
|||
// file, keep that section verbatim.
|
||||
//
|
||||
// EMBEDDED_SEED_VERSION: bump whenever this library is regenerated — the
|
||||
// GET /api/presets route re-seeds the root/embedded subtree when it changes.
|
||||
// GET /api/presets route re-seeds the root/embedded subtree when it changes
|
||||
// (v7.10: em dashes in descriptions/script comments replaced with '--').
|
||||
|
||||
export const EMBEDDED_SEED_VERSION = '7.01'
|
||||
export const EMBEDDED_SEED_VERSION = '7.10'
|
||||
|
||||
export interface EmbeddedPreset {
|
||||
folder: string
|
||||
|
|
@ -42,7 +43,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Retrowall (Yathosho's Supermicrocosm)",
|
||||
author: "Degnic",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Degnic - Retrowall (Yathosho's Supermicrocosm).avs\" by Degnic. The original is driven by DynamicMovement, Movement, Invert, which the script engine cannot run — replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Degnic - Retrowall (Yathosho's Supermicrocosm).avs\" by Degnic. The original is driven by DynamicMovement, Movement, Invert, which the script engine cannot run -- replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Degnic - Retrowall (Yathosho's Supermicrocosm).avs",
|
||||
approx: true,
|
||||
content: "name: \"Retrowall (Yathosho's Supermicrocosm)\"\nmode: dots\nblend: additive\npersist: 0.843\nlinewidth: 2.178\n\n[init]\nrings = 7\nn = rings * 103\n\n[frame]\nt = t + dt * (0.344 + bass_att * 0.6)\nhue = hue + dt * 0.112\nsquash = 0.315 + 0.25 * sin(t * 0.205)\n\n[point]\nring = floor(i * rings)\nri3 = frac(i * rings)\nr0 = 0.16 + ring * 0.142\na = ri3 * 6.28318 + t * (1.2 - ring * 0.18) + ring * 2.4\nx = sin(a) * r0 * (1 + bass * 0.18) / aspect\ny = cos(a) * r0 * squash\nsat = frac(ri3 * 5)\nsize = if(below(sat, 0.14), 3 + bass * 3, 1)\nred = 0.25 + bass * 0.5 + ring * 0.07 * (0.45 + 0.55 * sin(hue * 6.28318 + ring * 1.3))\ngreen = 0.25 + bass * 0.5 + ring * 0.07 * (0.45 + 0.55 * sin(hue * 6.28318 + ring * 1.3 + 2.09))\nblue = 0.25 + bass * 0.5 + ring * 0.07 * (0.45 + 0.55 * sin(hue * 6.28318 + ring * 1.3 + 4.19))\n",
|
||||
|
|
@ -51,7 +52,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Adrealine rush",
|
||||
author: "Degnic",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Degnic-Adrealine rush.avs\" by Degnic. The original is driven by en03: Convolution Filter, Simple, Color Map, which the script engine cannot run — replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Degnic-Adrealine rush.avs\" by Degnic. The original is driven by en03: Convolution Filter, Simple, Color Map, which the script engine cannot run -- replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Degnic-Adrealine rush.avs",
|
||||
approx: true,
|
||||
content: "name: \"Adrealine rush\"\nmode: dots\nblend: additive\npersist: 0.826\nlinewidth: 1.803\n\n[init]\nn = 1287\n\n[frame]\nt = t + dt * 0.304\nhue = hue + dt * 0.11\n\n[point]\nu = rand(i * 1.7) * 2 - 1\nw = rand(i * 3.3 + 11) * 2 - 1\nm = sin((u * 2.681 + w * 5.047 + t) * 3.14159) * sin((u * 6.682 - w * 2.465 - t * 0.7) * 3.14159)\nx = u * 0.907 / aspect\ny = w * 0.875\nlum = max(0, m) * (0.3 + bass * 0.9) + 0.06\nred = lum * 0.3\ngreen = lum * 0.65\nblue = min(1, lum * 1.3)\nsize = 1 + abs(m) * 3.025\n",
|
||||
|
|
@ -60,7 +61,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Alien Heart",
|
||||
author: "Duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Duo - Alien Heart.avs\" by Duo. The original is driven by Fadeout, ClearScreen, MovingParticle, which the script engine cannot run — replaced with a generated \"tunnel\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Duo - Alien Heart.avs\" by Duo. The original is driven by Fadeout, ClearScreen, MovingParticle, which the script engine cannot run -- replaced with a generated \"tunnel\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Duo - Alien Heart.avs",
|
||||
approx: true,
|
||||
content: "name: \"Alien Heart\"\nmode: lines\nblend: additive\npersist: 0.897\nlinewidth: 1.95\n\n[init]\nn = 1015\n\n[frame]\nt = t + dt * (0.377 + bass_att * 1.5)\nhue = hue + dt * 0.038\n\n[point]\nring = floor(i * 29)\nri2 = frac(i * 29)\nz = frac(ring / 29 + t)\nrad = 0.05 + z * 0.917\na = ri2 * 6.28318 + ring * 0.423 + sin(t * 0.7) * 2\nx = sin(a) * rad * (0.55 + sv * 0.656) / aspect\ny = cos(a) * rad * (0.55 + sv * 0.656)\nred = (1 - z) * (0.3 + bass * 0.7) * abs(sin(z * 4.256))\ngreen = (1 - z) * (0.3 + bass * 0.7) * 0.22\nblue = (1 - z) * (0.3 + bass * 0.7) * abs(cos(z * 4.256))\n",
|
||||
|
|
@ -69,7 +70,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Brainstorm",
|
||||
author: "Duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Duo - Brainstorm.avs\" by Duo. The original is driven by Invert, UniqueTone, Brightness, which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Duo - Brainstorm.avs\" by Duo. The original is driven by Invert, UniqueTone, Brightness, which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Duo - Brainstorm.avs",
|
||||
approx: true,
|
||||
content: "name: \"Brainstorm\"\nmode: lines\nblend: additive\npersist: 0.859\nlinewidth: 2.309\n\n[init]\nsegs = 6\nn = 584\n\n[frame]\nrot = rot + dt * (0.093 + mid_att * 0.5)\nhue = hue + dt * 0.084\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 9 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + amp * 1.3 * 0.85\ngreen = 0.3 + amp * 1.3 * 0.92\nblue = 0.3 + amp * 1.3\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -78,7 +79,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Molecules (S_KuPeRS Remix)",
|
||||
author: "EL-VIS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"EL-VIS - Molecules (S_KuPeRS Remix).avs\" by EL-VIS. The original is driven by DynamicMovement, Color Map, Invert, which the script engine cannot run — replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"EL-VIS - Molecules (S_KuPeRS Remix).avs\" by EL-VIS. The original is driven by DynamicMovement, Color Map, Invert, which the script engine cannot run -- replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/EL-VIS - Molecules (S_KuPeRS Remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"Molecules (S_KuPeRS Remix)\"\nmode: lines\nblend: additive\npersist: 0.88\nlinewidth: 1.388\n\n[init]\nn = 1119\n\n[frame]\nt = t + dt * (0.211 + bass_att * 1.8)\nhue = hue + dt * 0.042 + beat * 0.012\n\n[point]\narm = floor(i * 3)\nfa = frac(i * 3)\nd = fa\nang = arm * 1.551 + d * 1.047 * 3.14159 + t\nrad = (0.04 + pow(d, 1.714) * 1.15) * (0.7 + bass * 0.5)\nx = sin(ang) * rad / aspect\ny = cos(ang) * rad\nred = (0.3 + 0.7 * d) * (0.3 + mid) * abs(sin(d * 2.325))\ngreen = (0.3 + 0.7 * d) * (0.3 + mid) * 0.22\nblue = (0.3 + 0.7 * d) * (0.3 + mid) * abs(cos(d * 2.325))\nskip = if(below(fa, 0.04), 1, 0)\n",
|
||||
|
|
@ -87,7 +88,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Take the Veil",
|
||||
author: "L1quid",
|
||||
description: "Auto-ported from the Winamp AVS preset \"L1quid - Take the Veil.avs\" by L1quid. The original is driven by unportable scope code (frame line 15: Unexpected character '$'), which the script engine cannot run — replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"L1quid - Take the Veil.avs\" by L1quid. The original is driven by unportable scope code (frame line 15: Unexpected character '$'), which the script engine cannot run -- replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/L1quid - Take the Veil.avs",
|
||||
approx: true,
|
||||
content: "name: \"Take the Veil\"\nmode: lines\nblend: additive\npersist: 0.895\nlinewidth: 1.78\n\n[init]\nn = 674\n\n[frame]\nt = t + dt * 0.275\nhue = hue + dt * 0.052\n\n[point]\nph = i * 6.28318 * 1.521\nfa = 3 + mid * 0.35\nfb = 6 + bass * 0.45\nx = sin(ph * fa + t) * (0.5 + bass * 0.3) / aspect\ny = sin(ph * fb + t * 1.3 + 0.957) * (0.5 + treb * 0.35)\nred = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * (0.25 + bass * 0.95)\ngreen = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * (0.25 + mid * 0.95)\nblue = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * (0.25 + treb * 0.95)\n",
|
||||
|
|
@ -105,7 +106,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "...hidden track...",
|
||||
author: "S_KuPeRS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - ...hidden track....avs\" by S_KuPeRS. The original is driven by DynamicMovement, Color Map, which the script engine cannot run — replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - ...hidden track....avs\" by S_KuPeRS. The original is driven by DynamicMovement, Color Map, which the script engine cannot run -- replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/S_KuPeRS - ...hidden track....avs",
|
||||
approx: true,
|
||||
content: "name: \"...hidden track...\"\nmode: lines\nblend: additive\npersist: 0.805\nlinewidth: 2.555\n\n[init]\nn = 205\n\n[frame]\nhue = hue + dt * 0.045 + beat * 0.01\ntravel = travel + dt * (0.253 + bass_att * 1.4)\nflash = flash * 0.86\n\n[beat]\nflash = 1\n\n[point]\ng = floor(i * 5)\ngi = frac(i * 5)\nph = frac(rand(g * 5.1 + 1) + travel * (0.55 + rand(g + 17) * 0.85))\na = gi * 6.28318\nrad = ph * (0.232 + bass * 0.659 + flash * 0.08)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nfade = sin(ph * 3.14159)\nred = min(1, fade * (0.35 + flash * 0.4) * 1.3)\ngreen = fade * (0.35 + flash * 0.4) * 0.5\nblue = fade * (0.35 + flash * 0.4) * 0.12\nskip = if(above(ph, 0.96), 1, 0)\n",
|
||||
|
|
@ -114,7 +115,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Arctic Rainbow",
|
||||
author: "S_KuPeRS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Arctic Rainbow.avs\" by S_KuPeRS. The original is driven by BlitterFeedback, DynamicMovement, Movement, which the script engine cannot run — replaced with a generated \"rain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Arctic Rainbow.avs\" by S_KuPeRS. The original is driven by BlitterFeedback, DynamicMovement, Movement, which the script engine cannot run -- replaced with a generated \"rain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/S_KuPeRS - Arctic Rainbow.avs",
|
||||
approx: true,
|
||||
content: "name: \"Arctic Rainbow\"\nmode: dots\nblend: additive\npersist: 0.789\nlinewidth: 1.877\n\n[init]\ncols = 48\nn = 918\n\n[frame]\nfall = fall + dt * (0.855 + vol_att * 1.119)\nhue = hue + dt * 0.034\n\n[point]\ncol = floor(i * cols)\nci = frac(i * cols)\nxx = (col / cols - 0.5) * 1.9\nyf = frac(rand(col * 3.7 + 1) + fall * (0.55 + rand(col + 5) * 0.5))\ntail = rand(col * 1.3 + 9) * 0.297 + 0.04\nyy = (yf * 2 - 1) * 1.05 + ci * tail\nx = xx / aspect\ny = yy\nred = (1 - ci) * (0.2 + treb * 0.85) + 0.04 * 0.85\ngreen = (1 - ci) * (0.2 + treb * 0.85) + 0.04 * 0.92\nblue = (1 - ci) * (0.2 + treb * 0.85) + 0.04\nskip = if(above(abs(yy), 1.02), 1, 0)\n",
|
||||
|
|
@ -123,7 +124,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Chinook",
|
||||
author: "S_KuPeRS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Chinook.avs\" by S_KuPeRS. The original is driven by ColorClip, ClearScreen, DynamicMovement, which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Chinook.avs\" by S_KuPeRS. The original is driven by ColorClip, ClearScreen, DynamicMovement, which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/S_KuPeRS - Chinook.avs",
|
||||
approx: true,
|
||||
content: "name: \"Chinook\"\nmode: dots\nblend: additive\npersist: 0.831\nlinewidth: 2.299\n\n[init]\nbars = 30\nn = bars * 9\n\n[frame]\nrot = rot + dt * (0.07 + mid * 0.3)\nhue = hue + dt * 0.106\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.893\na = bar * 6.28318 / bars + rot\nrad = 0.142 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.25 + bi * 0.75 * 0.3\ngreen = 0.25 + bi * 0.75 * 0.65\nblue = min(1, 0.25 + bi * 0.75 * 1.3)\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -132,7 +133,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Hexual Healing",
|
||||
author: "S_KuPeRS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Hexual Healing.avs\" by S_KuPeRS. The original is driven by Color Map, which the script engine cannot run — replaced with a generated \"lattice\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Hexual Healing.avs\" by S_KuPeRS. The original is driven by Color Map, which the script engine cannot run -- replaced with a generated \"lattice\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/S_KuPeRS - Hexual Healing.avs",
|
||||
approx: true,
|
||||
content: "name: \"Hexual Healing\"\nmode: dots\nblend: additive\npersist: 0.785\nlinewidth: 2.432\n\n[init]\ncols = 34\nn = cols * cols\n\n[frame]\nrot = rot + dt * (0.072 + mid * 0.4)\nhue = hue + dt * 0.062\n\n[point]\ncx = floor(i * cols) / (cols - 1)\ncy = frac(i * cols)\nh = sv * 0.506\nux = (cx - 0.5) * 1.674\nuy = (cy - 0.5) * 1.674\nrx = ux * cos(rot) - uy * sin(rot)\nry = ux * sin(rot) + uy * cos(rot)\nx = (rx / aspect) * (1 - h * 0.7)\ny = ry * (1 - h * 0.7)\nred = min(1, 0.22 + h * 2.2 * 1.3)\ngreen = 0.22 + h * 2.2 * 0.5\nblue = 0.22 + h * 2.2 * 0.12\nsize = 1.2 + h * 5\n",
|
||||
|
|
@ -141,7 +142,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Inverse Kinetics",
|
||||
author: "S_KuPeRS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Inverse Kinetics.avs\" by S_KuPeRS. The original is driven by effect#2176, DynamicMovement, which the script engine cannot run — replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Inverse Kinetics.avs\" by S_KuPeRS. The original is driven by effect#2176, DynamicMovement, which the script engine cannot run -- replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/S_KuPeRS - Inverse Kinetics.avs",
|
||||
approx: true,
|
||||
content: "name: \"Inverse Kinetics\"\nmode: dots\nblend: additive\npersist: 0.805\nlinewidth: 2.613\n\n[init]\nn = 817\n\n[frame]\ntt = tt + dt * (0.5 + bass_att * 1.1)\nhue = hue + dt * 0.103\nburst = burst * 0.9\n\n[beat]\nburst = 1\n\n[point]\njet = floor(i * 2)\nlife = frac(rand(i * 7.7 + jet) + tt * (0.35 + rand(i + 3) * 0.65))\na = jet * 6.28318 / 2 + rand(i * 5.1 + jet) * 0.736\nspd = 0.4 + rand(i * 9.2 + jet) * 0.8\npx = cos(a) * spd * life\npy = sin(a) * spd * life - 1.2 * life * life\nx = px * (0.85 + bass * 0.35) / aspect\ny = py\nred = max(0, 1 - life) * (0.35 + burst * 0.55) * abs(sin(life * 4))\ngreen = max(0, 1 - life) * (0.35 + burst * 0.55) * 0.22\nblue = max(0, 1 - life) * (0.35 + burst * 0.55) * abs(cos(life * 4))\nskip = if(above(life, 0.94), 1, 0)\n",
|
||||
|
|
@ -150,7 +151,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Kingish",
|
||||
author: "S_KuPeRS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Kingish.avs\" by S_KuPeRS. The original is driven by BlitterFeedback, which the script engine cannot run — replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Kingish.avs\" by S_KuPeRS. The original is driven by BlitterFeedback, which the script engine cannot run -- replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/S_KuPeRS - Kingish.avs",
|
||||
approx: true,
|
||||
content: "name: \"Kingish\"\nmode: dots\nblend: additive\npersist: 0.813\nlinewidth: 2.025\n\n[init]\nspokes = 27\nn = spokes * 22\n\n[frame]\nrot = rot + dt * (0.102 + mid * 0.4)\nt = t + dt * 2.987\nhue = hue + dt * 0.075\n\n[point]\nsp = floor(i * spokes)\nsi = frac(i * spokes)\na = sp * 6.28318 / spokes + rot\nwave = sin(si * 2 * 3.14159 - t) * (0.03 + bass * 0.28)\nrad = 0.12 + si * 0.92 + wave\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = (1 - si) * 0.45 + 0.15 + sv * 0.55 * abs(sin(sp * 0.4))\ngreen = (1 - si) * 0.45 + 0.15 + sv * 0.55 * 0.22\nblue = (1 - si) * 0.45 + 0.15 + sv * 0.55 * abs(cos(sp * 0.4))\nskip = if(above(si, 0.985), 1, 0)\n",
|
||||
|
|
@ -159,7 +160,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Spirit Realm (Degnic's Plasmoid RMX)",
|
||||
author: "S_KuPeRS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Spirit Realm (Degnic's Plasmoid RMX).avs\" by S_KuPeRS. The original is driven by BlitterFeedback, \u0005, DotPlane, which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Spirit Realm (Degnic's Plasmoid RMX).avs\" by S_KuPeRS. The original is driven by BlitterFeedback, \u0005, DotPlane, which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/S_KuPeRS - Spirit Realm (Degnic's Plasmoid RMX).avs",
|
||||
approx: true,
|
||||
content: "name: \"Spirit Realm (Degnic's Plasmoid RMX)\"\nmode: lines\nblend: additive\npersist: 0.885\nlinewidth: 2.389\n\n[init]\nn = 1199\n\n[frame]\nt = t + dt * (0.344 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.085\n\n[point]\na = i * 6.28318 * 2\nwob = sin(a * 3 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.422 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5))\ngreen = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5 + 2.09))\nblue = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5 + 4.19))\n",
|
||||
|
|
@ -177,7 +178,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Upward Current",
|
||||
author: "S_KuPeRS",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Upward Current.avs\" by S_KuPeRS. The original is driven by CustomBPM, DynamicMovement, Water, which the script engine cannot run — replaced with a generated \"rose\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"S_KuPeRS - Upward Current.avs\" by S_KuPeRS. The original is driven by CustomBPM, DynamicMovement, Water, which the script engine cannot run -- replaced with a generated \"rose\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/S_KuPeRS - Upward Current.avs",
|
||||
approx: true,
|
||||
content: "name: \"Upward Current\"\nmode: lines\nblend: additive\npersist: 0.914\nlinewidth: 1.629\n\n[init]\nn = 869\n\n[frame]\nt = t + dt * (0.134 + mid * 0.5)\nhue = hue + dt * 0.122\nflash = flash * 0.87\n\n[beat]\nflash = 1\n\n[point]\nth = i * 6.28318 * 2 + t\nr = abs(cos(2 * th + bass * 0.656))\nrad = r * (0.5 + bass * 0.3 + sv * 0.2 + flash * 0.08)\nx = sin(th) * rad / aspect\ny = cos(th) * rad\nred = 0.25 + 0.65 * r + v * 0.25 * abs(sin(th * 0.5))\ngreen = 0.25 + 0.65 * r + v * 0.25 * 0.22\nblue = 0.25 + 0.65 * r + v * 0.25 * abs(cos(th * 0.5))\n",
|
||||
|
|
@ -186,7 +187,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Aqua-fumes",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Aqua-fumes.avs\" by Tuggummi. The original is driven by Holden03: Convolution Filter, Color Map, Bump, which the script engine cannot run — replaced with a generated \"starfield\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Aqua-fumes.avs\" by Tuggummi. The original is driven by Holden03: Convolution Filter, Color Map, Bump, which the script engine cannot run -- replaced with a generated \"starfield\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Aqua-fumes.avs",
|
||||
approx: true,
|
||||
content: "name: \"Aqua-fumes\"\nmode: dots\nblend: additive\npersist: 0.787\nlinewidth: 2.043\n\n[init]\nn = 966\n\n[frame]\ntravel = travel + dt * (0.347 + vol_att * 1.816)\nhue = hue + dt * 0.076\n\n[point]\na = rand(i * 7.3) * 6.28318\nz = frac(rand(i * 3.1 + 5) + travel * (0.5 + rand(i + 9) * 0.7))\nrad = z * z * 1.075\nx = sin(a) * rad / aspect\ny = cos(a) * rad\ntw = 0.4 + 0.6 * sin(z * 40 + time * 3) * (0.5 + treb)\nred = tw * abs(sin(i * 3.959))\ngreen = tw * 0.22\nblue = tw * abs(cos(i * 3.959))\nsize = 1 + z * 3 * (0.5 + bass)\nskip = if(above(z, 0.97), 1, 0)\n",
|
||||
|
|
@ -195,7 +196,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Club Seizure (color enhanced mix)",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Club Seizure (color enhanced mix).avs\" by Tuggummi. The original is driven by Movement, DynamicMovement, Multiplier, which the script engine cannot run — replaced with a generated \"helix\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Club Seizure (color enhanced mix).avs\" by Tuggummi. The original is driven by Movement, DynamicMovement, Multiplier, which the script engine cannot run -- replaced with a generated \"helix\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Club Seizure (color enhanced mix).avs",
|
||||
approx: true,
|
||||
content: "name: \"Club Seizure (color enhanced mix)\"\nmode: lines\nblend: additive\npersist: 0.864\nlinewidth: 2.379\n\n[init]\nn = 946\n\n[frame]\nt = t + dt * (0.322 + bass_att * 0.9)\nhue = hue + dt * 0.089\nflash = flash * 0.86\n\n[beat]\nflash = 1\n\n[point]\nst = floor(i * 2)\nsi = frac(i * 2)\ns = si * 6 * 6.28318 + t\nph = st * 3.14159\nrad = (0.28 + bass * 0.32 + flash * 0.06) * (0.55 + 0.45 * (cos(s + ph) * 0.5 + 0.5))\nx = sin(s + ph) * rad / aspect\ny = (si - 0.5) * 1.8\nred = 0.25 + 0.55 * (cos(s + ph) * 0.5 + 0.5) + treb * 0.25 * (0.45 + 0.55 * sin(hue * 6.28318 + s * 0.3))\ngreen = 0.25 + 0.55 * (cos(s + ph) * 0.5 + 0.5) + treb * 0.25 * (0.45 + 0.55 * sin(hue * 6.28318 + s * 0.3 + 2.09))\nblue = 0.25 + 0.55 * (cos(s + ph) * 0.5 + 0.5) + treb * 0.25 * (0.45 + 0.55 * sin(hue * 6.28318 + s * 0.3 + 4.19))\n",
|
||||
|
|
@ -204,7 +205,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Electro blobs",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Electro blobs.avs\" by Tuggummi. The original is driven by MovingParticle, Color Map, BlitterFeedback, which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Electro blobs.avs\" by Tuggummi. The original is driven by MovingParticle, Color Map, BlitterFeedback, which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Electro blobs.avs",
|
||||
approx: true,
|
||||
content: "name: \"Electro blobs\"\nmode: lines\nblend: additive\npersist: 0.866\nlinewidth: 1.536\n\n[init]\nsegs = 12\nn = 616\n\n[frame]\nrot = rot + dt * (0.085 + mid_att * 0.5)\nhue = hue + dt * 0.131\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 5 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + amp * 1.3 * 0.85\ngreen = 0.3 + amp * 1.3 * 0.92\nblue = 0.3 + amp * 1.3\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -213,7 +214,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Kaleidofied",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Kaleidofied.avs\" by Tuggummi. The original is driven by Invert, Movement, Bump, which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Kaleidofied.avs\" by Tuggummi. The original is driven by Invert, Movement, Bump, which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Kaleidofied.avs",
|
||||
approx: true,
|
||||
content: "name: \"Kaleidofied\"\nmode: lines\nblend: additive\npersist: 0.885\nlinewidth: 1.542\n\n[init]\nn = 1126\n\n[frame]\nt = t + dt * (0.589 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.1\n\n[point]\na = i * 6.28318 * 1\nwob = sin(a * 3 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.232 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5))\ngreen = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5 + 2.09))\nblue = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5 + 4.19))\n",
|
||||
|
|
@ -222,7 +223,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Magma Flow II",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Magma Flow II.avs\" by Tuggummi. The original is driven by Color Map, BufferSave, ClearScreen, which the script engine cannot run — replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Magma Flow II.avs\" by Tuggummi. The original is driven by Color Map, BufferSave, ClearScreen, which the script engine cannot run -- replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Magma Flow II.avs",
|
||||
approx: true,
|
||||
content: "name: \"Magma Flow II\"\nmode: dots\nblend: additive\npersist: 0.804\nlinewidth: 2.633\n\n[init]\nrings = 3\nn = rings * 104\n\n[frame]\nt = t + dt * (0.258 + bass_att * 0.6)\nhue = hue + dt * 0.036\nsquash = 0.387 + 0.25 * sin(t * 0.203)\n\n[point]\nring = floor(i * rings)\nri3 = frac(i * rings)\nr0 = 0.16 + ring * 0.148\na = ri3 * 6.28318 + t * (1.2 - ring * 0.18) + ring * 2.4\nx = sin(a) * r0 * (1 + bass * 0.18) / aspect\ny = cos(a) * r0 * squash\nsat = frac(ri3 * 5)\nsize = if(below(sat, 0.14), 3 + bass * 3, 1)\nred = 0.25 + bass * 0.5 + ring * 0.07 * abs(sin(ring * 1.3))\ngreen = 0.25 + bass * 0.5 + ring * 0.07 * 0.22\nblue = 0.25 + bass * 0.5 + ring * 0.07 * abs(cos(ring * 1.3))\n",
|
||||
|
|
@ -231,7 +232,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Multiple Orgasms",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Multiple Orgasms.avs\" by Tuggummi. The original is driven by Movement, Color Map, BufferSave, which the script engine cannot run — replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Multiple Orgasms.avs\" by Tuggummi. The original is driven by Movement, Color Map, BufferSave, which the script engine cannot run -- replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Multiple Orgasms.avs",
|
||||
approx: true,
|
||||
content: "name: \"Multiple Orgasms\"\nmode: lines\nblend: additive\npersist: 0.873\nlinewidth: 1.6\n\n[init]\nspokes = 30\nn = spokes * 33\n\n[frame]\nrot = rot + dt * (0.106 + mid * 0.4)\nt = t + dt * 2.164\nhue = hue + dt * 0.106\n\n[point]\nsp = floor(i * spokes)\nsi = frac(i * spokes)\na = sp * 6.28318 / spokes + rot\nwave = sin(si * 4 * 3.14159 - t) * (0.03 + bass * 0.28)\nrad = 0.12 + si * 0.919 + wave\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = (1 - si) * 0.45 + 0.15 + sv * 0.55 * (0.45 + 0.55 * sin(hue * 6.28318 + sp * 0.4))\ngreen = (1 - si) * 0.45 + 0.15 + sv * 0.55 * (0.45 + 0.55 * sin(hue * 6.28318 + sp * 0.4 + 2.09))\nblue = (1 - si) * 0.45 + 0.15 + sv * 0.55 * (0.45 + 0.55 * sin(hue * 6.28318 + sp * 0.4 + 4.19))\nskip = if(above(si, 0.985), 1, 0)\n",
|
||||
|
|
@ -240,7 +241,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Pina Colada",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Pina Colada.avs\" by Tuggummi. The original is driven by Color Map, which the script engine cannot run — replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Pina Colada.avs\" by Tuggummi. The original is driven by Color Map, which the script engine cannot run -- replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Pina Colada.avs",
|
||||
approx: true,
|
||||
content: "name: \"Pina Colada\"\nmode: lines\nblend: additive\npersist: 0.887\nlinewidth: 1.779\n\n[init]\nn = 943\n\n[frame]\nt = t + dt * (0.219 + bass_att * 1.8)\nhue = hue + dt * 0.098 + beat * 0.012\n\n[point]\narm = floor(i * 8)\nfa = frac(i * 8)\nd = fa\nang = arm * 1.519 + d * 1.263 * 3.14159 + t\nrad = (0.04 + pow(d, 2.354) * 1.15) * (0.7 + bass * 0.5)\nx = sin(ang) * rad / aspect\ny = cos(ang) * rad\nred = (0.3 + 0.7 * d) * (0.3 + mid) * (0.25 + bass * 0.95)\ngreen = (0.3 + 0.7 * d) * (0.3 + mid) * (0.25 + mid * 0.95)\nblue = (0.3 + 0.7 * d) * (0.3 + mid) * (0.25 + treb * 0.95)\nskip = if(below(fa, 0.04), 1, 0)\n",
|
||||
|
|
@ -249,7 +250,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Scope in Spotlight II",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Scope in Spotlight II.avs\" by Tuggummi. The original is driven by effect#117, Color Map, Invert, which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Scope in Spotlight II.avs\" by Tuggummi. The original is driven by effect#117, Color Map, Invert, which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Scope in Spotlight II.avs",
|
||||
approx: true,
|
||||
content: "name: \"Scope in Spotlight II\"\nmode: lines\nblend: additive\npersist: 0.854\nlinewidth: 2.056\n\n[init]\nsegs = 7\nn = 462\n\n[frame]\nrot = rot + dt * (0.107 + mid_att * 0.5)\nhue = hue + dt * 0.035\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 4 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = min(1, 0.3 + amp * 1.3 * 1.3)\ngreen = 0.3 + amp * 1.3 * 0.5\nblue = 0.3 + amp * 1.3 * 0.12\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -258,7 +259,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Solero Shots",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Solero Shots.avs\" by Tuggummi. The original is driven by effect#28, FastBright, Movement, which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Solero Shots.avs\" by Tuggummi. The original is driven by effect#28, FastBright, Movement, which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Solero Shots.avs",
|
||||
approx: true,
|
||||
content: "name: \"Solero Shots\"\nmode: lines\nblend: additive\npersist: 0.878\nlinewidth: 2.226\n\n[init]\nbars = 40\nn = bars * 12\n\n[frame]\nrot = rot + dt * (0.078 + mid * 0.3)\nhue = hue + dt * 0.032\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.813\na = bar * 6.28318 / bars + rot\nrad = 0.218 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.25 + bi * 0.75 * 0.3\ngreen = 0.25 + bi * 0.75 * 0.65\nblue = min(1, 0.25 + bi * 0.75 * 1.3)\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -267,7 +268,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Square Minded",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Square Minded.avs\" by Tuggummi. The original is driven by FastBright, which the script engine cannot run — replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Square Minded.avs\" by Tuggummi. The original is driven by FastBright, which the script engine cannot run -- replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Square Minded.avs",
|
||||
approx: true,
|
||||
content: "name: \"Square Minded\"\nmode: dots\nblend: additive\npersist: 0.783\nlinewidth: 2.696\n\n[init]\nn = 1492\n\n[frame]\nt = t + dt * 0.656\nhue = hue + dt * 0.13\n\n[point]\nu = rand(i * 1.7) * 2 - 1\nw = rand(i * 3.3 + 11) * 2 - 1\nm = sin((u * 3.356 + w * 3.959 + t) * 3.14159) * sin((u * 3.01 - w * 6.626 - t * 0.7) * 3.14159)\nx = u * 0.994 / aspect\ny = w * 0.856\nlum = max(0, m) * (0.3 + bass * 0.9) + 0.06\nred = lum * 0.85\ngreen = lum * 0.92\nblue = lum\nsize = 1 + abs(m) * 3.211\n",
|
||||
|
|
@ -276,7 +277,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Worm-O-Rama (Raz Remix)",
|
||||
author: "Tuggummi",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Worm-O-Rama (Raz Remix).avs\" by Tuggummi. The original is driven by MovingParticle, Filter, Simple, which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"Tuggummi - Worm-O-Rama (Raz Remix).avs\" by Tuggummi. The original is driven by MovingParticle, Filter, Simple, which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/Tuggummi - Worm-O-Rama (Raz Remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"Worm-O-Rama (Raz Remix)\"\nmode: lines\nblend: additive\npersist: 0.894\nlinewidth: 1.933\n\n[init]\nn = 1189\n\n[frame]\nt = t + dt * (0.418 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.102\n\n[point]\na = i * 6.28318 * 3\nwob = sin(a * 3 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.282 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + abs(v) * 1.2 * (0.25 + bass * 0.95)\ngreen = 0.3 + abs(v) * 1.2 * (0.25 + mid * 0.95)\nblue = 0.3 + abs(v) * 1.2 * (0.25 + treb * 0.95)\n",
|
||||
|
|
@ -294,7 +295,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Cartoon Trip",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Cartoon Trip.avs\" by UnConeD. The original is driven by DynamicMovement, FastBright, Color Reduction, which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Cartoon Trip.avs\" by UnConeD. The original is driven by DynamicMovement, FastBright, Color Reduction, which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Cartoon Trip.avs",
|
||||
approx: true,
|
||||
content: "name: \"Cartoon Trip\"\nmode: lines\nblend: additive\npersist: 0.831\nlinewidth: 2.55\n\n[init]\nbars = 39\nn = bars * 9\n\n[frame]\nrot = rot + dt * (0.116 + mid * 0.3)\nhue = hue + dt * 0.112\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.83\na = bar * 6.28318 / bars + rot\nrad = 0.189 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.25 + bi * 0.75 * 0.85\ngreen = 0.25 + bi * 0.75 * 0.92\nblue = 0.25 + bi * 0.75\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -303,7 +304,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Containment",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Containment.avs\" by UnConeD. The original is driven by unportable scope code (init line 12: Unexpected character '£'), which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Containment.avs\" by UnConeD. The original is driven by unportable scope code (init line 12: Unexpected character '£'), which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Containment.avs",
|
||||
approx: true,
|
||||
content: "name: \"Containment\"\nmode: lines\nblend: additive\npersist: 0.935\nlinewidth: 1.8\n\n[init]\nn = 847\n\n[frame]\nt = t + dt * (0.436 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.071\n\n[point]\na = i * 6.28318 * 2\nwob = sin(a * 2 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.25 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = min(1, 0.3 + abs(v) * 1.2 * 1.3)\ngreen = 0.3 + abs(v) * 1.2 * 0.5\nblue = 0.3 + abs(v) * 1.2 * 0.12\n",
|
||||
|
|
@ -321,7 +322,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Jello Cube",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Jello Cube.avs\" by UnConeD. The original is driven by Color Map, which the script engine cannot run — replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Jello Cube.avs\" by UnConeD. The original is driven by Color Map, which the script engine cannot run -- replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Jello Cube.avs",
|
||||
approx: true,
|
||||
content: "name: \"Jello Cube\"\nmode: lines\nblend: additive\npersist: 0.813\nlinewidth: 2.201\n\n[init]\nn = 620\n\n[frame]\nhue = hue + dt * 0.073 + beat * 0.01\ntravel = travel + dt * (0.196 + bass_att * 1.4)\nflash = flash * 0.86\n\n[beat]\nflash = 1\n\n[point]\ng = floor(i * 10)\ngi = frac(i * 10)\nph = frac(rand(g * 5.1 + 1) + travel * (0.55 + rand(g + 17) * 0.85))\na = gi * 6.28318\nrad = ph * (0.226 + bass * 0.743 + flash * 0.08)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nfade = sin(ph * 3.14159)\nred = fade * (0.35 + flash * 0.4) * abs(sin(g * 0.7))\ngreen = fade * (0.35 + flash * 0.4) * 0.22\nblue = fade * (0.35 + flash * 0.4) * abs(cos(g * 0.7))\nskip = if(above(ph, 0.96), 1, 0)\n",
|
||||
|
|
@ -330,7 +331,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Mercury",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Mercury.avs\" by UnConeD. The original is driven by Blur, DynamicMovement, FastBright, which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Mercury.avs\" by UnConeD. The original is driven by Blur, DynamicMovement, FastBright, which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Mercury.avs",
|
||||
approx: true,
|
||||
content: "name: \"Mercury\"\nmode: lines\nblend: additive\npersist: 0.888\nlinewidth: 1.97\n\n[init]\nn = 1109\n\n[frame]\nt = t + dt * (0.329 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.097\n\n[point]\na = i * 6.28318 * 3\nwob = sin(a * 6 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.31 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + abs(v) * 1.2 * 0.3\ngreen = 0.3 + abs(v) * 1.2 * 0.65\nblue = min(1, 0.3 + abs(v) * 1.2 * 1.3)\n",
|
||||
|
|
@ -339,7 +340,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Neon Coaster",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Neon Coaster.avs\" by UnConeD. The original is driven by unportable scope code (beat line 18: Unexpected character '¤'), which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Neon Coaster.avs\" by UnConeD. The original is driven by unportable scope code (beat line 18: Unexpected character '¤'), which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Neon Coaster.avs",
|
||||
approx: true,
|
||||
content: "name: \"Neon Coaster\"\nmode: dots\nblend: additive\npersist: 0.897\nlinewidth: 2.488\n\n[init]\nbars = 33\nn = bars * 12\n\n[frame]\nrot = rot + dt * (0.092 + mid * 0.3)\nhue = hue + dt * 0.066\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.765\na = bar * 6.28318 / bars + rot\nrad = 0.193 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = min(1, 0.25 + bi * 0.75 * 1.3)\ngreen = 0.25 + bi * 0.75 * 0.5\nblue = 0.25 + bi * 0.75 * 0.12\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -348,7 +349,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Plankton",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Plankton.avs\" by UnConeD. The original is driven by DynamicMovement, FastBright, which the script engine cannot run — replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Plankton.avs\" by UnConeD. The original is driven by DynamicMovement, FastBright, which the script engine cannot run -- replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Plankton.avs",
|
||||
approx: true,
|
||||
content: "name: \"Plankton\"\nmode: dots\nblend: additive\npersist: 0.83\nlinewidth: 2.37\n\n[init]\nn = 627\n\n[frame]\nhue = hue + dt * 0.033 + beat * 0.01\ntravel = travel + dt * (0.435 + bass_att * 1.4)\nflash = flash * 0.86\n\n[beat]\nflash = 1\n\n[point]\ng = floor(i * 11)\ngi = frac(i * 11)\nph = frac(rand(g * 5.1 + 1) + travel * (0.55 + rand(g + 17) * 0.85))\na = gi * 6.28318\nrad = ph * (0.194 + bass * 0.352 + flash * 0.08)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nfade = sin(ph * 3.14159)\nred = min(1, fade * (0.35 + flash * 0.4) * 1.3)\ngreen = fade * (0.35 + flash * 0.4) * 0.5\nblue = fade * (0.35 + flash * 0.4) * 0.12\nskip = if(above(ph, 0.96), 1, 0)\n",
|
||||
|
|
@ -357,7 +358,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Reflectocube",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Reflectocube.avs\" by UnConeD. The original is driven by Movement, DynamicMovement, which the script engine cannot run — replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Reflectocube.avs\" by UnConeD. The original is driven by Movement, DynamicMovement, which the script engine cannot run -- replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Reflectocube.avs",
|
||||
approx: true,
|
||||
content: "name: \"Reflectocube\"\nmode: lines\nblend: additive\npersist: 0.91\nlinewidth: 1.419\n\n[init]\nn = 1235\n\n[frame]\nt = t + dt * (0.31 + bass_att * 1.8)\nhue = hue + dt * 0.065 + beat * 0.012\n\n[point]\narm = floor(i * 4)\nfa = frac(i * 4)\nd = fa\nang = arm * 1.405 + d * 0.906 * 3.14159 + t\nrad = (0.04 + pow(d, 1.825) * 1.15) * (0.7 + bass * 0.5)\nx = sin(ang) * rad / aspect\ny = cos(ang) * rad\nred = (0.3 + 0.7 * d) * (0.3 + mid) * (0.45 + 0.55 * sin(hue * 6.28318 + d * 4.537))\ngreen = (0.3 + 0.7 * d) * (0.3 + mid) * (0.45 + 0.55 * sin(hue * 6.28318 + d * 4.537 + 2.09))\nblue = (0.3 + 0.7 * d) * (0.3 + mid) * (0.45 + 0.55 * sin(hue * 6.28318 + d * 4.537 + 4.19))\nskip = if(below(fa, 0.04), 1, 0)\n",
|
||||
|
|
@ -366,7 +367,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Speeder 3K",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Speeder 3K.avs\" by UnConeD. The original is driven by unportable scope code (init line 12: Unexpected character '¤'), which the script engine cannot run — replaced with a generated \"starfield\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Speeder 3K.avs\" by UnConeD. The original is driven by unportable scope code (init line 12: Unexpected character '¤'), which the script engine cannot run -- replaced with a generated \"starfield\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Speeder 3K.avs",
|
||||
approx: true,
|
||||
content: "name: \"Speeder 3K\"\nmode: dots\nblend: additive\npersist: 0.831\nlinewidth: 2.272\n\n[init]\nn = 949\n\n[frame]\ntravel = travel + dt * (0.156 + vol_att * 1.231)\nhue = hue + dt * 0.04\n\n[point]\na = rand(i * 7.3) * 6.28318\nz = frac(rand(i * 3.1 + 5) + travel * (0.5 + rand(i + 9) * 0.7))\nrad = z * z * 1.206\nx = sin(a) * rad / aspect\ny = cos(a) * rad\ntw = 0.4 + 0.6 * sin(z * 40 + time * 3) * (0.5 + treb)\nred = min(1, tw * 1.3)\ngreen = tw * 0.5\nblue = tw * 0.12\nsize = 1 + z * 3 * (0.5 + bass)\nskip = if(above(z, 0.97), 1, 0)\n",
|
||||
|
|
@ -375,7 +376,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "TC Plasma",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - TC Plasma.avs\" by UnConeD. The original is driven by CustomBPM, DynamicMovement, FastBright, which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - TC Plasma.avs\" by UnConeD. The original is driven by CustomBPM, DynamicMovement, FastBright, which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - TC Plasma.avs",
|
||||
approx: true,
|
||||
content: "name: \"TC Plasma\"\nmode: lines\nblend: additive\npersist: 0.932\nlinewidth: 1.976\n\n[init]\nn = 1072\n\n[frame]\nt = t + dt * (0.432 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.076\n\n[point]\na = i * 6.28318 * 3\nwob = sin(a * 4 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.223 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5))\ngreen = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5 + 2.09))\nblue = 0.3 + abs(v) * 1.2 * (0.45 + 0.55 * sin(hue * 6.28318 + a * 0.5 + 4.19))\n",
|
||||
|
|
@ -384,7 +385,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Tie Tunnel SSC",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Tie Tunnel SSC.avs\" by UnConeD. The original is driven by unportable scope code (init line 12: Unexpected character '¤'), which the script engine cannot run — replaced with a generated \"helix\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Tie Tunnel SSC.avs\" by UnConeD. The original is driven by unportable scope code (init line 12: Unexpected character '¤'), which the script engine cannot run -- replaced with a generated \"helix\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Tie Tunnel SSC.avs",
|
||||
approx: true,
|
||||
content: "name: \"Tie Tunnel SSC\"\nmode: lines\nblend: additive\npersist: 0.851\nlinewidth: 2.021\n\n[init]\nn = 1179\n\n[frame]\nt = t + dt * (0.17 + bass_att * 0.9)\nhue = hue + dt * 0.129\nflash = flash * 0.86\n\n[beat]\nflash = 1\n\n[point]\nst = floor(i * 2)\nsi = frac(i * 2)\ns = si * 6 * 6.28318 + t\nph = st * 3.14159\nrad = (0.28 + bass * 0.32 + flash * 0.06) * (0.55 + 0.45 * (cos(s + ph) * 0.5 + 0.5))\nx = sin(s + ph) * rad / aspect\ny = (si - 0.5) * 1.8\nred = min(1, 0.25 + 0.55 * (cos(s + ph) * 0.5 + 0.5) + treb * 0.25 * 1.3)\ngreen = 0.25 + 0.55 * (cos(s + ph) * 0.5 + 0.5) + treb * 0.25 * 0.5\nblue = 0.25 + 0.55 * (cos(s + ph) * 0.5 + 0.5) + treb * 0.25 * 0.12\n",
|
||||
|
|
@ -393,7 +394,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Zero-G Maze II",
|
||||
author: "UnConeD",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Zero-G Maze II.avs\" by UnConeD. The original is driven by DynamicMovement, which the script engine cannot run — replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD - Zero-G Maze II.avs\" by UnConeD. The original is driven by DynamicMovement, which the script engine cannot run -- replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD - Zero-G Maze II.avs",
|
||||
approx: true,
|
||||
content: "name: \"Zero-G Maze II\"\nmode: lines\nblend: additive\npersist: 0.916\nlinewidth: 1.457\n\n[init]\nn = 1049\n\n[frame]\nt = t + dt * (0.267 + bass_att * 1.8)\nhue = hue + dt * 0.038 + beat * 0.012\n\n[point]\narm = floor(i * 7)\nfa = frac(i * 7)\nd = fa\nang = arm * 1.253 + d * 0.88 * 3.14159 + t\nrad = (0.04 + pow(d, 2.401) * 1.15) * (0.7 + bass * 0.5)\nx = sin(ang) * rad / aspect\ny = cos(ang) * rad\nred = (0.3 + 0.7 * d) * (0.3 + mid) * (0.45 + 0.55 * sin(hue * 6.28318 + d * 2.064))\ngreen = (0.3 + 0.7 * d) * (0.3 + mid) * (0.45 + 0.55 * sin(hue * 6.28318 + d * 2.064 + 2.09))\nblue = (0.3 + 0.7 * d) * (0.3 + mid) * (0.45 + 0.55 * sin(hue * 6.28318 + d * 2.064 + 4.19))\nskip = if(below(fa, 0.04), 1, 0)\n",
|
||||
|
|
@ -402,7 +403,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "UnConeD -Zero-G Maze III",
|
||||
author: "",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD -Zero-G Maze III.avs\". The original is driven by BlitterFeedback, Movement, DynamicMovement, which the script engine cannot run — replaced with a generated \"tunnel\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"UnConeD -Zero-G Maze III.avs\". The original is driven by BlitterFeedback, Movement, DynamicMovement, which the script engine cannot run -- replaced with a generated \"tunnel\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/UnConeD -Zero-G Maze III.avs",
|
||||
approx: true,
|
||||
content: "name: \"UnConeD -Zero-G Maze III\"\nmode: lines\nblend: additive\npersist: 0.853\nlinewidth: 1.507\n\n[init]\nn = 722\n\n[frame]\nt = t + dt * (0.243 + bass_att * 1.5)\nhue = hue + dt * 0.093\n\n[point]\nring = floor(i * 19)\nri2 = frac(i * 19)\nz = frac(ring / 19 + t)\nrad = 0.05 + z * 0.881\na = ri2 * 6.28318 + ring * 0.16 + sin(t * 0.7) * 2\nx = sin(a) * rad * (0.55 + sv * 0.901) / aspect\ny = cos(a) * rad * (0.55 + sv * 0.901)\nred = (1 - z) * (0.3 + bass * 0.7) * 0.3\ngreen = (1 - z) * (0.3 + bass * 0.7) * 0.65\nblue = min(1, (1 - z) * (0.3 + bass * 0.7) * 1.3)\n",
|
||||
|
|
@ -411,7 +412,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "nebulous (skupers remix)",
|
||||
author: "amphirion",
|
||||
description: "Auto-ported from the Winamp AVS preset \"amphirion - nebulous (skupers remix).avs\" by amphirion. The original is driven by Water, UniqueTone, Interleave, which the script engine cannot run — replaced with a generated \"lattice\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"amphirion - nebulous (skupers remix).avs\" by amphirion. The original is driven by Water, UniqueTone, Interleave, which the script engine cannot run -- replaced with a generated \"lattice\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/amphirion - nebulous (skupers remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"nebulous (skupers remix)\"\nmode: dots\nblend: additive\npersist: 0.833\nlinewidth: 2.862\n\n[init]\ncols = 28\nn = cols * cols\n\n[frame]\nrot = rot + dt * (0.104 + mid * 0.4)\nhue = hue + dt * 0.08\n\n[point]\ncx = floor(i * cols) / (cols - 1)\ncy = frac(i * cols)\nh = sv * 0.235\nux = (cx - 0.5) * 1.448\nuy = (cy - 0.5) * 1.448\nrx = ux * cos(rot) - uy * sin(rot)\nry = ux * sin(rot) + uy * cos(rot)\nx = (rx / aspect) * (1 - h * 0.7)\ny = ry * (1 - h * 0.7)\nred = 0.22 + h * 2.2 * (0.45 + 0.55 * sin(hue * 6.28318 + cx * 3.774))\ngreen = 0.22 + h * 2.2 * (0.45 + 0.55 * sin(hue * 6.28318 + cx * 3.774 + 2.09))\nblue = 0.22 + h * 2.2 * (0.45 + 0.55 * sin(hue * 6.28318 + cx * 3.774 + 4.19))\nsize = 1.2 + h * 5\n",
|
||||
|
|
@ -420,7 +421,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "soundscape III (skupers remix)",
|
||||
author: "el-vis",
|
||||
description: "Auto-ported from the Winamp AVS preset \"el-vis - soundscape III (skupers remix).avs\" by el-vis. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"el-vis - soundscape III (skupers remix).avs\" by el-vis. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/el-vis - soundscape III (skupers remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"soundscape III (skupers remix)\"\nmode: lines\nblend: additive\npersist: 0.851\nlinewidth: 1.939\n\n[init]\nsegs = 14\nn = 582\n\n[frame]\nrot = rot + dt * (0.13 + mid_att * 0.5)\nhue = hue + dt * 0.073\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 4 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + amp * 1.3 * abs(sin(seg * 0.8))\ngreen = 0.3 + amp * 1.3 * 0.22\nblue = 0.3 + amp * 1.3 * abs(cos(seg * 0.8))\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -438,7 +439,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "jinx (skupers remix)",
|
||||
author: "horse-fly",
|
||||
description: "Auto-ported from the Winamp AVS preset \"horse-fly - jinx (skupers remix).avs\" by horse-fly. The original is driven by ColorClip, Simple, Mosaic, which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"horse-fly - jinx (skupers remix).avs\" by horse-fly. The original is driven by ColorClip, Simple, Mosaic, which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/horse-fly - jinx (skupers remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"jinx (skupers remix)\"\nmode: dots\nblend: additive\npersist: 0.814\nlinewidth: 1.769\n\n[init]\nbars = 46\nn = bars * 12\n\n[frame]\nrot = rot + dt * (0.046 + mid * 0.3)\nhue = hue + dt * 0.043\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.65\na = bar * 6.28318 / bars + rot\nrad = 0.246 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.25 + bi * 0.75 * abs(sin(bar * 6.28318 / bars))\ngreen = 0.25 + bi * 0.75 * 0.22\nblue = 0.25 + bi * 0.75 * abs(cos(bar * 6.28318 / bars))\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -447,7 +448,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "not quite a bendy tunnel (skupers remix)",
|
||||
author: "jheriko",
|
||||
description: "Auto-ported from the Winamp AVS preset \"jheriko - not quite a bendy tunnel (skupers remix).avs\" by jheriko. The original is driven by Interleave, DynamicMovement, effect#737, which the script engine cannot run — replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"jheriko - not quite a bendy tunnel (skupers remix).avs\" by jheriko. The original is driven by Interleave, DynamicMovement, effect#737, which the script engine cannot run -- replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/jheriko - not quite a bendy tunnel (skupers remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"not quite a bendy tunnel (skupers remix)\"\nmode: lines\nblend: additive\npersist: 0.862\nlinewidth: 1.443\n\n[init]\nn = 806\n\n[frame]\nt = t + dt * 0.276\nhue = hue + dt * 0.055\n\n[point]\nph = i * 6.28318 * 1.699\nfa = 2 + mid * 0.35\nfb = 3 + bass * 0.45\nx = sin(ph * fa + t) * (0.5 + bass * 0.3) / aspect\ny = sin(ph * fb + t * 1.3 + 2.216) * (0.5 + treb * 0.35)\nred = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 0.3\ngreen = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 0.65\nblue = min(1, 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 1.3)\n",
|
||||
|
|
@ -456,7 +457,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "newpoop (for wa5)",
|
||||
author: "justin",
|
||||
description: "Auto-ported from the Winamp AVS preset \"justin - newpoop (for wa5).avs\" by justin. The original is driven by ColorModifier, which the script engine cannot run — replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"justin - newpoop (for wa5).avs\" by justin. The original is driven by ColorModifier, which the script engine cannot run -- replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/justin - newpoop (for wa5).avs",
|
||||
approx: true,
|
||||
content: "name: \"newpoop (for wa5)\"\nmode: dots\nblend: additive\npersist: 0.796\nlinewidth: 2.44\n\n[init]\nrings = 4\nn = rings * 98\n\n[frame]\nt = t + dt * (0.176 + bass_att * 0.6)\nhue = hue + dt * 0.135\nsquash = 0.549 + 0.25 * sin(t * 0.439)\n\n[point]\nring = floor(i * rings)\nri3 = frac(i * rings)\nr0 = 0.16 + ring * 0.12\na = ri3 * 6.28318 + t * (1.2 - ring * 0.18) + ring * 2.4\nx = sin(a) * r0 * (1 + bass * 0.18) / aspect\ny = cos(a) * r0 * squash\nsat = frac(ri3 * 5)\nsize = if(below(sat, 0.14), 3 + bass * 3, 1)\nred = min(1, 0.25 + bass * 0.5 + ring * 0.07 * 1.3)\ngreen = 0.25 + bass * 0.5 + ring * 0.07 * 0.5\nblue = 0.25 + bass * 0.5 + ring * 0.07 * 0.12\n",
|
||||
|
|
@ -465,7 +466,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "the landscape is killing me (wa5remix)",
|
||||
author: "justin",
|
||||
description: "Auto-ported from the Winamp AVS preset \"justin - the landscape is killing me (wa5remix).avs\" by justin. The original is driven by DynamicDistanceModifier, ColorModifier, which the script engine cannot run — replaced with a generated \"rain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"justin - the landscape is killing me (wa5remix).avs\" by justin. The original is driven by DynamicDistanceModifier, ColorModifier, which the script engine cannot run -- replaced with a generated \"rain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/justin - the landscape is killing me (wa5remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"the landscape is killing me (wa5remix)\"\nmode: dots\nblend: additive\npersist: 0.704\nlinewidth: 2.586\n\n[init]\ncols = 54\nn = 1193\n\n[frame]\nfall = fall + dt * (0.514 + vol_att * 0.841)\nhue = hue + dt * 0.071\n\n[point]\ncol = floor(i * cols)\nci = frac(i * cols)\nxx = (col / cols - 0.5) * 1.9\nyf = frac(rand(col * 3.7 + 1) + fall * (0.55 + rand(col + 5) * 0.5))\ntail = rand(col * 1.3 + 9) * 0.31 + 0.04\nyy = (yf * 2 - 1) * 1.05 + ci * tail\nx = xx / aspect\ny = yy\nred = (1 - ci) * (0.2 + treb * 0.85) + 0.04 * (0.45 + 0.55 * sin(hue * 6.28318 + col * 0.3))\ngreen = (1 - ci) * (0.2 + treb * 0.85) + 0.04 * (0.45 + 0.55 * sin(hue * 6.28318 + col * 0.3 + 2.09))\nblue = (1 - ci) * (0.2 + treb * 0.85) + 0.04 * (0.45 + 0.55 * sin(hue * 6.28318 + col * 0.3 + 4.19))\nskip = if(above(abs(yy), 1.02), 1, 0)\n",
|
||||
|
|
@ -474,7 +475,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Dragonscales",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Dragonscales.avs\" by mig. The original is driven by CustomBPM, BufferSave, MovingParticle, which the script engine cannot run — replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Dragonscales.avs\" by mig. The original is driven by CustomBPM, BufferSave, MovingParticle, which the script engine cannot run -- replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Dragonscales.avs",
|
||||
approx: true,
|
||||
content: "name: \"Dragonscales\"\nmode: lines\nblend: additive\npersist: 0.885\nlinewidth: 2.375\n\n[init]\nn = 938\n\n[frame]\nt = t + dt * 0.353\nhue = hue + dt * 0.094\n\n[point]\nph = i * 6.28318 * 2.096\nfa = 2 + mid * 0.35\nfb = 3 + bass * 0.45\nx = sin(ph * fa + t) * (0.5 + bass * 0.3) / aspect\ny = sin(ph * fb + t * 1.3 + 2.866) * (0.5 + treb * 0.35)\nred = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * (0.25 + bass * 0.95)\ngreen = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * (0.25 + mid * 0.95)\nblue = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * (0.25 + treb * 0.95)\n",
|
||||
|
|
@ -483,7 +484,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Encapsulade",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Encapsulade.avs\" by mig. The original is driven by BufferSave, SetRenderMode, CustomBPM, which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Encapsulade.avs\" by mig. The original is driven by BufferSave, SetRenderMode, CustomBPM, which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Encapsulade.avs",
|
||||
approx: true,
|
||||
content: "name: \"Encapsulade\"\nmode: lines\nblend: additive\npersist: 0.814\nlinewidth: 2.058\n\n[init]\nbars = 64\nn = bars * 9\n\n[frame]\nrot = rot + dt * (0.103 + mid * 0.3)\nhue = hue + dt * 0.072\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.85\na = bar * 6.28318 / bars + rot\nrad = 0.262 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars))\ngreen = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars + 2.09))\nblue = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars + 4.19))\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -492,7 +493,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Freekwyrms",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Freekwyrms.avs\" by mig. The original is driven by BufferSave, SetRenderMode, MovingParticle, which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Freekwyrms.avs\" by mig. The original is driven by BufferSave, SetRenderMode, MovingParticle, which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Freekwyrms.avs",
|
||||
approx: true,
|
||||
content: "name: \"Freekwyrms\"\nmode: dots\nblend: additive\npersist: 0.864\nlinewidth: 1.436\n\n[init]\nbars = 46\nn = bars * 12\n\n[frame]\nrot = rot + dt * (0.09 + mid * 0.3)\nhue = hue + dt * 0.063\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.722\na = bar * 6.28318 / bars + rot\nrad = 0.216 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = min(1, 0.25 + bi * 0.75 * 1.3)\ngreen = 0.25 + bi * 0.75 * 0.5\nblue = 0.25 + bi * 0.75 * 0.12\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -501,7 +502,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Lilypod",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Lilypod.avs\" by mig. The original is driven by BufferSave, MovingParticle, 2.8+ Effect List Config, which the script engine cannot run — replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Lilypod.avs\" by mig. The original is driven by BufferSave, MovingParticle, 2.8+ Effect List Config, which the script engine cannot run -- replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Lilypod.avs",
|
||||
approx: true,
|
||||
content: "name: \"Lilypod\"\nmode: dots\nblend: additive\npersist: 0.787\nlinewidth: 1.928\n\n[init]\nn = 885\n\n[frame]\ntt = tt + dt * (0.5 + bass_att * 1.1)\nhue = hue + dt * 0.04\nburst = burst * 0.9\n\n[beat]\nburst = 1\n\n[point]\njet = floor(i * 4)\nlife = frac(rand(i * 7.7 + jet) + tt * (0.35 + rand(i + 3) * 0.65))\na = jet * 6.28318 / 4 + rand(i * 5.1 + jet) * 0.722\nspd = 0.4 + rand(i * 9.2 + jet) * 0.8\npx = cos(a) * spd * life\npy = sin(a) * spd * life - 0.744 * life * life\nx = px * (0.85 + bass * 0.35) / aspect\ny = py\nred = max(0, 1 - life) * (0.35 + burst * 0.55) * abs(sin(life * 4))\ngreen = max(0, 1 - life) * (0.35 + burst * 0.55) * 0.22\nblue = max(0, 1 - life) * (0.35 + burst * 0.55) * abs(cos(life * 4))\nskip = if(above(life, 0.94), 1, 0)\n",
|
||||
|
|
@ -510,7 +511,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Mist Wisps",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Mist Wisps.avs\" by mig. The original is driven by CustomBPM, BufferSave, MovingParticle, which the script engine cannot run — replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Mist Wisps.avs\" by mig. The original is driven by CustomBPM, BufferSave, MovingParticle, which the script engine cannot run -- replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Mist Wisps.avs",
|
||||
approx: true,
|
||||
content: "name: \"Mist Wisps\"\nmode: dots\nblend: additive\npersist: 0.758\nlinewidth: 2.24\n\n[init]\nn = 1297\n\n[frame]\nt = t + dt * 0.323\nhue = hue + dt * 0.1\n\n[point]\nu = rand(i * 1.7) * 2 - 1\nw = rand(i * 3.3 + 11) * 2 - 1\nm = sin((u * 2.207 + w * 6.547 + t) * 3.14159) * sin((u * 5.739 - w * 2.319 - t * 0.7) * 3.14159)\nx = u * 0.85 / aspect\ny = w * 0.957\nlum = max(0, m) * (0.3 + bass * 0.9) + 0.06\nred = lum * (0.25 + bass * 0.95)\ngreen = lum * (0.25 + mid * 0.95)\nblue = lum * (0.25 + treb * 0.95)\nsize = 1 + abs(m) * 3.505\n",
|
||||
|
|
@ -519,7 +520,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Nebulating - Hypercolorspace",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Nebulating - Hypercolorspace.avs\" by mig. The original is driven by CustomBPM, BufferSave, Fadeout, which the script engine cannot run — replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Nebulating - Hypercolorspace.avs\" by mig. The original is driven by CustomBPM, BufferSave, Fadeout, which the script engine cannot run -- replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Nebulating - Hypercolorspace.avs",
|
||||
approx: true,
|
||||
content: "name: \"Nebulating - Hypercolorspace\"\nmode: dots\nblend: additive\npersist: 0.792\nlinewidth: 2.678\n\n[init]\nn = 1374\n\n[frame]\nt = t + dt * 0.423\nhue = hue + dt * 0.123\n\n[point]\nu = rand(i * 1.7) * 2 - 1\nw = rand(i * 3.3 + 11) * 2 - 1\nm = sin((u * 3.51 + w * 2.666 + t) * 3.14159) * sin((u * 6.323 - w * 6.393 - t * 0.7) * 3.14159)\nx = u * 0.959 / aspect\ny = w * 0.871\nlum = max(0, m) * (0.3 + bass * 0.9) + 0.06\nred = min(1, lum * 1.3)\ngreen = lum * 0.5\nblue = lum * 0.12\nsize = 1 + abs(m) * 3.799\n",
|
||||
|
|
@ -528,7 +529,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Reverb - Deep Net",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Reverb - Deep Net.avs\" by mig. The original is driven by CustomBPM, BufferSave, Fadeout, which the script engine cannot run — replaced with a generated \"lattice\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Reverb - Deep Net.avs\" by mig. The original is driven by CustomBPM, BufferSave, Fadeout, which the script engine cannot run -- replaced with a generated \"lattice\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Reverb - Deep Net.avs",
|
||||
approx: true,
|
||||
content: "name: \"Reverb - Deep Net\"\nmode: dots\nblend: additive\npersist: 0.818\nlinewidth: 2.394\n\n[init]\ncols = 29\nn = cols * cols\n\n[frame]\nrot = rot + dt * (0.041 + mid * 0.4)\nhue = hue + dt * 0.089\n\n[point]\ncx = floor(i * cols) / (cols - 1)\ncy = frac(i * cols)\nh = sv * 0.525\nux = (cx - 0.5) * 1.845\nuy = (cy - 0.5) * 1.845\nrx = ux * cos(rot) - uy * sin(rot)\nry = ux * sin(rot) + uy * cos(rot)\nx = (rx / aspect) * (1 - h * 0.7)\ny = ry * (1 - h * 0.7)\nred = 0.22 + h * 2.2 * abs(sin(cx * 2.712))\ngreen = 0.22 + h * 2.2 * 0.22\nblue = 0.22 + h * 2.2 * abs(cos(cx * 2.712))\nsize = 1.2 + h * 5\n",
|
||||
|
|
@ -537,7 +538,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Slyde - Tri",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Slyde - Tri.avs\" by mig. The original is driven by BufferSave, SetRenderMode, MovingParticle, which the script engine cannot run — replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Slyde - Tri.avs\" by mig. The original is driven by BufferSave, SetRenderMode, MovingParticle, which the script engine cannot run -- replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Slyde - Tri.avs",
|
||||
approx: true,
|
||||
content: "name: \"Slyde - Tri\"\nmode: lines\nblend: additive\npersist: 0.863\nlinewidth: 1.626\n\n[init]\nn = 938\n\n[frame]\nt = t + dt * 0.483\nhue = hue + dt * 0.076\n\n[point]\nph = i * 6.28318 * 2.841\nfa = 6 + mid * 0.35\nfb = 2 + bass * 0.45\nx = sin(ph * fa + t) * (0.5 + bass * 0.3) / aspect\ny = sin(ph * fb + t * 1.3 + 1.909) * (0.5 + treb * 0.35)\nred = min(1, 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 1.3)\ngreen = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 0.5\nblue = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 0.12\n",
|
||||
|
|
@ -546,7 +547,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Solar Flaire",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Solar Flaire.avs\" by mig. The original is driven by BufferSave, Fadeout, SetRenderMode, which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Solar Flaire.avs\" by mig. The original is driven by BufferSave, Fadeout, SetRenderMode, which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Solar Flaire.avs",
|
||||
approx: true,
|
||||
content: "name: \"Solar Flaire\"\nmode: lines\nblend: additive\npersist: 0.866\nlinewidth: 1.678\n\n[init]\nbars = 59\nn = bars * 11\n\n[frame]\nrot = rot + dt * (0.076 + mid * 0.3)\nhue = hue + dt * 0.107\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.607\na = bar * 6.28318 / bars + rot\nrad = 0.241 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars))\ngreen = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars + 2.09))\nblue = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars + 4.19))\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -555,7 +556,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Spintronics - Backspin",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Spintronics - Backspin.avs\" by mig. The original is driven by 2.8+ Effect List Config, Simple, SetRenderMode, which the script engine cannot run — replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Spintronics - Backspin.avs\" by mig. The original is driven by 2.8+ Effect List Config, Simple, SetRenderMode, which the script engine cannot run -- replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Spintronics - Backspin.avs",
|
||||
approx: true,
|
||||
content: "name: \"Spintronics - Backspin\"\nmode: dots\nblend: additive\npersist: 0.804\nlinewidth: 2.037\n\n[init]\nn = 1157\n\n[frame]\ntt = tt + dt * (0.5 + bass_att * 1.1)\nhue = hue + dt * 0.12\nburst = burst * 0.9\n\n[beat]\nburst = 1\n\n[point]\njet = floor(i * 4)\nlife = frac(rand(i * 7.7 + jet) + tt * (0.35 + rand(i + 3) * 0.65))\na = jet * 6.28318 / 4 + rand(i * 5.1 + jet) * 0.547\nspd = 0.4 + rand(i * 9.2 + jet) * 0.8\npx = cos(a) * spd * life\npy = sin(a) * spd * life - 0.712 * life * life\nx = px * (0.85 + bass * 0.35) / aspect\ny = py\nred = min(1, max(0, 1 - life) * (0.35 + burst * 0.55) * 1.3)\ngreen = max(0, 1 - life) * (0.35 + burst * 0.55) * 0.5\nblue = max(0, 1 - life) * (0.35 + burst * 0.55) * 0.12\nskip = if(above(life, 0.94), 1, 0)\n",
|
||||
|
|
@ -564,7 +565,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Starslappin",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Starslappin.avs\" by mig. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Starslappin.avs\" by mig. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Starslappin.avs",
|
||||
approx: true,
|
||||
content: "name: \"Starslappin\"\nmode: lines\nblend: additive\npersist: 0.842\nlinewidth: 2.148\n\n[init]\nsegs = 7\nn = 545\n\n[frame]\nrot = rot + dt * (0.087 + mid_att * 0.5)\nhue = hue + dt * 0.125\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 6 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + amp * 1.3 * (0.25 + bass * 0.95)\ngreen = 0.3 + amp * 1.3 * (0.25 + mid * 0.95)\nblue = 0.3 + amp * 1.3 * (0.25 + treb * 0.95)\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -573,7 +574,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Street Art - Fire Inside",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Street Art - Fire Inside.avs\" by mig. The original is driven by BufferSave, Colorfade, Movement, which the script engine cannot run — replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Street Art - Fire Inside.avs\" by mig. The original is driven by BufferSave, Colorfade, Movement, which the script engine cannot run -- replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Street Art - Fire Inside.avs",
|
||||
approx: true,
|
||||
content: "name: \"Street Art - Fire Inside\"\nmode: dots\nblend: additive\npersist: 0.757\nlinewidth: 2.052\n\n[init]\nn = 1065\n\n[frame]\ntt = tt + dt * (0.5 + bass_att * 1.1)\nhue = hue + dt * 0.108\nburst = burst * 0.9\n\n[beat]\nburst = 1\n\n[point]\njet = floor(i * 4)\nlife = frac(rand(i * 7.7 + jet) + tt * (0.35 + rand(i + 3) * 0.65))\na = jet * 6.28318 / 4 + rand(i * 5.1 + jet) * 1.184\nspd = 0.4 + rand(i * 9.2 + jet) * 0.8\npx = cos(a) * spd * life\npy = sin(a) * spd * life - 1.383 * life * life\nx = px * (0.85 + bass * 0.35) / aspect\ny = py\nred = max(0, 1 - life) * (0.35 + burst * 0.55) * 0.3\ngreen = max(0, 1 - life) * (0.35 + burst * 0.55) * 0.65\nblue = min(1, max(0, 1 - life) * (0.35 + burst * 0.55) * 1.3)\nskip = if(above(life, 0.94), 1, 0)\n",
|
||||
|
|
@ -582,7 +583,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Swoo - Slow",
|
||||
author: "mig",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Swoo - Slow.avs\" by mig. The original is driven by CustomBPM, BufferSave, Movement, which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"mig - Swoo - Slow.avs\" by mig. The original is driven by CustomBPM, BufferSave, Movement, which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/mig - Swoo - Slow.avs",
|
||||
approx: true,
|
||||
content: "name: \"Swoo - Slow\"\nmode: lines\nblend: additive\npersist: 0.919\nlinewidth: 1.852\n\n[init]\nn = 1159\n\n[frame]\nt = t + dt * (0.461 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.046\n\n[point]\na = i * 6.28318 * 3\nwob = sin(a * 3 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.199 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + abs(v) * 1.2 * 0.3\ngreen = 0.3 + abs(v) * 1.2 * 0.65\nblue = min(1, 0.3 + abs(v) * 1.2 * 1.3)\n",
|
||||
|
|
@ -591,7 +592,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "smell of music (skupers remix)",
|
||||
author: "nixa",
|
||||
description: "Auto-ported from the Winamp AVS preset \"nixa - smell of music (skupers remix).avs\" by nixa. The original is driven by Mirror, DynamicMovement, Movement, which the script engine cannot run — replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"nixa - smell of music (skupers remix).avs\" by nixa. The original is driven by Mirror, DynamicMovement, Movement, which the script engine cannot run -- replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/nixa - smell of music (skupers remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"smell of music (skupers remix)\"\nmode: lines\nblend: additive\npersist: 0.805\nlinewidth: 1.342\n\n[init]\nspokes = 31\nn = spokes * 34\n\n[frame]\nrot = rot + dt * (0.118 + mid * 0.4)\nt = t + dt * 2.453\nhue = hue + dt * 0.113\n\n[point]\nsp = floor(i * spokes)\nsi = frac(i * spokes)\na = sp * 6.28318 / spokes + rot\nwave = sin(si * 3 * 3.14159 - t) * (0.03 + bass * 0.28)\nrad = 0.12 + si * 0.868 + wave\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = (1 - si) * 0.45 + 0.15 + sv * 0.55 * 0.3\ngreen = (1 - si) * 0.45 + 0.15 + sv * 0.55 * 0.65\nblue = min(1, (1 - si) * 0.45 + 0.15 + sv * 0.55 * 1.3)\nskip = if(above(si, 0.985), 1, 0)\n",
|
||||
|
|
@ -600,7 +601,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "bumpy",
|
||||
author: "p-k",
|
||||
description: "Auto-ported from the Winamp AVS preset \"p-k - bumpy.avs\" by p-k. The original is driven by CustomBPM, Color Map, which the script engine cannot run — replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"p-k - bumpy.avs\" by p-k. The original is driven by CustomBPM, Color Map, which the script engine cannot run -- replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/p-k - bumpy.avs",
|
||||
approx: true,
|
||||
content: "name: \"bumpy\"\nmode: dots\nblend: additive\npersist: 0.798\nlinewidth: 1.642\n\n[init]\nn = 640\n\n[frame]\nhue = hue + dt * 0.119 + beat * 0.01\ntravel = travel + dt * (0.394 + bass_att * 1.4)\nflash = flash * 0.86\n\n[beat]\nflash = 1\n\n[point]\ng = floor(i * 10)\ngi = frac(i * 10)\nph = frac(rand(g * 5.1 + 1) + travel * (0.55 + rand(g + 17) * 0.85))\na = gi * 6.28318\nrad = ph * (0.28 + bass * 0.544 + flash * 0.08)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nfade = sin(ph * 3.14159)\nred = fade * (0.35 + flash * 0.4) * 0.3\ngreen = fade * (0.35 + flash * 0.4) * 0.65\nblue = min(1, fade * (0.35 + flash * 0.4) * 1.3)\nskip = if(above(ph, 0.96), 1, 0)\n",
|
||||
|
|
@ -609,7 +610,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "splendora",
|
||||
author: "",
|
||||
description: "Auto-ported from the Winamp AVS preset \"splendora.avs\". The original is driven by Grain, Simple, Movement, which the script engine cannot run — replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"splendora.avs\". The original is driven by Grain, Simple, Movement, which the script engine cannot run -- replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/splendora.avs",
|
||||
approx: true,
|
||||
content: "name: \"splendora\"\nmode: lines\nblend: additive\npersist: 0.867\nlinewidth: 1.513\n\n[init]\nn = 974\n\n[frame]\nt = t + dt * (0.211 + bass_att * 1.8)\nhue = hue + dt * 0.068 + beat * 0.012\n\n[point]\narm = floor(i * 9)\nfa = frac(i * 9)\nd = fa\nang = arm * 1.515 + d * 1.922 * 3.14159 + t\nrad = (0.04 + pow(d, 1.746) * 1.15) * (0.7 + bass * 0.5)\nx = sin(ang) * rad / aspect\ny = cos(ang) * rad\nred = (0.3 + 0.7 * d) * (0.3 + mid) * abs(sin(d * 2.585))\ngreen = (0.3 + 0.7 * d) * (0.3 + mid) * 0.22\nblue = (0.3 + 0.7 * d) * (0.3 + mid) * abs(cos(d * 2.585))\nskip = if(below(fa, 0.04), 1, 0)\n",
|
||||
|
|
@ -618,7 +619,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Amp Picks",
|
||||
name: "Urantia",
|
||||
author: "zxe",
|
||||
description: "Auto-ported from the Winamp AVS preset \"zxe-Urantia.avs\" by zxe. The original is driven by effect#326, \u0001, UniqueTone, which the script engine cannot run — replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"zxe-Urantia.avs\" by zxe. The original is driven by effect#326, \u0001, UniqueTone, which the script engine cannot run -- replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Amp Picks/zxe-Urantia.avs",
|
||||
approx: true,
|
||||
content: "name: \"Urantia\"\nmode: dots\nblend: additive\npersist: 0.862\nlinewidth: 2.9\n\n[init]\nrings = 4\nn = rings * 101\n\n[frame]\nt = t + dt * (0.393 + bass_att * 0.6)\nhue = hue + dt * 0.094\nsquash = 0.387 + 0.25 * sin(t * 0.454)\n\n[point]\nring = floor(i * rings)\nri3 = frac(i * rings)\nr0 = 0.16 + ring * 0.141\na = ri3 * 6.28318 + t * (1.2 - ring * 0.18) + ring * 2.4\nx = sin(a) * r0 * (1 + bass * 0.18) / aspect\ny = cos(a) * r0 * squash\nsat = frac(ri3 * 2)\nsize = if(below(sat, 0.14), 3 + bass * 3, 1)\nred = 0.25 + bass * 0.5 + ring * 0.07 * (0.25 + bass * 0.95)\ngreen = 0.25 + bass * 0.5 + ring * 0.07 * (0.25 + mid * 0.95)\nblue = 0.25 + bass * 0.5 + ring * 0.07 * (0.25 + treb * 0.95)\n",
|
||||
|
|
@ -627,7 +628,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Dynamics",
|
||||
name: "tentaclism (fake hboy rmx)",
|
||||
author: "dynamic duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"01 dynamic duo - tentaclism (fake hboy rmx).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"starfield\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"01 dynamic duo - tentaclism (fake hboy rmx).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"starfield\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Dynamics/01 dynamic duo - tentaclism (fake hboy rmx).avs",
|
||||
approx: true,
|
||||
content: "name: \"tentaclism (fake hboy rmx)\"\nmode: dots\nblend: additive\npersist: 0.833\nlinewidth: 2.485\n\n[init]\nn = 952\n\n[frame]\ntravel = travel + dt * (0.231 + vol_att * 1.898)\nhue = hue + dt * 0.056\n\n[point]\na = rand(i * 7.3) * 6.28318\nz = frac(rand(i * 3.1 + 5) + travel * (0.5 + rand(i + 9) * 0.7))\nrad = z * z * 0.992\nx = sin(a) * rad / aspect\ny = cos(a) * rad\ntw = 0.4 + 0.6 * sin(z * 40 + time * 3) * (0.5 + treb)\nred = min(1, tw * 1.3)\ngreen = tw * 0.5\nblue = tw * 0.12\nsize = 1 + z * 3 * (0.5 + bass)\nskip = if(above(z, 0.97), 1, 0)\n",
|
||||
|
|
@ -636,7 +637,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Dynamics",
|
||||
name: "tentaclism (sky of contempt mix by drew)",
|
||||
author: "dynamic duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"02 dynamic duo - tentaclism (sky of contempt mix by drew).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"02 dynamic duo - tentaclism (sky of contempt mix by drew).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"orbits\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Dynamics/02 dynamic duo - tentaclism (sky of contempt mix by drew).avs",
|
||||
approx: true,
|
||||
content: "name: \"tentaclism (sky of contempt mix by drew)\"\nmode: dots\nblend: additive\npersist: 0.83\nlinewidth: 2.652\n\n[init]\nrings = 3\nn = rings * 87\n\n[frame]\nt = t + dt * (0.201 + bass_att * 0.6)\nhue = hue + dt * 0.06\nsquash = 0.564 + 0.25 * sin(t * 0.401)\n\n[point]\nring = floor(i * rings)\nri3 = frac(i * rings)\nr0 = 0.16 + ring * 0.108\na = ri3 * 6.28318 + t * (1.2 - ring * 0.18) + ring * 2.4\nx = sin(a) * r0 * (1 + bass * 0.18) / aspect\ny = cos(a) * r0 * squash\nsat = frac(ri3 * 4)\nsize = if(below(sat, 0.14), 3 + bass * 3, 1)\nred = 0.25 + bass * 0.5 + ring * 0.07 * abs(sin(ring * 1.3))\ngreen = 0.25 + bass * 0.5 + ring * 0.07 * 0.22\nblue = 0.25 + bass * 0.5 + ring * 0.07 * abs(cos(ring * 1.3))\n",
|
||||
|
|
@ -654,7 +655,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Dynamics",
|
||||
name: "tentaclism (cathode ray mix by onionring of doom)",
|
||||
author: "dynamic duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"04 dynamic duo - tentaclism (cathode ray mix by onionring of doom).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 19: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"04 dynamic duo - tentaclism (cathode ray mix by onionring of doom).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 19: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Dynamics/04 dynamic duo - tentaclism (cathode ray mix by onionring of doom).avs",
|
||||
approx: true,
|
||||
content: "name: \"tentaclism (cathode ray mix by onionring of doom)\"\nmode: lines\nblend: additive\npersist: 0.873\nlinewidth: 1.987\n\n[init]\nspokes = 26\nn = spokes * 38\n\n[frame]\nrot = rot + dt * (0.076 + mid * 0.4)\nt = t + dt * 1.652\nhue = hue + dt * 0.062\n\n[point]\nsp = floor(i * spokes)\nsi = frac(i * spokes)\na = sp * 6.28318 / spokes + rot\nwave = sin(si * 5 * 3.14159 - t) * (0.03 + bass * 0.28)\nrad = 0.12 + si * 0.882 + wave\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = (1 - si) * 0.45 + 0.15 + sv * 0.55 * 0.3\ngreen = (1 - si) * 0.45 + 0.15 + sv * 0.55 * 0.65\nblue = min(1, (1 - si) * 0.45 + 0.15 + sv * 0.55 * 1.3)\nskip = if(above(si, 0.985), 1, 0)\n",
|
||||
|
|
@ -663,7 +664,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Dynamics",
|
||||
name: "chromatics (glowy mix by meaningless-existance)",
|
||||
author: "dynamic duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"05 dynamic duo - chromatics (glowy mix by meaningless-existance).avs\" by dynamic duo. The original is driven by a trivial scope (n=4; the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"tunnel\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"05 dynamic duo - chromatics (glowy mix by meaningless-existance).avs\" by dynamic duo. The original is driven by a trivial scope (n=4; the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"tunnel\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Dynamics/05 dynamic duo - chromatics (glowy mix by meaningless-existance).avs",
|
||||
approx: true,
|
||||
content: "name: \"chromatics (glowy mix by meaningless-existance)\"\nmode: lines\nblend: additive\npersist: 0.857\nlinewidth: 1.543\n\n[init]\nn = 731\n\n[frame]\nt = t + dt * (0.338 + bass_att * 1.5)\nhue = hue + dt * 0.042\n\n[point]\nring = floor(i * 17)\nri2 = frac(i * 17)\nz = frac(ring / 17 + t)\nrad = 0.05 + z * 0.805\na = ri2 * 6.28318 + ring * 0.411 + sin(t * 0.7) * 2\nx = sin(a) * rad * (0.55 + sv * 1.073) / aspect\ny = cos(a) * rad * (0.55 + sv * 1.073)\nred = (1 - z) * (0.3 + bass * 0.7) * abs(sin(z * 2.074))\ngreen = (1 - z) * (0.3 + bass * 0.7) * 0.22\nblue = (1 - z) * (0.3 + bass * 0.7) * abs(cos(z * 2.074))\n",
|
||||
|
|
@ -672,7 +673,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Dynamics",
|
||||
name: "tentaclism (midas remix)",
|
||||
author: "dynamic duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"06 dynamic duo - tentaclism (midas remix).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"06 dynamic duo - tentaclism (midas remix).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"fountain\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Dynamics/06 dynamic duo - tentaclism (midas remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"tentaclism (midas remix)\"\nmode: dots\nblend: additive\npersist: 0.848\nlinewidth: 2.168\n\n[init]\nn = 757\n\n[frame]\ntt = tt + dt * (0.5 + bass_att * 1.1)\nhue = hue + dt * 0.053\nburst = burst * 0.9\n\n[beat]\nburst = 1\n\n[point]\njet = floor(i * 2)\nlife = frac(rand(i * 7.7 + jet) + tt * (0.35 + rand(i + 3) * 0.65))\na = jet * 6.28318 / 2 + rand(i * 5.1 + jet) * 1.14\nspd = 0.4 + rand(i * 9.2 + jet) * 0.8\npx = cos(a) * spd * life\npy = sin(a) * spd * life - 1.009 * life * life\nx = px * (0.85 + bass * 0.35) / aspect\ny = py\nred = min(1, max(0, 1 - life) * (0.35 + burst * 0.55) * 1.3)\ngreen = max(0, 1 - life) * (0.35 + burst * 0.55) * 0.5\nblue = max(0, 1 - life) * (0.35 + burst * 0.55) * 0.12\nskip = if(above(life, 0.94), 1, 0)\n",
|
||||
|
|
@ -681,7 +682,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Dynamics",
|
||||
name: "tentaclism (raz remix - ugly edit)",
|
||||
author: "dynamic duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"07 dynamic duo - tentaclism (raz remix - ugly edit).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"07 dynamic duo - tentaclism (raz remix - ugly edit).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"spectrum bars\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Dynamics/07 dynamic duo - tentaclism (raz remix - ugly edit).avs",
|
||||
approx: true,
|
||||
content: "name: \"tentaclism (raz remix - ugly edit)\"\nmode: lines\nblend: additive\npersist: 0.873\nlinewidth: 1.756\n\n[init]\nbars = 44\nn = bars * 11\n\n[frame]\nrot = rot + dt * (0.118 + mid * 0.3)\nhue = hue + dt * 0.119\n\n[point]\nbar = floor(i * bars)\nbi = frac(i * bars)\nlvl = getspec(bar / bars, 0, 0)\nh = lvl * 0.767\na = bar * 6.28318 / bars + rot\nrad = 0.145 + bi * h\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars))\ngreen = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars + 2.09))\nblue = 0.25 + bi * 0.75 * (0.45 + 0.55 * sin(hue * 6.28318 + bar * 6.28318 / bars + 4.19))\nskip = if(above(bi, 0.97), 1, 0)\n",
|
||||
|
|
@ -690,7 +691,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Dynamics",
|
||||
name: "tentaclism (the y.m.o. rework #1)",
|
||||
author: "dynamic duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"08 dynamic duo - tentaclism (the y.m.o. rework #1).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"08 dynamic duo - tentaclism (the y.m.o. rework #1).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Dynamics/08 dynamic duo - tentaclism (the y.m.o. rework #1).avs",
|
||||
approx: true,
|
||||
content: "name: \"tentaclism (the y.m.o. rework #1)\"\nmode: dots\nblend: additive\npersist: 0.831\nlinewidth: 1.694\n\n[init]\nspokes = 32\nn = spokes * 27\n\n[frame]\nrot = rot + dt * (0.073 + mid * 0.4)\nt = t + dt * 1.807\nhue = hue + dt * 0.131\n\n[point]\nsp = floor(i * spokes)\nsi = frac(i * spokes)\na = sp * 6.28318 / spokes + rot\nwave = sin(si * 2 * 3.14159 - t) * (0.03 + bass * 0.28)\nrad = 0.12 + si * 0.758 + wave\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = (1 - si) * 0.45 + 0.15 + sv * 0.55 * abs(sin(sp * 0.4))\ngreen = (1 - si) * 0.45 + 0.15 + sv * 0.55 * 0.22\nblue = (1 - si) * 0.45 + 0.15 + sv * 0.55 * abs(cos(sp * 0.4))\nskip = if(above(si, 0.985), 1, 0)\n",
|
||||
|
|
@ -699,7 +700,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Dynamics",
|
||||
name: "tentaclism (kans of kansis mix by drew - edit)",
|
||||
author: "dynamic duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"09 dynamic duo - tentaclism (kans of kansis mix by drew - edit).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"09 dynamic duo - tentaclism (kans of kansis mix by drew - edit).avs\" by dynamic duo. The original is driven by unportable scope code (frame line 20: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Dynamics/09 dynamic duo - tentaclism (kans of kansis mix by drew - edit).avs",
|
||||
approx: true,
|
||||
content: "name: \"tentaclism (kans of kansis mix by drew - edit)\"\nmode: dots\nblend: additive\npersist: 0.827\nlinewidth: 2.039\n\n[init]\nn = 1449\n\n[frame]\nt = t + dt * 0.447\nhue = hue + dt * 0.034\n\n[point]\nu = rand(i * 1.7) * 2 - 1\nw = rand(i * 3.3 + 11) * 2 - 1\nm = sin((u * 6.164 + w * 5.725 + t) * 3.14159) * sin((u * 2.761 - w * 2.167 - t * 0.7) * 3.14159)\nx = u * 0.936 / aspect\ny = w * 0.903\nlum = max(0, m) * (0.3 + bass * 0.9) + 0.06\nred = min(1, lum * 1.3)\ngreen = lum * 0.5\nblue = lum * 0.12\nsize = 1 + abs(m) * 3.26\n",
|
||||
|
|
@ -708,7 +709,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "the pacifist (duo's underworld mix)",
|
||||
author: "amphirion",
|
||||
description: "Auto-ported from the Winamp AVS preset \"01 amphirion - the pacifist (duo's underworld mix).avs\" by amphirion. The original is driven by a trivial scope (n=4; the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"01 amphirion - the pacifist (duo's underworld mix).avs\" by amphirion. The original is driven by a trivial scope (n=4; the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/01 amphirion - the pacifist (duo's underworld mix).avs",
|
||||
approx: true,
|
||||
content: "name: \"the pacifist (duo's underworld mix)\"\nmode: lines\nblend: additive\npersist: 0.856\nlinewidth: 1.75\n\n[init]\nsegs = 14\nn = 483\n\n[frame]\nrot = rot + dt * (0.149 + mid_att * 0.5)\nhue = hue + dt * 0.117\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 4 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + amp * 1.3 * (0.45 + 0.55 * sin(hue * 6.28318 + seg * 0.8))\ngreen = 0.3 + amp * 1.3 * (0.45 + 0.55 * sin(hue * 6.28318 + seg * 0.8 + 2.09))\nblue = 0.3 + amp * 1.3 * (0.45 + 0.55 * sin(hue * 6.28318 + seg * 0.8 + 4.19))\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -726,7 +727,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "roll-on mojo (duo remix)",
|
||||
author: "zamuz",
|
||||
description: "Auto-ported from the Winamp AVS preset \"04 zamuz - roll-on mojo (duo remix).avs\" by zamuz. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"04 zamuz - roll-on mojo (duo remix).avs\" by zamuz. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"swirl\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/04 zamuz - roll-on mojo (duo remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"roll-on mojo (duo remix)\"\nmode: lines\nblend: additive\npersist: 0.889\nlinewidth: 1.751\n\n[init]\nn = 950\n\n[frame]\nt = t + dt * (0.251 + bass_att * 1.8)\nhue = hue + dt * 0.089 + beat * 0.012\n\n[point]\narm = floor(i * 3)\nfa = frac(i * 3)\nd = fa\nang = arm * 1.538 + d * 1.277 * 3.14159 + t\nrad = (0.04 + pow(d, 1.775) * 1.15) * (0.7 + bass * 0.5)\nx = sin(ang) * rad / aspect\ny = cos(ang) * rad\nred = (0.3 + 0.7 * d) * (0.3 + mid) * abs(sin(d * 3.995))\ngreen = (0.3 + 0.7 * d) * (0.3 + mid) * 0.22\nblue = (0.3 + 0.7 * d) * (0.3 + mid) * abs(cos(d * 3.995))\nskip = if(below(fa, 0.04), 1, 0)\n",
|
||||
|
|
@ -735,7 +736,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "cafe de duo (vanish's wicked jungle massive remix)",
|
||||
author: "duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"05 duo - cafe de duo (vanish's wicked jungle massive remix).avs\" by duo. The original is driven by unportable scope code (frame line 19: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"05 duo - cafe de duo (vanish's wicked jungle massive remix).avs\" by duo. The original is driven by unportable scope code (frame line 19: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/05 duo - cafe de duo (vanish's wicked jungle massive remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"cafe de duo (vanish's wicked jungle massive remix)\"\nmode: lines\nblend: additive\npersist: 0.873\nlinewidth: 1.915\n\n[init]\nsegs = 10\nn = 623\n\n[frame]\nrot = rot + dt * (0.112 + mid_att * 0.5)\nhue = hue + dt * 0.038\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 9 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + amp * 1.3 * (0.25 + bass * 0.95)\ngreen = 0.3 + amp * 1.3 * (0.25 + mid * 0.95)\nblue = 0.3 + amp * 1.3 * (0.25 + treb * 0.95)\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -744,7 +745,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "incantation (duo remix - edit)",
|
||||
author: "skupers",
|
||||
description: "Auto-ported from the Winamp AVS preset \"06 skupers - incantation (duo remix - edit).avs\" by skupers. The original is driven by a trivial scope (n=4; the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"06 skupers - incantation (duo remix - edit).avs\" by skupers. The original is driven by a trivial scope (n=4; the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/06 skupers - incantation (duo remix - edit).avs",
|
||||
approx: true,
|
||||
content: "name: \"incantation (duo remix - edit)\"\nmode: lines\nblend: additive\npersist: 0.892\nlinewidth: 1.682\n\n[init]\nsegs = 14\nn = 476\n\n[frame]\nrot = rot + dt * (0.088 + mid_att * 0.5)\nhue = hue + dt * 0.074\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 6 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + amp * 1.3 * abs(sin(seg * 0.8))\ngreen = 0.3 + amp * 1.3 * 0.22\nblue = 0.3 + amp * 1.3 * abs(cos(seg * 0.8))\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -753,7 +754,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "miraculous flow (nemo remix)",
|
||||
author: "duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"07 duo - miraculous flow (nemo remix).avs\" by duo. The original is driven by UniqueTone, DynamicMovement, FastBright, which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"07 duo - miraculous flow (nemo remix).avs\" by duo. The original is driven by UniqueTone, DynamicMovement, FastBright, which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/07 duo - miraculous flow (nemo remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"miraculous flow (nemo remix)\"\nmode: lines\nblend: additive\npersist: 0.91\nlinewidth: 1.628\n\n[init]\nn = 981\n\n[frame]\nt = t + dt * (0.579 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.122\n\n[point]\na = i * 6.28318 * 3\nwob = sin(a * 6 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.202 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = min(1, 0.3 + abs(v) * 1.2 * 1.3)\ngreen = 0.3 + abs(v) * 1.2 * 0.5\nblue = 0.3 + abs(v) * 1.2 * 0.12\n",
|
||||
|
|
@ -762,7 +763,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "warm freeform (mykal remix)",
|
||||
author: "duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"08 duo - warm freeform (mykal remix).avs\" by duo. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"08 duo - warm freeform (mykal remix).avs\" by duo. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"web\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/08 duo - warm freeform (mykal remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"warm freeform (mykal remix)\"\nmode: dots\nblend: additive\npersist: 0.898\nlinewidth: 1.303\n\n[init]\nspokes = 32\nn = spokes * 37\n\n[frame]\nrot = rot + dt * (0.135 + mid * 0.4)\nt = t + dt * 2.906\nhue = hue + dt * 0.077\n\n[point]\nsp = floor(i * spokes)\nsi = frac(i * spokes)\na = sp * 6.28318 / spokes + rot\nwave = sin(si * 3 * 3.14159 - t) * (0.03 + bass * 0.28)\nrad = 0.12 + si * 0.868 + wave\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = (1 - si) * 0.45 + 0.15 + sv * 0.55 * abs(sin(sp * 0.4))\ngreen = (1 - si) * 0.45 + 0.15 + sv * 0.55 * 0.22\nblue = (1 - si) * 0.45 + 0.15 + sv * 0.55 * abs(cos(sp * 0.4))\nskip = if(above(si, 0.985), 1, 0)\n",
|
||||
|
|
@ -771,7 +772,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "pleasure point (duo remix)",
|
||||
author: "zxe",
|
||||
description: "Auto-ported from the Winamp AVS preset \"09 zxe - pleasure point (duo remix).avs\" by zxe. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"09 zxe - pleasure point (duo remix).avs\" by zxe. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/09 zxe - pleasure point (duo remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"pleasure point (duo remix)\"\nmode: lines\nblend: additive\npersist: 0.87\nlinewidth: 1.808\n\n[init]\nn = 856\n\n[frame]\nt = t + dt * 0.572\nhue = hue + dt * 0.036\n\n[point]\nph = i * 6.28318 * 2.087\nfa = 2 + mid * 0.35\nfb = 7 + bass * 0.45\nx = sin(ph * fa + t) * (0.5 + bass * 0.3) / aspect\ny = sin(ph * fb + t * 1.3 + 1.499) * (0.5 + treb * 0.35)\nred = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 0.3\ngreen = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 0.65\nblue = min(1, 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 1.3)\n",
|
||||
|
|
@ -780,7 +781,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "heart dynamics (duo's high dose mix)",
|
||||
author: "zamuz",
|
||||
description: "Auto-ported from the Winamp AVS preset \"10 zamuz - heart dynamics (duo's high dose mix).avs\" by zamuz. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"10 zamuz - heart dynamics (duo's high dose mix).avs\" by zamuz. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"ribbon\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/10 zamuz - heart dynamics (duo's high dose mix).avs",
|
||||
approx: true,
|
||||
content: "name: \"heart dynamics (duo's high dose mix)\"\nmode: lines\nblend: additive\npersist: 0.909\nlinewidth: 1.819\n\n[init]\nn = 1105\n\n[frame]\nt = t + dt * (0.35 + bass_att * 0.8)\nsway = sway + dt * (0.5 + treb)\nhue = hue + dt * 0.091\n\n[point]\na = i * 6.28318 * 3\nwob = sin(a * 5 + t * 2) * (0.08 + treb * 0.3)\nrad = (0.42 + mid * 0.25) * (0.85 + 0.15 * sin(a * 3 + sway)) + v * 0.184 - wob\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + abs(v) * 1.2 * abs(sin(a * 0.5))\ngreen = 0.3 + abs(v) * 1.2 * 0.22\nblue = 0.3 + abs(v) * 1.2 * abs(cos(a * 0.5))\n",
|
||||
|
|
@ -789,7 +790,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "we build here (duo's building blocks remix)",
|
||||
author: "nemo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"11 nemo - we build here (duo's building blocks remix).avs\" by nemo. The original is driven by DynamicMovement, BufferSave, 2.8+ Effect List Config, which the script engine cannot run — replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"11 nemo - we build here (duo's building blocks remix).avs\" by nemo. The original is driven by DynamicMovement, BufferSave, 2.8+ Effect List Config, which the script engine cannot run -- replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/11 nemo - we build here (duo's building blocks remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"we build here (duo's building blocks remix)\"\nmode: dots\nblend: additive\npersist: 0.739\nlinewidth: 2.311\n\n[init]\nn = 1183\n\n[frame]\nt = t + dt * 0.515\nhue = hue + dt * 0.134\n\n[point]\nu = rand(i * 1.7) * 2 - 1\nw = rand(i * 3.3 + 11) * 2 - 1\nm = sin((u * 6.135 + w * 2.876 + t) * 3.14159) * sin((u * 3.312 - w * 5.365 - t * 0.7) * 3.14159)\nx = u * 0.99 / aspect\ny = w * 0.98\nlum = max(0, m) * (0.3 + bass * 0.9) + 0.06\nred = min(1, lum * 1.3)\ngreen = lum * 0.5\nblue = lum * 0.12\nsize = 1 + abs(m) * 3.466\n",
|
||||
|
|
@ -798,7 +799,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "wickedjunglesmassive (yathosho's cartographic re-rub)",
|
||||
author: "duo & vanish",
|
||||
description: "Auto-ported from the Winamp AVS preset \"12 duo & vanish - wickedjunglesmassive (yathosho's cartographic re-rub).avs\" by duo & vanish. The original is driven by unportable scope code (frame line 19: Expected ')' but found ';'), which the script engine cannot run — replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"12 duo & vanish - wickedjunglesmassive (yathosho's cartographic re-rub).avs\" by duo & vanish. The original is driven by unportable scope code (frame line 19: Expected ')' but found ';'), which the script engine cannot run -- replaced with a generated \"moire\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/12 duo & vanish - wickedjunglesmassive (yathosho's cartographic re-rub).avs",
|
||||
approx: true,
|
||||
content: "name: \"wickedjunglesmassive (yathosho's cartographic re-rub)\"\nmode: dots\nblend: additive\npersist: 0.805\nlinewidth: 1.835\n\n[init]\nn = 1292\n\n[frame]\nt = t + dt * 0.675\nhue = hue + dt * 0.035\n\n[point]\nu = rand(i * 1.7) * 2 - 1\nw = rand(i * 3.3 + 11) * 2 - 1\nm = sin((u * 3.6 + w * 6.394 + t) * 3.14159) * sin((u * 5.053 - w * 4.781 - t * 0.7) * 3.14159)\nx = u * 0.897 / aspect\ny = w * 0.959\nlum = max(0, m) * (0.3 + bass * 0.9) + 0.06\nred = lum * (0.45 + 0.55 * sin(hue * 6.28318 + u * 4.308))\ngreen = lum * (0.45 + 0.55 * sin(hue * 6.28318 + u * 4.308 + 2.09))\nblue = lum * (0.45 + 0.55 * sin(hue * 6.28318 + u * 4.308 + 4.19))\nsize = 1 + abs(m) * 2.706\n",
|
||||
|
|
@ -807,7 +808,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "why i love you (duo's pulsedriver remix)",
|
||||
author: "skupers",
|
||||
description: "Auto-ported from the Winamp AVS preset \"13 skupers - why i love you (duo's pulsedriver remix).avs\" by skupers. The original is driven by a trivial scope (n=10; the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"13 skupers - why i love you (duo's pulsedriver remix).avs\" by skupers. The original is driven by a trivial scope (n=10; the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"kaleido\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/13 skupers - why i love you (duo's pulsedriver remix).avs",
|
||||
approx: true,
|
||||
content: "name: \"why i love you (duo's pulsedriver remix)\"\nmode: lines\nblend: additive\npersist: 0.843\nlinewidth: 1.547\n\n[init]\nsegs = 8\nn = 528\n\n[frame]\nrot = rot + dt * (0.074 + mid_att * 0.5)\nhue = hue + dt * 0.052\nflash = flash * 0.85\n\n[beat]\nflash = 1\n\n[point]\nseg = floor(i * segs)\nsi = frac(i * segs)\na0 = si * 6.28318 / segs + rot\namp = 0.1 + sv * 0.55 + bass * 0.25 + flash * 0.06\nrad = 0.15 + amp * (0.4 + 0.6 * sin(a0 * 6 + time * 2))\na = seg * 6.28318 / segs + a0 * if(below(seg % 2, 1), 1, -1)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nred = 0.3 + amp * 1.3 * 0.85\ngreen = 0.3 + amp * 1.3 * 0.92\nblue = 0.3 + amp * 1.3\nskip = if(above(si, 0.96), 1, 0)\n",
|
||||
|
|
@ -816,7 +817,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "conjuring sands (skupers remix - edit)",
|
||||
author: "duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"14 duo - conjuring sands (skupers remix - edit).avs\" by duo. The original is driven by a trivial scope (n=15; the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"14 duo - conjuring sands (skupers remix - edit).avs\" by duo. The original is driven by a trivial scope (n=15; the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"lissajous\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/14 duo - conjuring sands (skupers remix - edit).avs",
|
||||
approx: true,
|
||||
content: "name: \"conjuring sands (skupers remix - edit)\"\nmode: lines\nblend: additive\npersist: 0.922\nlinewidth: 2.216\n\n[init]\nn = 874\n\n[frame]\nt = t + dt * 0.211\nhue = hue + dt * 0.039\n\n[point]\nph = i * 6.28318 * 2.729\nfa = 6 + mid * 0.35\nfb = 5 + bass * 0.45\nx = sin(ph * fa + t) * (0.5 + bass * 0.3) / aspect\ny = sin(ph * fb + t * 1.3 + 1.092) * (0.5 + treb * 0.35)\nred = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * abs(sin(ph * 0.5))\ngreen = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * 0.22\nblue = 0.3 + 0.45 * sin(ph * 2 + t) + abs(v) * 0.6 * abs(cos(ph * 0.5))\n",
|
||||
|
|
@ -834,7 +835,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
folder: "root/embedded/Envision",
|
||||
name: "warm freeform (ya-tho-sho treatment)",
|
||||
author: "duo",
|
||||
description: "Auto-ported from the Winamp AVS preset \"16 duo - warm freeform (ya-tho-sho treatment).avs\" by duo. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run — replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
description: "Auto-ported from the Winamp AVS preset \"16 duo - warm freeform (ya-tho-sho treatment).avs\" by duo. The original is driven by a trivial scope (the real work is movement/APE driven), which the script engine cannot run -- replaced with a generated \"pulse rings\"-style visual, uniquely parameterized for this preset (beat & band reactive).",
|
||||
originalFile: "/avs-originals/embedded/root/embedded/Envision/16 duo - warm freeform (ya-tho-sho treatment).avs",
|
||||
approx: true,
|
||||
content: "name: \"warm freeform (ya-tho-sho treatment)\"\nmode: lines\nblend: additive\npersist: 0.855\nlinewidth: 1.459\n\n[init]\nn = 572\n\n[frame]\nhue = hue + dt * 0.129 + beat * 0.01\ntravel = travel + dt * (0.44 + bass_att * 1.4)\nflash = flash * 0.86\n\n[beat]\nflash = 1\n\n[point]\ng = floor(i * 13)\ngi = frac(i * 13)\nph = frac(rand(g * 5.1 + 1) + travel * (0.55 + rand(g + 17) * 0.85))\na = gi * 6.28318\nrad = ph * (0.305 + bass * 0.472 + flash * 0.08)\nx = sin(a) * rad / aspect\ny = cos(a) * rad\nfade = sin(ph * 3.14159)\nred = fade * (0.35 + flash * 0.4) * 0.85\ngreen = fade * (0.35 + flash * 0.4) * 0.92\nblue = fade * (0.35 + flash * 0.4)\nskip = if(above(ph, 0.96), 1, 0)\n",
|
||||
|
|
@ -853,7 +854,7 @@ export const EMBEDDED_LIBRARY: EmbeddedPreset[] = [
|
|||
name: "Prism Chandelier",
|
||||
author: "Zai",
|
||||
description:
|
||||
"Six mirrored ribbons spin as one kaleidoscope; every beat turns the color wheel a notch and the kick flares the whole prism. Hand-authored for OVE — hsv rainbow + beatage kick envelope.",
|
||||
"Six mirrored ribbons spin as one kaleidoscope; every beat turns the color wheel a notch and the kick flares the whole prism. Hand-authored for OVE -- hsv rainbow + beatage kick envelope.",
|
||||
content: `name: "Prism Chandelier"
|
||||
author: "Zai"
|
||||
mode: lines
|
||||
|
|
@ -896,7 +897,7 @@ skip = if(below(si, 0.015), 1, 0)
|
|||
name: "Neon Heartbeat",
|
||||
author: "Zai",
|
||||
description:
|
||||
"A solid-mode bloom that throbs with the bass — the fill hue jumps on every beat and the petals breathe on the kick envelope. Hand-authored for OVE (solid mode + hsv color).",
|
||||
"A solid-mode bloom that throbs with the bass -- the fill hue jumps on every beat and the petals breathe on the kick envelope. Hand-authored for OVE (solid mode + hsv color).",
|
||||
content: `name: "Neon Heartbeat"
|
||||
author: "Zai"
|
||||
mode: solid
|
||||
|
|
@ -935,7 +936,7 @@ skip = if(below(li, 0.008), 1, 0)
|
|||
name: "Spectrum Serpent",
|
||||
author: "Zai",
|
||||
description:
|
||||
"An oscilloscope serpent coiled into a spiral — the body swells where the spectrum is loud and the rainbow shifts a step on every beat. Hand-authored for OVE.",
|
||||
"An oscilloscope serpent coiled into a spiral -- the body swells where the spectrum is loud and the rainbow shifts a step on every beat. Hand-authored for OVE.",
|
||||
content: `name: "Spectrum Serpent"
|
||||
author: "Zai"
|
||||
mode: lines
|
||||
|
|
@ -973,7 +974,7 @@ alpha = 0.45 + 0.55 * sin(i * pi)
|
|||
name: "Bass Bloom",
|
||||
author: "Zai",
|
||||
description:
|
||||
"A fountain of 480 megabuf particles launched by every beat — each petal carries the exact hue of the beat that spawned it, so the falling arcs leave a rainbow memory of the music. Hand-authored for OVE.",
|
||||
"A fountain of 480 megabuf particles launched by every beat -- each petal carries the exact hue of the beat that spawned it, so the falling arcs leave a rainbow memory of the music. Hand-authored for OVE.",
|
||||
content: `name: "Bass Bloom"
|
||||
author: "Zai"
|
||||
mode: dots
|
||||
|
|
@ -1087,7 +1088,7 @@ skip = if(above(vert, sides + 0.5), 1, 0)
|
|||
name: "Aurora Veil",
|
||||
author: "Zai",
|
||||
description:
|
||||
"Nine waving curtains, each lit by its own frequency band (getspec) — the whole color scheme drifts once per 4-beat bar for slow, breathing color changes. Hand-authored for OVE.",
|
||||
"Nine waving curtains, each lit by its own frequency band (getspec) -- the whole color scheme drifts once per 4-beat bar for slow, breathing color changes. Hand-authored for OVE.",
|
||||
content: `name: "Aurora Veil"
|
||||
author: "Zai"
|
||||
mode: lines
|
||||
|
|
@ -1128,7 +1129,7 @@ skip = if(below(ci, 0.01), 1, 0)
|
|||
name: "Supernova",
|
||||
author: "Zai",
|
||||
description:
|
||||
"Every beat detonates the entire 620-particle field — shells leave the core white-hot and saturate into the beat's hue as they expand and cool. Hand-authored for OVE (megabuf physics + drag).",
|
||||
"Every beat detonates the entire 620-particle field -- shells leave the core white-hot and saturate into the beat's hue as they expand and cool. Hand-authored for OVE (megabuf physics + drag).",
|
||||
content: `name: "Supernova"
|
||||
author: "Zai"
|
||||
mode: dots
|
||||
|
|
@ -1195,7 +1196,7 @@ if(above(age, 0),
|
|||
name: "Tunnel Vision",
|
||||
author: "Zai",
|
||||
description:
|
||||
"A tunnel of rings where every ring carries the hue of the beat it was born on — each kick sends a new color wave riding out from the center. Hand-authored for OVE.",
|
||||
"A tunnel of rings where every ring carries the hue of the beat it was born on -- each kick sends a new color wave riding out from the center. Hand-authored for OVE.",
|
||||
content: `name: "Tunnel Vision"
|
||||
author: "Zai"
|
||||
mode: lines
|
||||
|
|
@ -1239,7 +1240,7 @@ skip = if(above(dot, per - 1.5), 1, 0)
|
|||
name: "Lissajous Loom",
|
||||
author: "Zai",
|
||||
description:
|
||||
"A lissajous weave that re-threads its frequency ratio once per 4-beat bar while the rainbow rotates on every single beat — the pattern morphs in color and shape together. Hand-authored for OVE.",
|
||||
"A lissajous weave that re-threads its frequency ratio once per 4-beat bar while the rainbow rotates on every single beat -- the pattern morphs in color and shape together. Hand-authored for OVE.",
|
||||
content: `name: "Lissajous Loom"
|
||||
author: "Zai"
|
||||
mode: lines
|
||||
|
|
@ -1279,7 +1280,7 @@ alpha = 0.55 + 0.45 * sin(ph * fa)
|
|||
name: "Beat Matrix",
|
||||
author: "Zai",
|
||||
description:
|
||||
"A 16-band spectrum wall — every beat rotates the entire rainbow across the columns and whitewashes the lit cells for one strobe flash. Hand-authored for OVE (direct getspec bands).",
|
||||
"A 16-band spectrum wall -- every beat rotates the entire rainbow across the columns and whitewashes the lit cells for one strobe flash. Hand-authored for OVE (direct getspec bands).",
|
||||
content: `name: "Beat Matrix"
|
||||
author: "Zai"
|
||||
mode: dots
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ export class AvaEngine {
|
|||
}
|
||||
|
||||
getScriptName(): string {
|
||||
return this.script?.meta.name ?? '—'
|
||||
return this.script?.meta.name ?? '--'
|
||||
}
|
||||
|
||||
private resize(): void {
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ function tokenize(src: string, baseLine: number): Token[] {
|
|||
const tokens: Token[] = []
|
||||
let i = 0
|
||||
let line = baseLine
|
||||
let depth = 0 // paren depth — newlines inside parens are not separators
|
||||
let depth = 0 // paren depth -- newlines inside parens are not separators
|
||||
// Kind of each open paren ('loop' vs 'expr') — newlines directly inside a
|
||||
// loop( body ARE statement separators (AVS-eel loop semantics).
|
||||
const parenKinds: ('loop' | 'expr')[] = []
|
||||
|
|
@ -316,7 +316,7 @@ class Parser {
|
|||
stmts.push(this.parseAssignExpr())
|
||||
const after = this.peek()
|
||||
if (after && !(after.type === 'op' && after.value === ';')) {
|
||||
throw new ExpressionError(`Unexpected '${after.value}' — separate statements with ';' or a newline`, after.line)
|
||||
throw new ExpressionError(`Unexpected '${after.value}' -- separate statements with ';' or a newline`, after.line)
|
||||
}
|
||||
}
|
||||
return stmts
|
||||
|
|
@ -520,7 +520,7 @@ class Parser {
|
|||
this.next() // '('
|
||||
const count = this.parseAssignExpr()
|
||||
if (!this.atOp(',')) {
|
||||
throw new ExpressionError('loop(count, body) — expected a body after the count', t.line)
|
||||
throw new ExpressionError('loop(count, body) -- expected a body after the count', t.line)
|
||||
}
|
||||
this.next()
|
||||
const body: Node[] = []
|
||||
|
|
@ -531,7 +531,7 @@ class Parser {
|
|||
body.push(this.parseAssignExpr())
|
||||
const after = this.peek()
|
||||
if (after && !(after.type === 'op' && (after.value === ';' || after.value === ')'))) {
|
||||
throw new ExpressionError(`Unexpected '${after.value}' in loop body — separate statements with ';'`, after.line)
|
||||
throw new ExpressionError(`Unexpected '${after.value}' in loop body -- separate statements with ';'`, after.line)
|
||||
}
|
||||
}
|
||||
this.expectOp(')')
|
||||
|
|
@ -594,7 +594,7 @@ class Parser {
|
|||
stmts.push(this.parseAssignExpr())
|
||||
const after = this.peek()
|
||||
if (after && !(after.type === 'op' && (after.value === ';' || after.value === ',' || after.value === ')'))) {
|
||||
throw new ExpressionError(`Unexpected '${after.value}' — separate statements with ';'`, after.line)
|
||||
throw new ExpressionError(`Unexpected '${after.value}' -- separate statements with ';'`, after.line)
|
||||
}
|
||||
}
|
||||
if (this.atOp(')')) this.next()
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export async function exportPresetsZip(
|
|||
try {
|
||||
const inScope = presets.filter((p) => subtreeOf(folderPath)(p.folderPath))
|
||||
if (inScope.length === 0) {
|
||||
return { ok: false, error: 'That folder is empty — nothing to export.' }
|
||||
return { ok: false, error: 'That folder is empty -- nothing to export.' }
|
||||
}
|
||||
const folderSet = new Set(folders.filter(subtreeOf(folderPath)))
|
||||
for (const p of inScope) {
|
||||
|
|
@ -109,7 +109,7 @@ export async function importPresetsZip(
|
|||
const entries = Object.values(zip.files).filter((e) => !e.dir)
|
||||
if (entries.length === 0) return { ok: false, error: 'That zip is empty.' }
|
||||
if (entries.length > MAX_ZIP_ENTRIES) {
|
||||
return { ok: false, error: `That zip has too many entries (${entries.length} — limit ${MAX_ZIP_ENTRIES}).` }
|
||||
return { ok: false, error: `That zip has too many entries (${entries.length} -- limit ${MAX_ZIP_ENTRIES}).` }
|
||||
}
|
||||
|
||||
const target = isUserAreaPath(selectedFolder) ? selectedFolder : USER_ROOT
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export interface BuiltinPreset {
|
|||
content: string
|
||||
}
|
||||
|
||||
export const STARTER_TEMPLATE = `# AVA visualization script — starter template
|
||||
export const STARTER_TEMPLATE = `# AVA visualization script -- starter template
|
||||
# Tap "Help" in the editor for the full variable & function reference.
|
||||
name: My Visualization
|
||||
author: you
|
||||
|
|
@ -94,7 +94,7 @@ blue = 0.5 + 0.5 * sin(hue * 6.28318 + 4.188)
|
|||
name: "wonder 'bout",
|
||||
author: 'zamuz (adapted)',
|
||||
description:
|
||||
'A field of rings that spawn, expand and fade — each at its own tempo, sized by the bass, in stable per-ring colors (the original spawned Texer II ring sprites with random colors and bass-scaled sizes). From the visbot.net classic by zamuz.',
|
||||
'A field of rings that spawn, expand and fade -- each at its own tempo, sized by the bass, in stable per-ring colors (the original spawned Texer II ring sprites with random colors and bass-scaled sizes). From the visbot.net classic by zamuz.',
|
||||
originalFile: '/avs-originals/zamuz - wonder bout.avs',
|
||||
content: `# Adapted from "wonder 'bout" by zamuz (Winamp AVS / visbot.net)
|
||||
# The original spawned Texer II ring sprites: ss = ss + .05 per frame,
|
||||
|
|
@ -142,7 +142,7 @@ skip = if(below(gi, 0.025), 1, 0)
|
|||
name: 'Quantization',
|
||||
author: 'synth-c (adapted)',
|
||||
description:
|
||||
'Audio-reactive rings snapped to a pixel grid — the original quantized scope coordinates ((x*40)|0)/40 and rendered a sound heightmap as dot fog. Here the rings are quantized dots that thicken with the mid range.',
|
||||
'Audio-reactive rings snapped to a pixel grid -- the original quantized scope coordinates ((x*40)|0)/40 and rendered a sound heightmap as dot fog. Here the rings are quantized dots that thicken with the mid range.',
|
||||
originalFile: '/avs-originals/Synth-C - Quantization.avs',
|
||||
content: `# Adapted from "Synth-C - Quantization" (Winamp AVS / visbot.net)
|
||||
# Original Superscope: r = i*2pi; d = snd + .5; x = sin(r)*d; y = cos(r)*d
|
||||
|
|
@ -184,7 +184,7 @@ size = 2 + mid * 5
|
|||
name: "keep tryin'",
|
||||
author: 'zamuz (adapted)',
|
||||
description:
|
||||
"Bass-driven particle bursts that expand outward with a sinusoidal swirl — the original spawned white Texer dots with radius = bass*3+.3 and pushed the screen through sin(y*20) swirl movements. Dot size follows the highs.",
|
||||
"Bass-driven particle bursts that expand outward with a sinusoidal swirl -- the original spawned white Texer dots with radius = bass*3+.3 and pushed the screen through sin(y*20) swirl movements. Dot size follows the highs.",
|
||||
originalFile: '/avs-originals/zamuz - keep tryin.avs',
|
||||
content: `# Adapted from "keep tryin'" by zamuz (Winamp AVS / visbot.net)
|
||||
# Original Texer II dots: rs = getspec(.1,.1,0)*3 + .3 on spawn,
|
||||
|
|
@ -226,9 +226,9 @@ size = 1.5 + treb * 3
|
|||
name: 'vorticity',
|
||||
author: 'synth-c / zamuz (adapted)',
|
||||
description:
|
||||
'Swirling spiral arms rotating in a vortex — the original advected 3D particle trails through a rotating vector field at sound-driven speed. Here six arms twist harder as the mid range rises and the whole vortex spins with the bass.',
|
||||
'Swirling spiral arms rotating in a vortex -- the original advected 3D particle trails through a rotating vector field at sound-driven speed. Here six arms twist harder as the mid range rises and the whole vortex spins with the bass.',
|
||||
originalFile: '/avs-originals/zamuz - vorticity brain activity remix.avs',
|
||||
content: `# Adapted from "vorticity (brain activity remix)" — original by synth-c,
|
||||
content: `# Adapted from "vorticity (brain activity remix)" -- original by synth-c,
|
||||
# remix by zamuz (Winamp AVS / visbot.net). The original ran 3D particle
|
||||
# trails through rotating vector fields at sound-driven speed (sndspd = 10).
|
||||
name: vorticity
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ async function playIndex(gen: number, index: number): Promise<void> {
|
|||
if (reason !== null) {
|
||||
toast({
|
||||
title: 'Track skipped',
|
||||
description: `${entry.title} — ${reason}`,
|
||||
description: `${entry.title} -- ${reason}`,
|
||||
variant: 'destructive',
|
||||
})
|
||||
}
|
||||
|
|
@ -264,13 +264,13 @@ async function playIndex(gen: number, index: number): Promise<void> {
|
|||
setQueue({ status: 'blocked', lastError: played.error ?? null })
|
||||
toast({
|
||||
title: 'Auto-advance paused',
|
||||
description: 'The browser blocked automatic playback — press Resume to continue the queue.',
|
||||
description: 'The browser blocked automatic playback -- press Resume to continue the queue.',
|
||||
})
|
||||
return
|
||||
}
|
||||
toast({
|
||||
title: 'Track skipped',
|
||||
description: `${entry.title} — ${played.error ?? 'playback failed.'}`,
|
||||
description: `${entry.title} -- ${played.error ?? 'playback failed.'}`,
|
||||
variant: 'destructive',
|
||||
})
|
||||
handleTrackFailure(gen, index, played.error ?? 'playback failed.', null)
|
||||
|
|
@ -289,7 +289,7 @@ function handleTrackFailure(gen: number, index: number, reason: string | null, c
|
|||
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
||||
setQueue({
|
||||
status: 'error',
|
||||
lastError: reason ?? 'Several tracks in a row could not be loaded — the queue paused to avoid hammering the resolver.',
|
||||
lastError: reason ?? 'Several tracks in a row could not be loaded -- the queue paused to avoid hammering the resolver.',
|
||||
lastErrorCode: code,
|
||||
})
|
||||
toast({
|
||||
|
|
@ -299,7 +299,7 @@ function handleTrackFailure(gen: number, index: number, reason: string | null, c
|
|||
})
|
||||
return
|
||||
}
|
||||
toast({ title: 'Skipping to the next track', description: 'The failed one stays in the list — jump back anytime.' })
|
||||
toast({ title: 'Skipping to the next track', description: 'The failed one stays in the list -- jump back anytime.' })
|
||||
void playIndex(gen, index + 1)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ function tryParse(text: string): { script: AvaScript | null; meta?: ScriptMeta;
|
|||
flushSection()
|
||||
const name = sectionMatch[1].toLowerCase()
|
||||
if (!SECTION_NAMES.has(name)) {
|
||||
return { script: null, meta: { ...meta }, error: { message: `Unknown section '[${name}]' — valid sections: init, frame, beat, point`, section: name, line: lineNo } }
|
||||
return { script: null, meta: { ...meta }, error: { message: `Unknown section '[${name}]' -- valid sections: init, frame, beat, point`, section: name, line: lineNo } }
|
||||
}
|
||||
if (sections[name]) {
|
||||
return { script: null, meta: { ...meta }, error: { message: `Duplicate section '[${name}]'`, section: name, line: lineNo } }
|
||||
|
|
@ -133,12 +133,12 @@ function tryParse(text: string): { script: AvaScript | null; meta?: ScriptMeta;
|
|||
if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('//')) continue
|
||||
const headerMatch = trimmed.match(/^([a-zA-Z]+)\s*:\s*(.*)$/)
|
||||
if (!headerMatch) {
|
||||
return { script: null, meta: { ...meta }, error: { message: `Expected 'key: value' header or a [section] — got '${trimmed}'`, section: 'header', line: lineNo } }
|
||||
return { script: null, meta: { ...meta }, error: { message: `Expected 'key: value' header or a [section] -- got '${trimmed}'`, section: 'header', line: lineNo } }
|
||||
}
|
||||
const key = headerMatch[1].toLowerCase()
|
||||
const value = headerMatch[2].trim()
|
||||
if (!HEADER_KEYS.has(key)) {
|
||||
return { script: null, meta: { ...meta }, error: { message: `Unknown header key '${key}' — valid keys: name, author, description, mode, blend, persist, linewidth`, section: 'header', line: lineNo } }
|
||||
return { script: null, meta: { ...meta }, error: { message: `Unknown header key '${key}' -- valid keys: name, author, description, mode, blend, persist, linewidth`, section: 'header', line: lineNo } }
|
||||
}
|
||||
// v7.2: string headers may be written quoted (name: "Bass Bloom") —
|
||||
// strip one layer of matching surrounding quotes so the footer reads
|
||||
|
|
|
|||
|
|
@ -503,7 +503,7 @@ const DIGIT_BLOCKS: Array<[number, number]> = [
|
|||
const DIGIT_BLOCK0_SIZE = DIGIT_BLOCKS[0][1] - DIGIT_BLOCKS[0][0] + 1
|
||||
const BIG_BASE = DIGIT_BLOCK0_SIZE + (DIGIT_BLOCKS[1][1] - DIGIT_BLOCKS[1][0] + 1) // 32164
|
||||
const BIG_BASE_N = BigInt(BIG_BASE)
|
||||
const BITS_PER_DIGIT = 14 // floor(log2(32164)) — bitmap digits carry 14 bits
|
||||
const BITS_PER_DIGIT = 14 // floor(log2(32164)) -- bitmap digits carry 14 bits
|
||||
|
||||
function digitChar(d: number): string {
|
||||
return d < DIGIT_BLOCK0_SIZE
|
||||
|
|
@ -884,7 +884,7 @@ function decodeDictBody(body: string): string {
|
|||
out += next
|
||||
i++
|
||||
} else {
|
||||
out += c // trailing lone escape — be lenient
|
||||
out += c // trailing lone escape -- be lenient
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
|
@ -1179,8 +1179,8 @@ export function decodeScriptHash(input: string): HashDecodeResult {
|
|||
return {
|
||||
ok: false,
|
||||
error: looksCutOff
|
||||
? 'This share string looks cut off — it should end with "]". Copy the whole string and try again.'
|
||||
: 'This does not look like an OVE share string — it should read like "My Script:[▼…]".',
|
||||
? 'This share string looks cut off -- it should end with "]". Copy the whole string and try again.'
|
||||
: 'This does not look like an OVE share string -- it should read like "My Script:[▼…]".',
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1188,7 +1188,7 @@ export function decodeScriptHash(input: string): HashDecodeResult {
|
|||
if (payload.length < 9 || !isCheckDigit(payload[payload.length - 8])) {
|
||||
return {
|
||||
ok: false,
|
||||
error: 'This share string looks cut off — the 8 check digits at its end are missing. Copy the whole string and try again.',
|
||||
error: 'This share string looks cut off -- the 8 check digits at its end are missing. Copy the whole string and try again.',
|
||||
}
|
||||
}
|
||||
const digits = payload.slice(-8)
|
||||
|
|
@ -1196,7 +1196,7 @@ export function decodeScriptHash(input: string): HashDecodeResult {
|
|||
if (!isCheckDigit(d)) {
|
||||
return {
|
||||
ok: false,
|
||||
error: 'This share string looks cut off — the 8 check digits at its end are missing. Copy the whole string and try again.',
|
||||
error: 'This share string looks cut off -- the 8 check digits at its end are missing. Copy the whole string and try again.',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1221,7 +1221,7 @@ export function decodeScriptHash(input: string): HashDecodeResult {
|
|||
if (dictBody === null) {
|
||||
return {
|
||||
ok: false,
|
||||
error: 'This share string is damaged — its packing header does not parse. Copy the whole string and try again.',
|
||||
error: 'This share string is damaged -- its packing header does not parse. Copy the whole string and try again.',
|
||||
}
|
||||
}
|
||||
script = decodeDictBody(dictBody)
|
||||
|
|
@ -1235,7 +1235,7 @@ export function decodeScriptHash(input: string): HashDecodeResult {
|
|||
if (checkDigits(fnv1a(script)) !== digits) {
|
||||
return {
|
||||
ok: false,
|
||||
error: 'The check digits do not match — the string was altered or cut off while copying. Copy the whole string and try again.',
|
||||
error: 'The check digits do not match -- the string was altered or cut off while copying. Copy the whole string and try again.',
|
||||
}
|
||||
}
|
||||
return { ok: true, script, name }
|
||||
|
|
@ -1249,5 +1249,5 @@ export const SHARE_LEGEND: ReadonlyArray<{ symbol: string; meaning: string }> =
|
|||
{ symbol: '♦', meaning: 'space' },
|
||||
{ symbol: '♡', meaning: 'beats' },
|
||||
{ symbol: '♠', meaning: 'beatage' },
|
||||
{ symbol: '一', meaning: 'one packed digit — 15 bits of script' },
|
||||
{ symbol: '一', meaning: 'one packed digit -- 15 bits of script' },
|
||||
]
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ function writeUserStore(payload: UserStorePayload): UserResult {
|
|||
return {
|
||||
ok: false,
|
||||
error:
|
||||
'Browser storage is full or unavailable — delete some user presets (they live only in this browser).',
|
||||
'Browser storage is full or unavailable -- delete some user presets (they live only in this browser).',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -384,7 +384,7 @@ export function importUserPresets(
|
|||
const now = Date.now()
|
||||
for (const entry of entries) {
|
||||
if (presets.length >= MAX_USER_PRESETS) {
|
||||
return { ok: false, error: `User preset limit reached (${MAX_USER_PRESETS} in this browser) — import stopped.` }
|
||||
return { ok: false, error: `User preset limit reached (${MAX_USER_PRESETS} in this browser) -- import stopped.` }
|
||||
}
|
||||
const folderPath = validUserFolder(entry.folderPath)
|
||||
const name = isValidUserName(entry.name)
|
||||
|
|
|
|||
|
|
@ -71,10 +71,10 @@ export const SERVICES: ServiceDef[] = [
|
|||
domains: ['youtube.com', 'youtu.be', 'music.youtube.com'],
|
||||
cookieDomain: '.youtube.com',
|
||||
blurb:
|
||||
'One Google login covers both YouTube and YouTube Music — playlists, liked music and uploads, and no more "confirm you are not a bot" walls.',
|
||||
'One Google login covers both YouTube and YouTube Music -- playlists, liked music and uploads, and no more "confirm you are not a bot" walls.',
|
||||
steps: cookieSteps(
|
||||
'youtube.com (or music.youtube.com)',
|
||||
'Paste the whole thing below — a working YouTube login is the FULL set of ~20 cookies (SID, SAPISID, __Secure-3PSID, LOGIN_INFO, …), never a single cookie on its own.',
|
||||
'Paste the whole thing below -- a working YouTube login is the FULL set of ~20 cookies (SID, SAPISID, __Secure-3PSID, LOGIN_INFO, …), never a single cookie on its own.',
|
||||
),
|
||||
criticalCookies: ['SID', 'HSID', 'SSID', 'SAPISID', '__Secure-3PSID', 'LOGIN_INFO'],
|
||||
streamStatus: 'live',
|
||||
|
|
@ -90,7 +90,7 @@ export const SERVICES: ServiceDef[] = [
|
|||
'Access your private playlists, likes and sets from the Link button on this machine.',
|
||||
steps: cookieSteps(
|
||||
'soundcloud.com',
|
||||
'Paste the whole thing below — the cookie that carries your login is oauth_token (plus a few others).',
|
||||
'Paste the whole thing below -- the cookie that carries your login is oauth_token (plus a few others).',
|
||||
),
|
||||
criticalCookies: ['oauth_token'],
|
||||
streamStatus: 'live',
|
||||
|
|
@ -103,15 +103,15 @@ export const SERVICES: ServiceDef[] = [
|
|||
domains: ['spotify.com', 'open.spotify.com'],
|
||||
cookieDomain: '.spotify.com',
|
||||
blurb: 'Store your Spotify login so playlist links resolve with your account.',
|
||||
note: 'Spotify streams are DRM-protected, so playback of Spotify links is not possible yet — your login is saved for when support arrives.',
|
||||
note: 'Spotify streams are DRM-protected, so playback of Spotify links is not possible yet -- your login is saved for when support arrives.',
|
||||
steps: cookieSteps(
|
||||
'open.spotify.com',
|
||||
'Paste the whole thing below — the cookie that carries your login is sp_dc.',
|
||||
'Paste the whole thing below -- the cookie that carries your login is sp_dc.',
|
||||
),
|
||||
criticalCookies: ['sp_dc'],
|
||||
streamStatus: 'coming-soon',
|
||||
comingSoonNote:
|
||||
'Spotify playback is coming in a later update — your saved Spotify login will be used automatically the moment it ships. Meanwhile, YouTube, SoundCloud and direct-file links work today.',
|
||||
'Spotify playback is coming in a later update -- your saved Spotify login will be used automatically the moment it ships. Meanwhile, YouTube, SoundCloud and direct-file links work today.',
|
||||
},
|
||||
{
|
||||
id: 'apple',
|
||||
|
|
@ -121,11 +121,11 @@ export const SERVICES: ServiceDef[] = [
|
|||
domains: ['music.apple.com', 'apple.com'],
|
||||
cookieDomain: '.apple.com',
|
||||
blurb: 'Store your Apple Music login so library links resolve with your account.',
|
||||
note: 'Apple Music streams are DRM-protected, so playback of Apple Music links is not possible yet — your login is saved for when support arrives.',
|
||||
note: 'Apple Music streams are DRM-protected, so playback of Apple Music links is not possible yet -- your login is saved for when support arrives.',
|
||||
steps: cookieSteps('music.apple.com', 'Paste the whole thing below.'),
|
||||
streamStatus: 'coming-soon',
|
||||
comingSoonNote:
|
||||
'Apple Music playback is coming in a later update — your saved Apple Music login will be used automatically the moment it ships. Meanwhile, YouTube, SoundCloud and direct-file links work today.',
|
||||
'Apple Music playback is coming in a later update -- your saved Apple Music login will be used automatically the moment it ships. Meanwhile, YouTube, SoundCloud and direct-file links work today.',
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ export const SERVICES: ServiceDef[] = [
|
|||
function cookieSteps(host: string, lastStep: string): string[] {
|
||||
return [
|
||||
`Open ${host} in this browser and make sure you are logged in.`,
|
||||
'Easiest (one click): install a cookie exporter — “Get cookies.txt LOCALLY” on Chrome/Edge/Brave or “cookies.txt” on Firefox. Open that page, click the extension, choose Export — then drag the downloaded file straight into the box below (no need to open or copy anything).',
|
||||
'Easiest (one click): install a cookie exporter -- “Get cookies.txt LOCALLY” on Chrome/Edge/Brave or “cookies.txt” on Firefox. Open that page, click the extension, choose Export -- then drag the downloaded file straight into the box below (no need to open or copy anything).',
|
||||
'No extension? Press F12 → Network tab → reload the page → click the first request in the list (the page itself). The list stays empty until you reload with the tab open.',
|
||||
'Scroll down to the “Request Headers” section → find the “cookie:” row → right-click its value → Copy value. (In Firefox this lives on the request’s Headers tab too.)',
|
||||
lastStep,
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ async function getOrCreateKey(): Promise<CryptoKey> {
|
|||
if (found && found.key instanceof CryptoKey) return found.key
|
||||
const key = await crypto.subtle.generateKey(
|
||||
{ name: 'AES-GCM', length: 256 },
|
||||
false, // non-extractable — the raw key never leaves the browser key store
|
||||
false, // non-extractable -- the raw key never leaves the browser key store
|
||||
['encrypt', 'decrypt'],
|
||||
)
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
|
|
@ -191,13 +191,13 @@ export async function saveMusicSession(
|
|||
): Promise<{ ok: true } | { ok: false; error: string }> {
|
||||
const text = cookieText.trim()
|
||||
if (text.length < 8) {
|
||||
return { ok: false, error: 'That looks too short to be a cookie — paste the whole Cookie header value or a cookies.txt export.' }
|
||||
return { ok: false, error: 'That looks too short to be a cookie -- paste the whole Cookie header value or a cookies.txt export.' }
|
||||
}
|
||||
if (text.length > MAX_COOKIE_LENGTH) {
|
||||
return { ok: false, error: 'That cookie data is too large (over 64KB).' }
|
||||
}
|
||||
if (!cryptoAvailable()) {
|
||||
return { ok: false, error: 'This browser context is not secure (needs https) — logins cannot be stored here.' }
|
||||
return { ok: false, error: 'This browser context is not secure (needs https) -- logins cannot be stored here.' }
|
||||
}
|
||||
try {
|
||||
const key = await getOrCreateKey()
|
||||
|
|
|
|||
|
|
@ -1,19 +1,25 @@
|
|||
// OVE — release notes for the "What's New!" dialog (v7.6).
|
||||
// OVE -- release notes for the "What's New!" dialog (v7.6).
|
||||
//
|
||||
// The visitor-facing changelog, newest release first. This is the ONE place
|
||||
// to update when shipping a version: every bump of APP_VERSION in version.ts
|
||||
// must come with a matching entry at the top of RELEASE_NOTES (a dev-mode
|
||||
// guard below warns in the console when the two drift apart).
|
||||
//
|
||||
// Keep entries brief — one line per change, written for visitors (what they
|
||||
// VOICE (v7.10): I write these notes myself, in the first person -- "I
|
||||
// added…", "I fixed…" -- as a build diary. Never address the reader ("you"
|
||||
// / "your"), never speak of myself in the third person; when the visitor is
|
||||
// relevant, "the visitor" / "each browser". Punctuation: no em dashes --
|
||||
// a plain double minus ( -- ) everywhere.
|
||||
//
|
||||
// Keep entries brief -- one line per change, written for visitors (what they
|
||||
// can now do / what stopped breaking), not for the build log. The verbose
|
||||
// engineering history still lives in version.ts; this file is the digest.
|
||||
//
|
||||
// Change kinds shown in the dialog:
|
||||
// added — new capability
|
||||
// improved — made better/faster/ friendlier
|
||||
// fixed — a bug that stopped reproducing
|
||||
// removed — taken away (with the reason in the text)
|
||||
// added -- new capability
|
||||
// improved -- made better/faster/ friendlier
|
||||
// fixed -- a bug that stopped reproducing
|
||||
// removed -- taken away (with the reason in the text)
|
||||
|
||||
import { APP_VERSION } from '@/lib/version'
|
||||
|
||||
|
|
@ -33,17 +39,39 @@ export interface ReleaseNote {
|
|||
}
|
||||
|
||||
export const RELEASE_NOTES: ReleaseNote[] = [
|
||||
{
|
||||
version: '7.10',
|
||||
name: 'Ten demo tracks, my own voice',
|
||||
changes: [
|
||||
{
|
||||
kind: 'added',
|
||||
text: 'A ten-track Demo collection replaces the single demo track. Each Demo Track click plays once through; the next click (or the Stop button) advances to the next track in filename order, wrapping back to Track 1 after Track 10. Each visitor’s place in the collection is saved in their browser, so returning later picks up where they left off.',
|
||||
},
|
||||
{
|
||||
kind: 'improved',
|
||||
text: 'I rewrote these notes in my own voice -- first person, as my build diary. No more third-person marketing copy.',
|
||||
},
|
||||
{
|
||||
kind: 'removed',
|
||||
text: 'Redundant helper text across the site -- the landing menu’s source list, the presets panel’s read-only paragraph, the mix-mode hints, the settings descriptions, the link dialog’s footnote and the footer’s “engine ok” dot. The interface trusts its own labels now.',
|
||||
},
|
||||
{
|
||||
kind: 'improved',
|
||||
text: 'Every em dash in the interface replaced with a plain double minus ( -- ).',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '7.9',
|
||||
name: 'Footer credit + changelog polish',
|
||||
changes: [
|
||||
{
|
||||
kind: 'added',
|
||||
text: 'The footer now signs the work — “© 2026 · Site Created & Deployed by Sum’ting White” (year always current) with a clickable “View my portfolio at zcreations.dev” that opens the portfolio in a new tab.',
|
||||
text: 'My signature in the footer -- “© 2026 · Site Created & Deployed by Sum’ting White” (the year always current) with a link to my portfolio at zcreations.dev.',
|
||||
},
|
||||
{
|
||||
kind: 'improved',
|
||||
text: 'What’s New tidy-up: a theme-matched divider now sits above every release box, and the Added / Improved / Fixed / Removed tags right-align against an invisible column so every description lines up on the same edge.',
|
||||
text: 'What’s New tidy-up -- a theme-matched divider above every release box, and the change tags right-aligned against an invisible column so every description lines up on the same edge.',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -53,15 +81,15 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
changes: [
|
||||
{
|
||||
kind: 'improved',
|
||||
text: 'Script⇢Hash strings are now ~72% shorter than the script (was ~49%) — the median share string is about a QUARTER of the script’s length. “1400” now costs less than one character: the whole script is packed into CJK + Hangul digits carrying ~15 bits apiece (your base-62 idea, with 32,164 digits instead of 62).',
|
||||
text: 'I rebuilt the share codec -- Script⇢Hash strings are now ~72% shorter than the script (was ~49%); the median share string is about a QUARTER of the script’s length. “1400” now costs less than one character: the whole script packs into CJK + Hangul digits carrying ~15 bits apiece.',
|
||||
},
|
||||
{
|
||||
kind: 'improved',
|
||||
text: 'The symbol dictionary grew ~170 data-mined entries — every function with its open paren, every audio variable, AVS idioms like “hue = hue + dt * ”, header lines like “linewidth: ”, and ~70 number literals.',
|
||||
text: 'I grew the symbol dictionary by ~170 data-mined entries -- every function with its open paren, every audio variable, AVS idioms like “hue = hue + dt * ”, header lines like “linewidth: ”, and ~70 number literals.',
|
||||
},
|
||||
{
|
||||
kind: 'added',
|
||||
text: 'Share strings from v7.7 (the ▲ ones) still paste back perfectly — and short scripts keep the readable symbol form, since the encoder always picks whichever is shorter.',
|
||||
text: 'v7.7 strings (the ▲ ones) still paste back perfectly -- and short scripts keep the readable symbol form, since the encoder always picks whichever is shorter.',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -71,34 +99,34 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
changes: [
|
||||
{
|
||||
kind: 'added',
|
||||
text: 'Script⇢Hash / Hash⇢Script — turn your script into ONE short Unicode string (♠ ♡ ♦ built-in references, ~half the length) and post it anywhere; anyone pastes it back and your script returns exactly as written.',
|
||||
text: 'I built Script⇢Hash / Hash⇢Script -- turn a script into ONE short Unicode string (♠ ♡ ♦ built-in references, ~half the length) and post it anywhere; anyone pastes it back and the script returns exactly as written.',
|
||||
},
|
||||
{
|
||||
kind: 'added',
|
||||
text: 'Share strings work even when the script doesn\u2019t compile — share work in progress to get help, advice or debugging.',
|
||||
text: 'Share strings work even when the script doesn’t compile -- share work in progress to get help, advice or debugging.',
|
||||
},
|
||||
{
|
||||
kind: 'added',
|
||||
text: 'Every string ends in check digits, so one that was cut off by a character limit is refused honestly instead of decoding into garbage.',
|
||||
text: 'Every string ends in check digits, so one cut off by a character limit is refused honestly instead of decoding into garbage.',
|
||||
},
|
||||
{
|
||||
kind: 'removed',
|
||||
text: 'The Music Services log in / “log out of all” section in Settings — the built-in account already plays links for everyone (it returns, reworked, in a later update).',
|
||||
text: 'The Music Services log in / “log out of all” section in Settings -- the built-in account already plays links for everyone (it returns, reworked, in a later update).',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '7.6.1',
|
||||
changes: [
|
||||
{ kind: 'removed', text: 'The “Set Beat” button from the header — tap-tempo lives in the Beat tab (and Space still works anywhere). The beat indicator stays.' },
|
||||
{ kind: 'removed', text: 'The “Set Beat” button from the header -- tap-tempo lives in the Beat tab (and Space still works anywhere). The beat indicator stays.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '7.6',
|
||||
name: 'What’s New!',
|
||||
changes: [
|
||||
{ kind: 'added', text: '“What’s New!” button in the header — every release’s additions, improvements and fixes at a glance.' },
|
||||
{ kind: 'added', text: 'A small dot on the button marks updates you haven’t seen yet; opening the list clears it.' },
|
||||
{ kind: 'added', text: 'The “What’s New!” button in the header -- every release’s additions, improvements and fixes at a glance.' },
|
||||
{ kind: 'added', text: 'A small dot on the button marks updates a visitor hasn’t seen yet; opening the list clears it.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -112,7 +140,7 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
version: '7.5',
|
||||
name: 'Music links that just play',
|
||||
changes: [
|
||||
{ kind: 'fixed', text: 'Many YouTube links failing with “media resource not suitable” — tracks are now downloaded audio-only and converted to MP3 on the server, instead of streaming expiring, IP-locked URLs.' },
|
||||
{ kind: 'fixed', text: 'Many YouTube links failing with “media resource not suitable” -- tracks are now downloaded audio-only and converted to MP3 on the server, instead of streaming expiring, IP-locked URLs.' },
|
||||
{ kind: 'improved', text: 'The Playing label shows the video’s real title.' },
|
||||
{ kind: 'improved', text: 'Over-long tracks get an honest “too long” answer, and playlist transitions no longer stall behind conversions.' },
|
||||
],
|
||||
|
|
@ -121,7 +149,7 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
version: '7.4',
|
||||
name: 'Sequence mode',
|
||||
changes: [
|
||||
{ kind: 'added', text: '“Sequence” mix mode — cycles the folder’s presets in order, wrapping back to the first so the folder loops forever.' },
|
||||
{ kind: 'added', text: '“Sequence” mix mode -- cycles the folder’s presets in order, wrapping back to the first so the folder loops forever.' },
|
||||
{ kind: 'improved', text: 'Random never picks the same preset twice in a row; the demo showcase now walks all ten Zai-Magic presets in order.' },
|
||||
],
|
||||
},
|
||||
|
|
@ -129,22 +157,22 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
version: '7.3',
|
||||
name: 'Demo-flow refinements',
|
||||
changes: [
|
||||
{ kind: 'improved', text: 'The demo track plays once through and returns you to the source picker — a demo, not a radio station.' },
|
||||
{ kind: 'improved', text: 'The demo track plays once through and returns to the source picker -- a demo, not a radio station.' },
|
||||
{ kind: 'fixed', text: 'The randomizer no longer switches presets while no music is playing.' },
|
||||
{ kind: 'removed', text: 'Preset-change popups (“Preset loaded”…) — the footer’s SCRIPT label already echoes every change.' },
|
||||
{ kind: 'removed', text: 'Preset-change popups (“Preset loaded”…) -- the footer’s SCRIPT label already echoes every change.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '7.2.1',
|
||||
changes: [
|
||||
{ kind: 'fixed', text: 'Zai-Magic “Supernova” fading to black after its first explosion — every beat now re-detonates the field with fresh geometry.' },
|
||||
{ kind: 'fixed', text: 'Zai-Magic “Supernova” fading to black after its first explosion -- every beat now re-detonates the field with fresh geometry.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '7.2',
|
||||
name: 'Showcase flow',
|
||||
changes: [
|
||||
{ kind: 'added', text: 'Animated shimmer on the Demo Track button — one click starts the full showcase (demo music + the Zai-Magic folder on random mix).' },
|
||||
{ kind: 'added', text: 'Animated shimmer on the Demo Track button -- one click starts the full showcase (demo music + the Zai-Magic folder on mix).' },
|
||||
{ kind: 'added', text: 'Preset changes blur-dissolve over 0.7 s instead of hard-cutting.' },
|
||||
{ kind: 'improved', text: 'Fresh visitors start on the Black + Purple Outline theme with Bass Bloom loaded.' },
|
||||
],
|
||||
|
|
@ -153,16 +181,16 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
version: '7.1',
|
||||
name: 'Real demo track + beat detector rewrite',
|
||||
changes: [
|
||||
{ kind: 'added', text: 'The Demo button plays “Neural Mecha Pulse” — a real mastered recording — with live tempo detection and a track chip in the header.' },
|
||||
{ kind: 'improved', text: 'Beat detection rewritten the way real trackers work (spectral flux → autocorrelation → phase-locked grid): locks the true BPM of real music in about two seconds.' },
|
||||
{ kind: 'removed', text: 'The demo BPM slider — a real track’s tempo is detected, not dialed in.' },
|
||||
{ kind: 'added', text: 'The Demo button plays a real mastered recording -- with live tempo detection and a track chip in the header.' },
|
||||
{ kind: 'improved', text: 'I rewrote beat detection the way real trackers work (spectral flux → autocorrelation → phase-locked grid): the true BPM of real music locks in about two seconds.' },
|
||||
{ kind: 'removed', text: 'The demo BPM slider -- a real track’s tempo is detected, not dialed in.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '7.00',
|
||||
name: 'Zai-Magic',
|
||||
changes: [
|
||||
{ kind: 'added', text: 'Ten hand-authored presets built around beat-synced color — the color wheel turns on the kick, palettes swap per beat and per bar.' },
|
||||
{ kind: 'added', text: 'Ten hand-authored presets built around beat-synced color -- the color wheel turns on the kick, palettes swap per beat and per bar.' },
|
||||
{ kind: 'added', text: 'Script tools hsvr/hsvg/hsvb, smoothstep and the beatage kick-envelope variable, documented in the help panel.' },
|
||||
],
|
||||
},
|
||||
|
|
@ -177,20 +205,20 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
{
|
||||
version: '6.9.1',
|
||||
changes: [
|
||||
{ kind: 'added', text: 'Social share previews — sharing the site shows the big image card on Facebook, X, WhatsApp and Discord.' },
|
||||
{ kind: 'added', text: 'Social share previews -- sharing the site shows the big image card on Facebook, X, WhatsApp and Discord.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '6.9',
|
||||
name: 'House account',
|
||||
changes: [
|
||||
{ kind: 'added', text: 'Anonymous visitors play YouTube links through the shared house account — bot walls stop applying to guests.' },
|
||||
{ kind: 'added', text: 'Anonymous visitors play YouTube links through my shared house account -- bot walls stop applying to guests.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '6.8.2',
|
||||
changes: [
|
||||
{ kind: 'improved', text: 'Music-service login cut to about four clicks — drag the exported cookie file straight onto the login box.' },
|
||||
{ kind: 'improved', text: 'Music-service login cut to about four clicks -- the exported cookie file can be dragged straight onto the login box.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -210,7 +238,7 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
version: '6.7',
|
||||
name: 'Lazy playlist queue',
|
||||
changes: [
|
||||
{ kind: 'added', text: 'Playlist links become a queue that streams one song at a time — each track is fetched only right before it plays.' },
|
||||
{ kind: 'added', text: 'Playlist links become a queue that streams one song at a time -- each track is fetched only right before it plays.' },
|
||||
{ kind: 'added', text: 'Queue bar with skip, jump and replay.' },
|
||||
],
|
||||
},
|
||||
|
|
@ -218,18 +246,18 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
version: '6.6',
|
||||
name: 'Music service logins',
|
||||
changes: [
|
||||
{ kind: 'added', text: 'Settings-tab logins for YouTube, SoundCloud, Spotify and Apple Music, encrypted on your computer.' },
|
||||
{ kind: 'added', text: 'Settings-tab logins for YouTube, SoundCloud, Spotify and Apple Music, encrypted on the visitor’s computer.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '6.5',
|
||||
name: 'Settings tab & themes',
|
||||
changes: [{ kind: 'added', text: 'Theme picker — base chrome × highlight color, saved per visitor.' }],
|
||||
changes: [{ kind: 'added', text: 'Theme picker -- base chrome × highlight color, saved per visitor.' }],
|
||||
},
|
||||
{
|
||||
version: '6.4',
|
||||
changes: [
|
||||
{ kind: 'fixed', text: 'Beat detection suspends when no music is playing — no ghost beats after Stop.' },
|
||||
{ kind: 'fixed', text: 'Beat detection suspends when no music is playing -- no ghost beats after Stop.' },
|
||||
{ kind: 'added', text: 'Royal purple dark theme (later joined by more bases).' },
|
||||
],
|
||||
},
|
||||
|
|
@ -240,13 +268,13 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
{
|
||||
version: '6.2',
|
||||
changes: [
|
||||
{ kind: 'improved', text: 'The embedded preset library is read-only; your own presets live in your browser.' },
|
||||
{ kind: 'improved', text: 'The embedded preset library is read-only; each visitor’s own presets live in their browser.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
version: '6.1',
|
||||
changes: [
|
||||
{ kind: 'improved', text: 'Every embedded preset is a unique generated visual — sixteen families, seeded parameters.' },
|
||||
{ kind: 'improved', text: 'Every embedded preset is a unique generated visual -- sixteen families, seeded parameters.' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -261,7 +289,7 @@ export const RELEASE_NOTES: ReleaseNote[] = [
|
|||
},
|
||||
{
|
||||
version: '4.0',
|
||||
changes: [{ kind: 'added', text: 'Link audio source — paste a URL, hear the music.' }],
|
||||
changes: [{ kind: 'added', text: 'Link audio source -- paste a URL, hear the music.' }],
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -274,6 +302,6 @@ if (
|
|||
RELEASE_NOTES[0].version !== APP_VERSION
|
||||
) {
|
||||
console.warn(
|
||||
`[release-notes] RELEASE_NOTES[0] (v${RELEASE_NOTES[0].version}) does not match APP_VERSION (v${APP_VERSION}) — add the new release's entry to src/lib/release-notes.ts.`,
|
||||
`[release-notes] RELEASE_NOTES[0] (v${RELEASE_NOTES[0].version}) does not match APP_VERSION (v${APP_VERSION}) -- add the new release's entry to src/lib/release-notes.ts.`,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,21 +31,21 @@ export const THEME_BASES: ThemeBase[] = [
|
|||
id: 'purple',
|
||||
name: 'Royal Purple',
|
||||
dark: true,
|
||||
blurb: 'Deep purple chrome with light-yellow highlights — the classic OVE look.',
|
||||
blurb: 'Deep purple chrome with light-yellow highlights -- the classic OVE look.',
|
||||
swatch: { bg: '#1b0f2e', panel: '#2a1a42', border: '#453063' },
|
||||
},
|
||||
{
|
||||
id: 'matte',
|
||||
name: 'Matte Black',
|
||||
dark: true,
|
||||
blurb: 'True matte black — neutral, no hue, zero glare.',
|
||||
blurb: 'True matte black -- neutral, no hue, zero glare.',
|
||||
swatch: { bg: '#0b0b0d', panel: '#141417', border: '#26262c' },
|
||||
},
|
||||
{
|
||||
id: 'outline',
|
||||
name: 'Black + Purple Outline',
|
||||
dark: true,
|
||||
blurb: 'Pure black stage with outlined panels — the outline follows your highlight color (blue by default).',
|
||||
blurb: 'Pure black stage with outlined panels -- the outline follows your highlight color (blue by default).',
|
||||
swatch: { bg: '#000000', panel: '#0a0a0e', border: '#4c1d95' },
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,31 @@
|
|||
// warns in the console when the two drift apart.
|
||||
//
|
||||
// History:
|
||||
// 7.10 — ten demo tracks + first-person changelog + declutter. The demo
|
||||
// source is now a COLLECTION: ten mastered tracks in
|
||||
// public/demo-tracks/ (demo-01.mp3 … demo-10.mp3, filename order
|
||||
// 1→10, replacing the single Neural Mecha Pulse file). Each Demo
|
||||
// click plays the visitor's PLACE in the collection once through;
|
||||
// the place advances when a pass truly ends — natural finish or
|
||||
// the Stop button ('ended'/'stop' teardown reasons, a new
|
||||
// onDemoEnded signature) — and wraps 10→1; switching to another
|
||||
// source keeps the place. The place persists per visitor in
|
||||
// localStorage (ove.demoTrack.next), so returning picks up where
|
||||
// they left off. The engine caches one decoded buffer at a time,
|
||||
// keyed by track index (~50–60 MB PCM each — all ten would be half
|
||||
// a gigabyte). The header chip + footer SRC label show the current
|
||||
// track's name (Demo Track N). RELEASE_NOTES rewritten in the
|
||||
// operator's first-person voice (no more third-person marketing
|
||||
// copy or addressing the visitor), and every em dash in the
|
||||
// interface replaced with a plain double minus ( -- ) — including
|
||||
// the embedded preset library's descriptions and script comments
|
||||
// (EMBEDDED_SEED_VERSION 7.01 → 7.10 re-seed). Declutter: the
|
||||
// landing menu's source list line, the presets panel's two
|
||||
// read-only paragraphs, the Random/Sequence hint line, the empty
|
||||
// user-folder note reworded, the Settings theme/highlight/Native
|
||||
// paragraphs, the link dialog's privacy footnote and the footer's
|
||||
// engine-ok dot are all gone — compile errors still toast, so the
|
||||
// always-green badge was noise
|
||||
// 7.9 — footer credit + What's New polish. The footer's blank middle now
|
||||
// carries the maker's signature: "© {year} · Site Created &
|
||||
// Deployed by Sum'ting White" (year generated from the clock,
|
||||
|
|
@ -274,4 +299,4 @@
|
|||
|
||||
export const APP_NAME = 'Open Visualization Engine'
|
||||
export const APP_SHORT = 'OVE'
|
||||
export const APP_VERSION = '7.9'
|
||||
export const APP_VERSION = '7.10'
|
||||
|
|
|
|||
Loading…
Reference in a new issue