@nexart/codemode-sdk 1.8.3 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -0
- package/README.md +121 -2
- package/dist/cjs/browser.cjs +3077 -0
- package/dist/cjs/browser.js +3042 -0
- package/dist/cjs/core.cjs +1998 -0
- package/dist/cjs/core.js +1966 -0
- package/dist/cjs/node.cjs +3245 -0
- package/dist/cjs/node.js +3208 -0
- package/dist/esm/browser.cjs +3077 -0
- package/dist/esm/browser.js +3042 -0
- package/dist/esm/core.cjs +1998 -0
- package/dist/esm/core.js +1966 -0
- package/dist/esm/node.cjs +3245 -0
- package/dist/esm/node.js +3208 -0
- package/dist/types/sdk/codemode/attestation.d.ts +24 -0
- package/dist/types/sdk/codemode/attestation.d.ts.map +1 -0
- package/dist/types/sdk/codemode/builder-manifest.d.ts.map +1 -0
- package/dist/types/sdk/codemode/canonicalJson.d.ts +16 -0
- package/dist/types/sdk/codemode/canonicalJson.d.ts.map +1 -0
- package/dist/{sdk → types/sdk}/codemode/core-index.d.ts +5 -1
- package/dist/types/sdk/codemode/core-index.d.ts.map +1 -0
- package/dist/types/sdk/codemode/engine.d.ts.map +1 -0
- package/dist/{sdk → types/sdk}/codemode/entry/browser.d.ts +1 -1
- package/dist/types/sdk/codemode/entry/browser.d.ts.map +1 -0
- package/dist/types/sdk/codemode/entry/node.d.ts.map +1 -0
- package/dist/types/sdk/codemode/execute.d.ts.map +1 -0
- package/dist/types/sdk/codemode/execution-sandbox.d.ts.map +1 -0
- package/dist/types/sdk/codemode/loop-engine.d.ts.map +1 -0
- package/dist/types/sdk/codemode/nodeReceipt.d.ts +65 -0
- package/dist/types/sdk/codemode/nodeReceipt.d.ts.map +1 -0
- package/dist/types/sdk/codemode/p5-runtime.d.ts.map +1 -0
- package/dist/{sdk → types/sdk}/codemode/runtime.d.ts +1 -1
- package/dist/types/sdk/codemode/runtime.d.ts.map +1 -0
- package/dist/types/sdk/codemode/snapshot.d.ts +72 -0
- package/dist/types/sdk/codemode/snapshot.d.ts.map +1 -0
- package/dist/types/sdk/codemode/sound-bridge.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-engine.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/chladniBloom.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/dualVortex.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/geometryIllusion.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/index.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/isoflow.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/loomWeave.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/noiseTerraces.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/orb.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/pixelGlyphs.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/prismFlowFields.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/radialBurst.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/resonantSoundBodies.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/rings.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/squares.d.ts.map +1 -0
- package/dist/types/sdk/codemode/soundart-sketches/waveStripes.d.ts.map +1 -0
- package/dist/types/sdk/codemode/static-engine.d.ts.map +1 -0
- package/dist/{sdk → types/sdk}/codemode/types.d.ts +96 -0
- package/dist/types/sdk/codemode/types.d.ts.map +1 -0
- package/dist/{sdk → types/sdk}/codemode/version.d.ts +2 -2
- package/dist/types/sdk/codemode/version.d.ts.map +1 -0
- package/dist/types/shared/soundSnapshot.d.ts.map +1 -0
- package/examples/sketch-minimal.js +27 -0
- package/examples/sketch-vars.js +59 -0
- package/examples/sketch.js +24 -0
- package/package.json +29 -23
- package/dist/sdk/codemode/builder-manifest.d.ts.map +0 -1
- package/dist/sdk/codemode/builder-manifest.js +0 -97
- package/dist/sdk/codemode/core-index.d.ts.map +0 -1
- package/dist/sdk/codemode/core-index.js +0 -28
- package/dist/sdk/codemode/engine.d.ts.map +0 -1
- package/dist/sdk/codemode/engine.js +0 -67
- package/dist/sdk/codemode/entry/browser.d.ts.map +0 -1
- package/dist/sdk/codemode/entry/browser.js +0 -69
- package/dist/sdk/codemode/entry/node.d.ts.map +0 -1
- package/dist/sdk/codemode/entry/node.js +0 -35
- package/dist/sdk/codemode/execute.d.ts.map +0 -1
- package/dist/sdk/codemode/execute.js +0 -283
- package/dist/sdk/codemode/execution-sandbox.d.ts.map +0 -1
- package/dist/sdk/codemode/execution-sandbox.js +0 -207
- package/dist/sdk/codemode/loop-engine.d.ts.map +0 -1
- package/dist/sdk/codemode/loop-engine.js +0 -229
- package/dist/sdk/codemode/p5-runtime.d.ts.map +0 -1
- package/dist/sdk/codemode/p5-runtime.js +0 -1033
- package/dist/sdk/codemode/runtime.d.ts.map +0 -1
- package/dist/sdk/codemode/runtime.js +0 -220
- package/dist/sdk/codemode/sound-bridge.d.ts.map +0 -1
- package/dist/sdk/codemode/sound-bridge.js +0 -128
- package/dist/sdk/codemode/soundart-engine.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-engine.js +0 -173
- package/dist/sdk/codemode/soundart-sketches/chladniBloom.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/chladniBloom.js +0 -53
- package/dist/sdk/codemode/soundart-sketches/dualVortex.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/dualVortex.js +0 -67
- package/dist/sdk/codemode/soundart-sketches/geometryIllusion.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/geometryIllusion.js +0 -89
- package/dist/sdk/codemode/soundart-sketches/index.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/index.js +0 -72
- package/dist/sdk/codemode/soundart-sketches/isoflow.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/isoflow.js +0 -60
- package/dist/sdk/codemode/soundart-sketches/loomWeave.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/loomWeave.js +0 -59
- package/dist/sdk/codemode/soundart-sketches/noiseTerraces.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/noiseTerraces.js +0 -53
- package/dist/sdk/codemode/soundart-sketches/orb.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/orb.js +0 -50
- package/dist/sdk/codemode/soundart-sketches/pixelGlyphs.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/pixelGlyphs.js +0 -72
- package/dist/sdk/codemode/soundart-sketches/prismFlowFields.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/prismFlowFields.js +0 -51
- package/dist/sdk/codemode/soundart-sketches/radialBurst.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/radialBurst.js +0 -60
- package/dist/sdk/codemode/soundart-sketches/resonantSoundBodies.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/resonantSoundBodies.js +0 -89
- package/dist/sdk/codemode/soundart-sketches/rings.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/rings.js +0 -89
- package/dist/sdk/codemode/soundart-sketches/squares.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/squares.js +0 -52
- package/dist/sdk/codemode/soundart-sketches/waveStripes.d.ts.map +0 -1
- package/dist/sdk/codemode/soundart-sketches/waveStripes.js +0 -44
- package/dist/sdk/codemode/static-engine.d.ts.map +0 -1
- package/dist/sdk/codemode/static-engine.js +0 -157
- package/dist/sdk/codemode/types.d.ts.map +0 -1
- package/dist/sdk/codemode/types.js +0 -34
- package/dist/sdk/codemode/version.d.ts.map +0 -1
- package/dist/sdk/codemode/version.js +0 -17
- package/dist/shared/soundSnapshot.d.ts.map +0 -1
- package/dist/shared/soundSnapshot.js +0 -128
- /package/dist/{sdk → types/sdk}/codemode/builder-manifest.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/engine.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/entry/node.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/execute.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/execution-sandbox.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/loop-engine.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/p5-runtime.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/sound-bridge.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-engine.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/chladniBloom.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/dualVortex.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/geometryIllusion.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/index.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/isoflow.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/loomWeave.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/noiseTerraces.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/orb.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/pixelGlyphs.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/prismFlowFields.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/radialBurst.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/resonantSoundBodies.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/rings.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/squares.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/soundart-sketches/waveStripes.d.ts +0 -0
- /package/dist/{sdk → types/sdk}/codemode/static-engine.d.ts +0 -0
- /package/dist/{shared → types/shared}/soundSnapshot.d.ts +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,eAAO,MAAM,eAAe,UAAc,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,IAAI,MAAM,CAAC;IACjB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9C,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjD,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,MAAM,IAAI,MAAM,CAAC;IACjB,QAAQ,IAAI,YAAY,CAAC;IACzB,OAAO,IAAI,MAAM,CAAC;IAClB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAqGD,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CAuHpE;AAED,eAAO,MAAM,aAAa;;;CAGzB,CAAC"}
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* NexArt Code Mode SDK - Agent-First Runtime Authority Layer
|
|
3
|
-
* See version.ts for SDK version (single source of truth)
|
|
4
|
-
*
|
|
5
|
-
* ╔══════════════════════════════════════════════════════════════════════════╗
|
|
6
|
-
* ║ AGENT-FIRST RUNTIME — DETERMINISTIC EXECUTION AUTHORITY ║
|
|
7
|
-
* ║ ║
|
|
8
|
-
* ║ This module provides a high-level runtime API designed for AI agents ║
|
|
9
|
-
* ║ (Replit, Lovable, Claude Code) to reliably execute deterministic code. ║
|
|
10
|
-
* ║ ║
|
|
11
|
-
* ║ Key Features: ║
|
|
12
|
-
* ║ - Deterministic PRNG: runtime.random() (seeded Mulberry32) ║
|
|
13
|
-
* ║ - Deterministic noise: runtime.noise(x, y?, z?) (seeded Perlin) ║
|
|
14
|
-
* ║ - Strict mode: Throws on Math.random, Date.now, performance.now ║
|
|
15
|
-
* ║ - Digest: Stable hash for verification and replay ║
|
|
16
|
-
* ║ - State snapshot: Canonical state for bundles ║
|
|
17
|
-
* ║ ║
|
|
18
|
-
* ║ BROWSER-SAFE: No Node.js dependencies. Works in Vite/Next/React. ║
|
|
19
|
-
* ╚══════════════════════════════════════════════════════════════════════════╝
|
|
20
|
-
*/
|
|
21
|
-
import { SDK_VERSION } from './version';
|
|
22
|
-
export const RUNTIME_VERSION = SDK_VERSION;
|
|
23
|
-
function hashSeed(seed) {
|
|
24
|
-
if (typeof seed === 'number') {
|
|
25
|
-
return Math.floor(seed) >>> 0;
|
|
26
|
-
}
|
|
27
|
-
let hash = 0;
|
|
28
|
-
for (let i = 0; i < seed.length; i++) {
|
|
29
|
-
const char = seed.charCodeAt(i);
|
|
30
|
-
hash = ((hash << 5) - hash) + char;
|
|
31
|
-
hash = hash >>> 0;
|
|
32
|
-
}
|
|
33
|
-
return hash || 1;
|
|
34
|
-
}
|
|
35
|
-
function createSeededRNG(seed) {
|
|
36
|
-
let a = seed >>> 0;
|
|
37
|
-
return () => {
|
|
38
|
-
a += 0x6D2B79F5;
|
|
39
|
-
let t = Math.imul(a ^ (a >>> 15), a | 1);
|
|
40
|
-
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
41
|
-
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function createSeededNoise(seed) {
|
|
45
|
-
const permutation = [];
|
|
46
|
-
const rng = createSeededRNG(seed);
|
|
47
|
-
for (let i = 0; i < 256; i++) {
|
|
48
|
-
permutation[i] = i;
|
|
49
|
-
}
|
|
50
|
-
for (let i = 255; i > 0; i--) {
|
|
51
|
-
const j = Math.floor(rng() * (i + 1));
|
|
52
|
-
[permutation[i], permutation[j]] = [permutation[j], permutation[i]];
|
|
53
|
-
}
|
|
54
|
-
for (let i = 0; i < 256; i++) {
|
|
55
|
-
permutation[256 + i] = permutation[i];
|
|
56
|
-
}
|
|
57
|
-
const fade = (t) => t * t * t * (t * (t * 6 - 15) + 10);
|
|
58
|
-
const lerp = (a, b, t) => a + t * (b - a);
|
|
59
|
-
const grad = (hash, x, y, z) => {
|
|
60
|
-
const h = hash & 15;
|
|
61
|
-
const u = h < 8 ? x : y;
|
|
62
|
-
const v = h < 4 ? y : h === 12 || h === 14 ? x : z;
|
|
63
|
-
return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);
|
|
64
|
-
};
|
|
65
|
-
return (x, y = 0, z = 0) => {
|
|
66
|
-
const X = Math.floor(x) & 255;
|
|
67
|
-
const Y = Math.floor(y) & 255;
|
|
68
|
-
const Z = Math.floor(z) & 255;
|
|
69
|
-
x -= Math.floor(x);
|
|
70
|
-
y -= Math.floor(y);
|
|
71
|
-
z -= Math.floor(z);
|
|
72
|
-
const u = fade(x);
|
|
73
|
-
const v = fade(y);
|
|
74
|
-
const w = fade(z);
|
|
75
|
-
const A = permutation[X] + Y;
|
|
76
|
-
const AA = permutation[A] + Z;
|
|
77
|
-
const AB = permutation[A + 1] + Z;
|
|
78
|
-
const B = permutation[X + 1] + Y;
|
|
79
|
-
const BA = permutation[B] + Z;
|
|
80
|
-
const BB = permutation[B + 1] + Z;
|
|
81
|
-
return (lerp(lerp(lerp(grad(permutation[AA], x, y, z), grad(permutation[BA], x - 1, y, z), u), lerp(grad(permutation[AB], x, y - 1, z), grad(permutation[BB], x - 1, y - 1, z), u), v), lerp(lerp(grad(permutation[AA + 1], x, y, z - 1), grad(permutation[BA + 1], x - 1, y, z - 1), u), lerp(grad(permutation[AB + 1], x, y - 1, z - 1), grad(permutation[BB + 1], x - 1, y - 1, z - 1), u), v), w) + 1) / 2;
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function stableStringify(obj) {
|
|
85
|
-
if (obj === null)
|
|
86
|
-
return 'null';
|
|
87
|
-
if (obj === undefined)
|
|
88
|
-
return 'undefined';
|
|
89
|
-
if (typeof obj !== 'object')
|
|
90
|
-
return JSON.stringify(obj);
|
|
91
|
-
if (Array.isArray(obj)) {
|
|
92
|
-
return '[' + obj.map(stableStringify).join(',') + ']';
|
|
93
|
-
}
|
|
94
|
-
const keys = Object.keys(obj).sort();
|
|
95
|
-
const pairs = keys.map(k => `${JSON.stringify(k)}:${stableStringify(obj[k])}`);
|
|
96
|
-
return '{' + pairs.join(',') + '}';
|
|
97
|
-
}
|
|
98
|
-
function fnv1aHash(str) {
|
|
99
|
-
let hash = 0x811c9dc5;
|
|
100
|
-
for (let i = 0; i < str.length; i++) {
|
|
101
|
-
hash ^= str.charCodeAt(i);
|
|
102
|
-
hash = Math.imul(hash, 0x01000193);
|
|
103
|
-
}
|
|
104
|
-
const h1 = (hash >>> 0).toString(16).padStart(8, '0');
|
|
105
|
-
let hash2 = 0x811c9dc5;
|
|
106
|
-
for (let i = str.length - 1; i >= 0; i--) {
|
|
107
|
-
hash2 ^= str.charCodeAt(i);
|
|
108
|
-
hash2 = Math.imul(hash2, 0x01000193);
|
|
109
|
-
}
|
|
110
|
-
const h2 = (hash2 >>> 0).toString(16).padStart(8, '0');
|
|
111
|
-
return h1 + h2;
|
|
112
|
-
}
|
|
113
|
-
export function createRuntime(options) {
|
|
114
|
-
const numericSeed = hashSeed(options.seed);
|
|
115
|
-
const vars = options.vars ?? [];
|
|
116
|
-
const mode = options.mode ?? 'static';
|
|
117
|
-
const strict = options.strict ?? false;
|
|
118
|
-
const metadata = options.metadata;
|
|
119
|
-
if (vars.length > 10) {
|
|
120
|
-
throw new Error(`[NexArt Runtime] vars array must have 0-10 elements, got ${vars.length}`);
|
|
121
|
-
}
|
|
122
|
-
for (let i = 0; i < vars.length; i++) {
|
|
123
|
-
if (typeof vars[i] !== 'number' || !Number.isFinite(vars[i])) {
|
|
124
|
-
throw new Error(`[NexArt Runtime] vars[${i}] must be a finite number`);
|
|
125
|
-
}
|
|
126
|
-
if (vars[i] < 0 || vars[i] > 100) {
|
|
127
|
-
throw new Error(`[NexArt Runtime] vars[${i}] must be in range 0-100, got ${vars[i]}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
const paddedVars = [...vars];
|
|
131
|
-
while (paddedVars.length < 10) {
|
|
132
|
-
paddedVars.push(0);
|
|
133
|
-
}
|
|
134
|
-
const rng = createSeededRNG(numericSeed);
|
|
135
|
-
const noiseFunc = createSeededNoise(numericSeed);
|
|
136
|
-
const state = {
|
|
137
|
-
sdkVersion: RUNTIME_VERSION,
|
|
138
|
-
seed: numericSeed,
|
|
139
|
-
vars: paddedVars,
|
|
140
|
-
mode,
|
|
141
|
-
...(metadata !== undefined && { metadata }),
|
|
142
|
-
};
|
|
143
|
-
function random() {
|
|
144
|
-
return rng();
|
|
145
|
-
}
|
|
146
|
-
function randomInt(min, max) {
|
|
147
|
-
const range = max - min + 1;
|
|
148
|
-
return Math.floor(rng() * range) + min;
|
|
149
|
-
}
|
|
150
|
-
function randomRange(min, max) {
|
|
151
|
-
return rng() * (max - min) + min;
|
|
152
|
-
}
|
|
153
|
-
function noise(x, y, z) {
|
|
154
|
-
return noiseFunc(x, y ?? 0, z ?? 0);
|
|
155
|
-
}
|
|
156
|
-
function run(fn) {
|
|
157
|
-
if (!strict) {
|
|
158
|
-
return fn();
|
|
159
|
-
}
|
|
160
|
-
const originalMathRandom = Math.random;
|
|
161
|
-
const originalDateNow = Date.now;
|
|
162
|
-
const hasPerformance = typeof performance !== 'undefined' && performance !== null;
|
|
163
|
-
const originalPerformanceNow = hasPerformance ? performance.now : undefined;
|
|
164
|
-
const throwMathRandom = () => {
|
|
165
|
-
throw new Error('NEXART_STRICT: Non-deterministic API used: Math.random. Use runtime.random() instead.');
|
|
166
|
-
};
|
|
167
|
-
const throwDateNow = () => {
|
|
168
|
-
throw new Error('NEXART_STRICT: Non-deterministic API used: Date.now. Pass time as an input or use deterministic counters.');
|
|
169
|
-
};
|
|
170
|
-
const throwPerformanceNow = () => {
|
|
171
|
-
throw new Error('NEXART_STRICT: Non-deterministic API used: performance.now.');
|
|
172
|
-
};
|
|
173
|
-
try {
|
|
174
|
-
Math.random = throwMathRandom;
|
|
175
|
-
Date.now = throwDateNow;
|
|
176
|
-
if (hasPerformance && originalPerformanceNow) {
|
|
177
|
-
performance.now = throwPerformanceNow;
|
|
178
|
-
}
|
|
179
|
-
return fn();
|
|
180
|
-
}
|
|
181
|
-
finally {
|
|
182
|
-
Math.random = originalMathRandom;
|
|
183
|
-
Date.now = originalDateNow;
|
|
184
|
-
if (hasPerformance && originalPerformanceNow) {
|
|
185
|
-
performance.now = originalPerformanceNow;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
function digest() {
|
|
190
|
-
const input = stableStringify({
|
|
191
|
-
sdkVersion: RUNTIME_VERSION,
|
|
192
|
-
seed: numericSeed,
|
|
193
|
-
vars: paddedVars,
|
|
194
|
-
mode,
|
|
195
|
-
...(metadata !== undefined && { metadata }),
|
|
196
|
-
});
|
|
197
|
-
return fnv1aHash(input);
|
|
198
|
-
}
|
|
199
|
-
function getState() {
|
|
200
|
-
return { ...state, vars: [...state.vars] };
|
|
201
|
-
}
|
|
202
|
-
function getSeed() {
|
|
203
|
-
return numericSeed;
|
|
204
|
-
}
|
|
205
|
-
return Object.freeze({
|
|
206
|
-
random,
|
|
207
|
-
randomInt,
|
|
208
|
-
randomRange,
|
|
209
|
-
noise,
|
|
210
|
-
run,
|
|
211
|
-
digest,
|
|
212
|
-
getState,
|
|
213
|
-
getSeed,
|
|
214
|
-
strict,
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
export const NexArtRuntime = {
|
|
218
|
-
create: createRuntime,
|
|
219
|
-
VERSION: RUNTIME_VERSION,
|
|
220
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sound-bridge.d.ts","sourceRoot":"","sources":["../../../sound-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAGhE;;;GAGG;AACH,MAAM,WAAW,YAAa,SAAQ,QAAQ,CAAC,aAAa,CAAC;CAE5D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,aAAa,GAAG,YAAY,CAExE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,YAAY,CAEtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC9D,OAAO,EAAE,CAAC,EACV,QAAQ,EAAE,aAAa,GACtB,CAAC,GAAG;IAAE,CAAC,EAAE,YAAY,CAAA;CAAE,CAuBzB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB;IAE9B;;OAEG;sBACe,MAAM,UAAU,MAAM,UAAU,MAAM,KAAG,MAAM;IAIjE;;OAEG;2BACoB,MAAM,UAAU,MAAM,UAAU,MAAM,WAAU,MAAM,KAAO,MAAM;IAK1F;;OAEG;2BACoB,MAAM,aAAa,MAAM,cAAc,MAAM,KAAG,MAAM;EAIhF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,aAAa,EACvB,WAAW,GAAE,MAAU,GACtB,MAAM,EAAE,CAeV;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AACjD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAChE,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,YAAY,CAiBvE"}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SoundArt → Code Mode Bridge
|
|
3
|
-
*
|
|
4
|
-
* This module injects sound-derived parameters into the Code Mode runtime
|
|
5
|
-
* as read-only `S.*` globals. It is the integration layer between sound
|
|
6
|
-
* analysis and generative art rendering.
|
|
7
|
-
*
|
|
8
|
-
* Usage in Code Mode sketches:
|
|
9
|
-
* S.volume // 0-100: Overall loudness
|
|
10
|
-
* S.bass // 0-100: Bass frequency energy
|
|
11
|
-
* S.treble // 0-100: Treble frequency energy
|
|
12
|
-
* S.aggression // 0-100: Intensity/harshness
|
|
13
|
-
* S.t // 0-1: Normalized time position
|
|
14
|
-
* etc.
|
|
15
|
-
*/
|
|
16
|
-
import { createEmptySoundSnapshot, freezeSoundSnapshot } from '../../shared/soundSnapshot';
|
|
17
|
-
/**
|
|
18
|
-
* Create a frozen, read-only sound globals object from a snapshot
|
|
19
|
-
*/
|
|
20
|
-
export function createSoundGlobals(snapshot) {
|
|
21
|
-
return freezeSoundSnapshot(snapshot);
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Create empty/default sound globals for testing or fallback
|
|
25
|
-
*/
|
|
26
|
-
export function createEmptySoundGlobals() {
|
|
27
|
-
return freezeSoundSnapshot(createEmptySoundSnapshot());
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Inject sound globals into the p5 runtime context
|
|
31
|
-
*
|
|
32
|
-
* This adds the `S` global object to the runtime so sketches can access
|
|
33
|
-
* sound-derived parameters like S.volume, S.bass, etc.
|
|
34
|
-
*
|
|
35
|
-
* @param runtime - The p5 runtime object
|
|
36
|
-
* @param snapshot - The sound snapshot to inject
|
|
37
|
-
* @returns The runtime with S globals added
|
|
38
|
-
*/
|
|
39
|
-
export function injectSoundGlobals(runtime, snapshot) {
|
|
40
|
-
const globals = createSoundGlobals(snapshot);
|
|
41
|
-
// Create a proxy to make S immutable and prevent modification
|
|
42
|
-
const immutableS = new Proxy(globals, {
|
|
43
|
-
set() {
|
|
44
|
-
console.warn('[SoundBridge] S.* globals are read-only');
|
|
45
|
-
return false;
|
|
46
|
-
},
|
|
47
|
-
deleteProperty() {
|
|
48
|
-
console.warn('[SoundBridge] Cannot delete S.* properties');
|
|
49
|
-
return false;
|
|
50
|
-
},
|
|
51
|
-
defineProperty() {
|
|
52
|
-
console.warn('[SoundBridge] Cannot define new S.* properties');
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
return {
|
|
57
|
-
...runtime,
|
|
58
|
-
S: immutableS
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Helper function to map S.* values to useful ranges
|
|
63
|
-
*
|
|
64
|
-
* Usage in sketches:
|
|
65
|
-
* const density = mapSound(S.volume, 100, 2000) // Map 0-100 to 100-2000
|
|
66
|
-
*/
|
|
67
|
-
export function createSoundHelpers() {
|
|
68
|
-
return {
|
|
69
|
-
/**
|
|
70
|
-
* Map a sound value (0-100) to a custom range
|
|
71
|
-
*/
|
|
72
|
-
mapSound: (value, outMin, outMax) => {
|
|
73
|
-
return outMin + (value / 100) * (outMax - outMin);
|
|
74
|
-
},
|
|
75
|
-
/**
|
|
76
|
-
* Map a sound value (0-100) with easing
|
|
77
|
-
*/
|
|
78
|
-
mapSoundEased: (value, outMin, outMax, easing = 2) => {
|
|
79
|
-
const t = Math.pow(value / 100, easing);
|
|
80
|
-
return outMin + t * (outMax - outMin);
|
|
81
|
-
},
|
|
82
|
-
/**
|
|
83
|
-
* Get a value that oscillates based on sound
|
|
84
|
-
*/
|
|
85
|
-
soundOscillate: (base, amplitude, soundValue) => {
|
|
86
|
-
return base + Math.sin(soundValue * Math.PI / 50) * amplitude;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Convert SoundSnapshot hue (0-100) to degrees (0-360)
|
|
92
|
-
*/
|
|
93
|
-
export function hueToDegrees(hue) {
|
|
94
|
-
return (hue / 100) * 360;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Generate a color palette from sound parameters
|
|
98
|
-
*
|
|
99
|
-
* @param snapshot - The sound snapshot
|
|
100
|
-
* @param paletteSize - Number of colors to generate
|
|
101
|
-
* @returns Array of HSL color strings
|
|
102
|
-
*/
|
|
103
|
-
export function generateSoundPalette(snapshot, paletteSize = 6) {
|
|
104
|
-
const mainHue = hueToDegrees(snapshot.hue);
|
|
105
|
-
const hueShift = 20 + (snapshot.harmonicity / 100) * 40; // 20-60 degrees
|
|
106
|
-
const sat = 60 + (snapshot.treble / 100) * 30; // 60-90%
|
|
107
|
-
const light = 70 + (snapshot.bass / 100) * 25; // 70-95%
|
|
108
|
-
const palette = [];
|
|
109
|
-
for (let i = 0; i < paletteSize; i++) {
|
|
110
|
-
const hue = (mainHue + i * hueShift) % 360;
|
|
111
|
-
const satVar = sat - (i % 2) * 10;
|
|
112
|
-
const lightVar = light - (i % 3) * 5;
|
|
113
|
-
palette.push(`hsl(${hue}, ${satVar}%, ${lightVar}%)`);
|
|
114
|
-
}
|
|
115
|
-
return palette;
|
|
116
|
-
}
|
|
117
|
-
export function inferGenreProfile(snapshot) {
|
|
118
|
-
// Energy based on volume and aggression
|
|
119
|
-
const energy = (snapshot.volume > 60 || snapshot.aggression > 60) ? 'high' :
|
|
120
|
-
(snapshot.volume > 30) ? 'mid' : 'low';
|
|
121
|
-
// Structure based on rhythmicity and aggression
|
|
122
|
-
const structure = (snapshot.rhythmicity > 50 && snapshot.dynamicRange < 25) ? 'geometric' :
|
|
123
|
-
(snapshot.aggression > 60 && snapshot.dynamicRange > 50) ? 'chaotic' : 'organic';
|
|
124
|
-
// Clarity based on brightness
|
|
125
|
-
const clarity = (snapshot.brightness > 60) ? 'sharp' :
|
|
126
|
-
(snapshot.brightness > 40) ? 'clear' : 'muddy';
|
|
127
|
-
return { energy, structure, clarity };
|
|
128
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"soundart-engine.d.ts","sourceRoot":"","sources":["../../../soundart-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAI/E,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,OAAO,CAAC;IAC3C,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,OAAO,EAAE;QACP,UAAU,EAAE,OAAO,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,gBAAgB,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAC/C,CAAC;CACH;AAqCD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAoG/B;AA4BD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAEvE;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,kBAAkB,EAAE,CAGjE;AAGD,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC/E,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SoundArt → Code Mode Engine
|
|
3
|
-
*
|
|
4
|
-
* This is the orchestrator that runs SoundArt styles through the Code Mode engine.
|
|
5
|
-
* It replaces the old Canvas2D-based SoundArt renderer with a Code Mode pipeline.
|
|
6
|
-
*
|
|
7
|
-
* Architecture:
|
|
8
|
-
* 1. Sound analysis produces SoundFeatures (unchanged)
|
|
9
|
-
* 2. SoundFeatures → SoundSnapshot conversion
|
|
10
|
-
* 3. SoundSnapshot injected as S.* globals into Code Mode
|
|
11
|
-
* 4. SoundArt sketch executed via Code Mode runtime
|
|
12
|
-
* 5. Result: PNG or MP4 output
|
|
13
|
-
*/
|
|
14
|
-
import { createSoundSnapshot } from '../../shared/soundSnapshot';
|
|
15
|
-
import { createP5Runtime } from './p5-runtime';
|
|
16
|
-
import { injectSoundGlobals, generateSoundPalette, inferGenreProfile } from './sound-bridge';
|
|
17
|
-
import { getSoundArtSketch } from './soundart-sketches';
|
|
18
|
-
/**
|
|
19
|
-
* Apply tweak multipliers to a SoundSnapshot
|
|
20
|
-
*/
|
|
21
|
-
function applyTweaksToSnapshot(snapshot, tweaks) {
|
|
22
|
-
if (!tweaks)
|
|
23
|
-
return snapshot;
|
|
24
|
-
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
25
|
-
const tweaked = {
|
|
26
|
-
...snapshot,
|
|
27
|
-
volume: snapshot.volume * (tweaks.volumeRangeFactor ?? 1),
|
|
28
|
-
brightness: snapshot.brightness * (tweaks.centroidBrightnessFactor ?? 1),
|
|
29
|
-
aggression: snapshot.aggression * (tweaks.aggressionPaletteFactor ?? 1),
|
|
30
|
-
rhythmicity: snapshot.rhythmicity * (tweaks.rhythmPatternFactor ?? 1),
|
|
31
|
-
harmonicity: snapshot.harmonicity * (tweaks.harmonySmoothnessFactor ?? 1),
|
|
32
|
-
attack: snapshot.attack * (tweaks.attackSharpnessFactor ?? 1),
|
|
33
|
-
dynamicRange: snapshot.dynamicRange * (tweaks.dynamicRangeVariationFactor ?? 1),
|
|
34
|
-
bass: snapshot.bass * (tweaks.bassThicknessFactor ?? 1),
|
|
35
|
-
treble: snapshot.treble * (tweaks.trebleSharpnessFactor ?? 1),
|
|
36
|
-
};
|
|
37
|
-
// Clamp all numeric values to reasonable range
|
|
38
|
-
tweaked.volume = clamp(tweaked.volume, 0, 250);
|
|
39
|
-
tweaked.brightness = clamp(tweaked.brightness, 0, 250);
|
|
40
|
-
tweaked.aggression = clamp(tweaked.aggression, 0, 250);
|
|
41
|
-
tweaked.rhythmicity = clamp(tweaked.rhythmicity, 0, 250);
|
|
42
|
-
tweaked.harmonicity = clamp(tweaked.harmonicity, 0, 250);
|
|
43
|
-
tweaked.attack = clamp(tweaked.attack, 0, 250);
|
|
44
|
-
tweaked.dynamicRange = clamp(tweaked.dynamicRange, 0, 250);
|
|
45
|
-
tweaked.bass = clamp(tweaked.bass, 0, 250);
|
|
46
|
-
tweaked.treble = clamp(tweaked.treble, 0, 250);
|
|
47
|
-
return tweaked;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Render a SoundArt style using Code Mode
|
|
51
|
-
*
|
|
52
|
-
* This is the main entry point for the new SoundArt → Code Mode pipeline.
|
|
53
|
-
*/
|
|
54
|
-
export async function renderSoundArtViaCodeMode(options) {
|
|
55
|
-
const { style, sound, canvas, config, onProgress } = options;
|
|
56
|
-
onProgress?.(0.1);
|
|
57
|
-
// 1. Get the sketch code
|
|
58
|
-
const sketchCode = getSoundArtSketch(style);
|
|
59
|
-
if (!sketchCode) {
|
|
60
|
-
throw new Error(`SoundArt style "${style}" has not been converted to Code Mode yet`);
|
|
61
|
-
}
|
|
62
|
-
onProgress?.(0.2);
|
|
63
|
-
// 2. Create SoundSnapshot from SoundFeatures
|
|
64
|
-
const baseSnapshot = createSoundSnapshot(sound, sound.frames);
|
|
65
|
-
// 3. Apply tweak multipliers to the snapshot
|
|
66
|
-
const snapshot = applyTweaksToSnapshot(baseSnapshot, config.tweakParams);
|
|
67
|
-
onProgress?.(0.3);
|
|
68
|
-
// 3. Create the p5 runtime with seeded randomness
|
|
69
|
-
// Derive deterministic seed from sound features if not provided
|
|
70
|
-
const deriveSeedFromSound = (sound) => {
|
|
71
|
-
// Create a stable hash from sound parameters
|
|
72
|
-
const hashInput = (sound.rms * 1000) +
|
|
73
|
-
(sound.centroid * 100) +
|
|
74
|
-
(sound.durationSec * 10000) +
|
|
75
|
-
((sound.bands?.bass ?? 0) * 500) +
|
|
76
|
-
((sound.bands?.treble ?? 0) * 700);
|
|
77
|
-
// Simple hash to integer
|
|
78
|
-
return Math.abs(Math.floor(hashInput * 2147483647) % 2147483647) || 123456;
|
|
79
|
-
};
|
|
80
|
-
const runtimeConfig = {
|
|
81
|
-
seed: config.seed ?? deriveSeedFromSound(sound),
|
|
82
|
-
};
|
|
83
|
-
canvas.width = config.width;
|
|
84
|
-
canvas.height = config.height;
|
|
85
|
-
const baseRuntime = createP5Runtime(canvas, config.width, config.height, runtimeConfig);
|
|
86
|
-
// 4. Inject sound globals (S.*)
|
|
87
|
-
const runtime = injectSoundGlobals(baseRuntime, snapshot);
|
|
88
|
-
onProgress?.(0.4);
|
|
89
|
-
// 5. Add helper globals
|
|
90
|
-
const globals = {
|
|
91
|
-
...runtime,
|
|
92
|
-
width: config.width,
|
|
93
|
-
height: config.height,
|
|
94
|
-
backgroundMode: config.backgroundMode ?? 'rgb',
|
|
95
|
-
palette: generateSoundPalette(snapshot),
|
|
96
|
-
genre: inferGenreProfile(snapshot),
|
|
97
|
-
};
|
|
98
|
-
onProgress?.(0.5);
|
|
99
|
-
// 6. Execute the sketch
|
|
100
|
-
try {
|
|
101
|
-
executeSketch(sketchCode, globals);
|
|
102
|
-
onProgress?.(0.9);
|
|
103
|
-
}
|
|
104
|
-
catch (error) {
|
|
105
|
-
console.error(`[SoundArtEngine] Error executing style "${style}":`, error);
|
|
106
|
-
throw new Error(`Style "${style}" execution failed: ${error}`);
|
|
107
|
-
}
|
|
108
|
-
onProgress?.(1.0);
|
|
109
|
-
// 7. Build metadata
|
|
110
|
-
const metadata = {
|
|
111
|
-
mode: 'SoundArt',
|
|
112
|
-
style,
|
|
113
|
-
timestamp: new Date().toISOString(),
|
|
114
|
-
soundFeatures: {
|
|
115
|
-
duration: sound.durationSec,
|
|
116
|
-
amplitude: sound.rms,
|
|
117
|
-
frequency: sound.centroid,
|
|
118
|
-
bass: sound.bands?.bass ?? 0,
|
|
119
|
-
treble: sound.bands?.treble ?? 0,
|
|
120
|
-
aggression: snapshot.aggression,
|
|
121
|
-
},
|
|
122
|
-
effects: {
|
|
123
|
-
timeFilter: false,
|
|
124
|
-
backgroundMode: config.backgroundMode ?? 'rgb',
|
|
125
|
-
},
|
|
126
|
-
generationParams: {
|
|
127
|
-
seed: runtimeConfig.seed,
|
|
128
|
-
canvasSize: { width: config.width, height: config.height },
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
return {
|
|
132
|
-
style,
|
|
133
|
-
mode: 'soundart',
|
|
134
|
-
snapshot,
|
|
135
|
-
metadata,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Execute a sketch string in the context of the runtime globals
|
|
140
|
-
*/
|
|
141
|
-
function executeSketch(code, globals) {
|
|
142
|
-
// Build the function context with all globals
|
|
143
|
-
const globalNames = Object.keys(globals);
|
|
144
|
-
const globalValues = Object.values(globals);
|
|
145
|
-
// Wrap the sketch code to call setup() and optionally draw()
|
|
146
|
-
const wrappedCode = `
|
|
147
|
-
${code}
|
|
148
|
-
|
|
149
|
-
// Execute setup
|
|
150
|
-
if (typeof setup === 'function') {
|
|
151
|
-
setup();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// For static mode, we don't call draw()
|
|
155
|
-
// Loop mode would call draw() in a frame loop
|
|
156
|
-
`;
|
|
157
|
-
// Create and execute the function
|
|
158
|
-
const sketchFunction = new Function(...globalNames, wrappedCode);
|
|
159
|
-
sketchFunction(...globalValues);
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Check if a SoundArt style can be rendered via Code Mode
|
|
163
|
-
*/
|
|
164
|
-
export function canRenderViaCodeMode(style) {
|
|
165
|
-
return getSoundArtSketch(style) !== undefined;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Get the list of SoundArt styles available via Code Mode
|
|
169
|
-
*/
|
|
170
|
-
export function getCodeModeAvailableStyles() {
|
|
171
|
-
const { getAvailableSoundArtSketches } = require('./soundart-sketches');
|
|
172
|
-
return getAvailableSoundArtSketches();
|
|
173
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chladniBloom.d.ts","sourceRoot":"","sources":["../../../../soundart-sketches/chladniBloom.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,+hEAmDhC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
export const CHLADNI_BLOOM_SKETCH = `
|
|
2
|
-
function setup() {
|
|
3
|
-
const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';
|
|
4
|
-
if (bgMode === 'white') background(245, 245, 245);
|
|
5
|
-
else if (bgMode === 'black') background(10, 10, 10);
|
|
6
|
-
else {
|
|
7
|
-
const r = Math.floor((S.brightness / 100) * 255);
|
|
8
|
-
const g = Math.floor((S.rhythmicity / 100) * 255);
|
|
9
|
-
const b = Math.floor((S.harmonicity / 100) * 255);
|
|
10
|
-
background(r, g, b);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
translate(width / 2, height / 2);
|
|
14
|
-
|
|
15
|
-
const layers = Math.floor(map(S.volume + S.rhythmicity, 0, 200, 20, 90));
|
|
16
|
-
const minStrokeW = map(S.volume, 0, 100, 1.0, 3.0);
|
|
17
|
-
const maxStrokeW = map(S.treble, 0, 100, 2.0, 5.0);
|
|
18
|
-
|
|
19
|
-
noFill();
|
|
20
|
-
|
|
21
|
-
for (let i = 0; i < layers; i++) {
|
|
22
|
-
const freq1 = Math.floor(map(S.aggression + random() * 50, 0, 150, 3, 20));
|
|
23
|
-
const freq2 = Math.floor(map(S.treble + random() * 50, 0, 150, 2, 8));
|
|
24
|
-
const amp = map(S.dynamicRange + random() * 30, 0, 130, 60, 400);
|
|
25
|
-
const rotation = map(S.harmonicity + random() * 50, 0, 150, 0, PI * 4);
|
|
26
|
-
const radiusOffset = map(S.bass, 0, 100, 40, 80);
|
|
27
|
-
const strokeW = map(S.treble + S.volume * 0.5, 0, 100, minStrokeW, maxStrokeW);
|
|
28
|
-
|
|
29
|
-
const hBase = (330 + random() * 100) % 360;
|
|
30
|
-
const finalH = (hBase + (random() * 40 - 60) + map(S.hue, 0, 100, -10, 10) + 360) % 360;
|
|
31
|
-
const finalC = constrain(85 + map(S.brightness, 0, 100, -20, 20), 0, 100);
|
|
32
|
-
const finalL = constrain(90 + map(S.brightness, 0, 100, -15, 15), 0, 100);
|
|
33
|
-
const finalA = constrain(0.5 + map(S.attack, 0, 100, 0, 0.5), 0.3, 1);
|
|
34
|
-
|
|
35
|
-
push();
|
|
36
|
-
rotate(rotation);
|
|
37
|
-
strokeWeight(strokeW);
|
|
38
|
-
stroke('hsla(' + finalH + ',' + finalC + '%,' + finalL + '%,' + finalA + ')');
|
|
39
|
-
|
|
40
|
-
const angleStep = map(S.treble, 0, 100, 0.07, 0.03);
|
|
41
|
-
beginShape();
|
|
42
|
-
for (let aa = 0; aa < PI * 2; aa += angleStep) {
|
|
43
|
-
const rad = radiusOffset * i + amp * sin(freq1 * aa) * cos(freq2 * aa * map(S.rhythmicity, 0, 100, 0.3, 2));
|
|
44
|
-
const x = rad * cos(aa);
|
|
45
|
-
const y = rad * sin(aa);
|
|
46
|
-
vertex(x, y);
|
|
47
|
-
}
|
|
48
|
-
endShape(CLOSE);
|
|
49
|
-
pop();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
`;
|
|
53
|
-
export default CHLADNI_BLOOM_SKETCH;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dualVortex.d.ts","sourceRoot":"","sources":["../../../../soundart-sketches/dualVortex.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,m/EAiE9B,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
export const DUAL_VORTEX_SKETCH = `
|
|
2
|
-
function setup() {
|
|
3
|
-
const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';
|
|
4
|
-
if (bgMode === 'white') background(245, 245, 245);
|
|
5
|
-
else if (bgMode === 'black') background(10, 10, 10);
|
|
6
|
-
else {
|
|
7
|
-
const r = Math.floor((S.brightness / 100) * 255);
|
|
8
|
-
const g = Math.floor((S.rhythmicity / 100) * 255);
|
|
9
|
-
const b = Math.floor((S.harmonicity / 100) * 255);
|
|
10
|
-
background(r, g, b);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const presence = 1.0 - S.silence / 100;
|
|
14
|
-
const sizeFactor = (S.length * 0.7 + S.volume * 0.6);
|
|
15
|
-
const layers = Math.floor(map(S.length, 0, 100, 60, 180));
|
|
16
|
-
const baseR = map(sizeFactor, 0, 100, Math.min(width, height) * 0.15, Math.min(width, height) * 0.55);
|
|
17
|
-
const steps = Math.floor(map(S.attack, 0, 100, 180, 480));
|
|
18
|
-
const twist = map(S.harmonicity, 0, 100, 0.5, 3.5);
|
|
19
|
-
const bulge = map(S.aggression, 0, 100, 0.05, 0.55);
|
|
20
|
-
const waveF = map(S.rhythmicity, 0, 100, 0.8, 5.0);
|
|
21
|
-
const CY = height * 0.5 + map(S.bass, 0, 100, -height * 0.1, height * 0.1);
|
|
22
|
-
const wBase = map(S.volume, 0, 100, 1.5, 6.0);
|
|
23
|
-
const alphaLo = map(S.dynamicRange, 0, 100, 80, 180) * presence;
|
|
24
|
-
const alphaHi = map(S.dynamicRange, 0, 100, 180, 255) * presence;
|
|
25
|
-
|
|
26
|
-
const mainHue = (S.brightness * 3.6) % 360;
|
|
27
|
-
|
|
28
|
-
noFill();
|
|
29
|
-
|
|
30
|
-
for (let pass = 0; pass < 2; pass++) {
|
|
31
|
-
const isSecond = pass === 0;
|
|
32
|
-
const alphaScale = isSecond ? 0.7 : 1.0;
|
|
33
|
-
const weightScale = isSecond ? 0.85 : 1.1;
|
|
34
|
-
|
|
35
|
-
for (let i = 0; i < layers; i++) {
|
|
36
|
-
const t = i / (layers - 1);
|
|
37
|
-
const h = (mainHue + i * 22.5) % 360;
|
|
38
|
-
const sat = map(S.treble, 0, 100, 60, 90);
|
|
39
|
-
const bri = map(S.bass, 0, 100, 70, 95);
|
|
40
|
-
|
|
41
|
-
const r0 = baseR * (0.6 + (isSecond ? 0.8 : 0.7) * sin(PI * 2 * t + 0.42));
|
|
42
|
-
const rot = t * (twist + 0.6) + sin(i * 0.05) * map(S.attack, 0, 100, 0.02, 0.12);
|
|
43
|
-
|
|
44
|
-
const hueShift = (i / layers) * 120;
|
|
45
|
-
const finalH = (h + hueShift) % 360;
|
|
46
|
-
const a = lerp(alphaHi, alphaLo, pow(t, 0.9)) * alphaScale / 255;
|
|
47
|
-
|
|
48
|
-
push();
|
|
49
|
-
translate(width * 0.5, CY);
|
|
50
|
-
rotate(rot);
|
|
51
|
-
|
|
52
|
-
strokeWeight(max(0.6, wBase * weightScale));
|
|
53
|
-
stroke('hsla(' + finalH + ',' + sat + '%,' + bri + '%,' + constrain(a, 0, 1) + ')');
|
|
54
|
-
|
|
55
|
-
beginShape();
|
|
56
|
-
for (let k = 0; k <= steps; k++) {
|
|
57
|
-
const ang = map(k, 0, steps, 0, PI * 2);
|
|
58
|
-
const baseRR = r0 * (1.0 + bulge * sin(ang * waveF + t * PI * 3));
|
|
59
|
-
vertex(baseRR * cos(ang), baseRR * sin(ang));
|
|
60
|
-
}
|
|
61
|
-
endShape(CLOSE);
|
|
62
|
-
pop();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
`;
|
|
67
|
-
export default DUAL_VORTEX_SKETCH;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"geometryIllusion.d.ts","sourceRoot":"","sources":["../../../../soundart-sketches/geometryIllusion.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,krGAuFpC,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
|