@nexart/codemode-sdk 1.5.0 → 1.6.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 +326 -0
- package/CODE_MODE_PROTOCOL.md +471 -0
- package/LICENSE.md +62 -0
- package/README.md +296 -58
- package/builder.manifest.schema.json +62 -0
- package/dist/builder-manifest.d.ts +79 -0
- package/dist/builder-manifest.d.ts.map +1 -0
- package/dist/builder-manifest.js +97 -0
- package/dist/core-index.d.ts +21 -0
- package/dist/core-index.d.ts.map +1 -0
- package/dist/core-index.js +26 -0
- package/dist/engine.d.ts +17 -39
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +52 -253
- package/dist/execute.d.ts +46 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +283 -0
- package/dist/execution-sandbox.d.ts +107 -0
- package/dist/execution-sandbox.d.ts.map +1 -0
- package/dist/execution-sandbox.js +207 -0
- package/dist/index.d.ts +24 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -16
- package/dist/loop-engine.d.ts +3 -0
- package/dist/loop-engine.d.ts.map +1 -1
- package/dist/loop-engine.js +17 -7
- package/dist/noise-bridge.d.ts +44 -0
- package/dist/noise-bridge.d.ts.map +1 -0
- package/dist/noise-bridge.js +68 -0
- package/dist/noise-engine.d.ts +74 -0
- package/dist/noise-engine.d.ts.map +1 -0
- package/dist/noise-engine.js +132 -0
- package/dist/noise-sketches/fractalNoise.d.ts +11 -0
- package/dist/noise-sketches/fractalNoise.d.ts.map +1 -0
- package/dist/noise-sketches/fractalNoise.js +121 -0
- package/dist/noise-sketches/index.d.ts +21 -0
- package/dist/noise-sketches/index.d.ts.map +1 -0
- package/dist/noise-sketches/index.js +28 -0
- package/dist/p5-runtime.d.ts +3 -1
- package/dist/p5-runtime.d.ts.map +1 -1
- package/dist/p5-runtime.js +2 -0
- package/dist/sound-bridge.d.ts +89 -0
- package/dist/sound-bridge.d.ts.map +1 -0
- package/dist/sound-bridge.js +128 -0
- package/dist/soundart-engine.d.ts +87 -0
- package/dist/soundart-engine.d.ts.map +1 -0
- package/dist/soundart-engine.js +173 -0
- package/dist/soundart-sketches/chladniBloom.d.ts +3 -0
- package/dist/soundart-sketches/chladniBloom.d.ts.map +1 -0
- package/dist/soundart-sketches/chladniBloom.js +53 -0
- package/dist/soundart-sketches/dualVortex.d.ts +3 -0
- package/dist/soundart-sketches/dualVortex.d.ts.map +1 -0
- package/dist/soundart-sketches/dualVortex.js +67 -0
- package/dist/soundart-sketches/geometryIllusion.d.ts +3 -0
- package/dist/soundart-sketches/geometryIllusion.d.ts.map +1 -0
- package/dist/soundart-sketches/geometryIllusion.js +89 -0
- package/dist/soundart-sketches/index.d.ts +39 -0
- package/dist/soundart-sketches/index.d.ts.map +1 -0
- package/dist/soundart-sketches/index.js +72 -0
- package/dist/soundart-sketches/isoflow.d.ts +3 -0
- package/dist/soundart-sketches/isoflow.d.ts.map +1 -0
- package/dist/soundart-sketches/isoflow.js +60 -0
- package/dist/soundart-sketches/loomWeave.d.ts +3 -0
- package/dist/soundart-sketches/loomWeave.d.ts.map +1 -0
- package/dist/soundart-sketches/loomWeave.js +59 -0
- package/dist/soundart-sketches/noiseTerraces.d.ts +3 -0
- package/dist/soundart-sketches/noiseTerraces.d.ts.map +1 -0
- package/dist/soundart-sketches/noiseTerraces.js +53 -0
- package/dist/soundart-sketches/orb.d.ts +3 -0
- package/dist/soundart-sketches/orb.d.ts.map +1 -0
- package/dist/soundart-sketches/orb.js +50 -0
- package/dist/soundart-sketches/pixelGlyphs.d.ts +3 -0
- package/dist/soundart-sketches/pixelGlyphs.d.ts.map +1 -0
- package/dist/soundart-sketches/pixelGlyphs.js +72 -0
- package/dist/soundart-sketches/prismFlowFields.d.ts +3 -0
- package/dist/soundart-sketches/prismFlowFields.d.ts.map +1 -0
- package/dist/soundart-sketches/prismFlowFields.js +51 -0
- package/dist/soundart-sketches/radialBurst.d.ts +3 -0
- package/dist/soundart-sketches/radialBurst.d.ts.map +1 -0
- package/dist/soundart-sketches/radialBurst.js +60 -0
- package/dist/soundart-sketches/resonantSoundBodies.d.ts +3 -0
- package/dist/soundart-sketches/resonantSoundBodies.d.ts.map +1 -0
- package/dist/soundart-sketches/resonantSoundBodies.js +89 -0
- package/dist/soundart-sketches/rings.d.ts +11 -0
- package/dist/soundart-sketches/rings.d.ts.map +1 -0
- package/dist/soundart-sketches/rings.js +89 -0
- package/dist/soundart-sketches/squares.d.ts +3 -0
- package/dist/soundart-sketches/squares.d.ts.map +1 -0
- package/dist/soundart-sketches/squares.js +52 -0
- package/dist/soundart-sketches/waveStripes.d.ts +3 -0
- package/dist/soundart-sketches/waveStripes.d.ts.map +1 -0
- package/dist/soundart-sketches/waveStripes.js +44 -0
- package/dist/static-engine.d.ts +7 -0
- package/dist/static-engine.d.ts.map +1 -1
- package/dist/static-engine.js +69 -14
- package/dist/types.d.ts +67 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/package.json +26 -15
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const PRISM_FLOW_FIELDS_SKETCH = "\nfunction setup() {\n const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';\n if (bgMode === 'white') background(245, 245, 245);\n else if (bgMode === 'black') background(10, 10, 10);\n else {\n const r = Math.floor((S.brightness / 100) * 255);\n const g = Math.floor((S.rhythmicity / 100) * 255);\n const b = Math.floor((S.harmonicity / 100) * 255);\n background(r, g, b);\n }\n\n const particleCount = Math.floor(map(S.volume, 0, 100, 1500, 8200));\n const maxSteps = Math.floor(map(S.rhythmicity, 0, 100, 200, 680));\n const weightMin = map(S.volume, 0, 100, 0.5, 1.8);\n const weightMax = map(S.treble, 0, 100, 1.2, 3.2);\n const angleMult = map(max(0, S.harmonicity - 5), 0, 95, 2.5, 7.0);\n const stepJitter = map(S.aggression, 0, 100, 0.5, 2.5);\n const skewOffset = map(S.hue, 0, 100, -PI / 6, PI / 6);\n const alphaBase = map(S.brightness, 0, 100, 0.4, 0.7);\n const scaleF = map(S.harmonicity, 0, 100, 0.0001, 0.0024);\n\n noFill();\n\n for (let i = 0; i < particleCount; i++) {\n let x = random() * width;\n let y = random() * height;\n const hueShift = (i / particleCount) * 360 + (S.hue * 3.6);\n const h = hueShift % 360;\n const sat = map(S.aggression, 0, 100, 70, 100);\n const bri = map(S.brightness, 0, 100, 60, 100);\n \n stroke('hsla(' + h + ',' + sat + '%,' + bri + '%,' + alphaBase + ')');\n strokeWeight(map(random(), 0, 1, weightMin, weightMax));\n \n beginShape();\n vertex(x, y);\n for (let j = 0; j < maxSteps; j++) {\n const angle = noise(x * scaleF, y * scaleF) * PI * 4 + skewOffset;\n const dx = cos(angle) * (angleMult + (random() - 0.5) * stepJitter);\n const dy = sin(angle) * (angleMult + (random() - 0.5) * stepJitter);\n x += dx;\n y += dy;\n if (x < 0 || x > width || y < 0 || y > height) break;\n vertex(x, y);\n }\n endShape();\n }\n}\n";
|
|
2
|
+
export default PRISM_FLOW_FIELDS_SKETCH;
|
|
3
|
+
//# sourceMappingURL=prismFlowFields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prismFlowFields.d.ts","sourceRoot":"","sources":["../../soundart-sketches/prismFlowFields.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,43DAiDpC,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export const PRISM_FLOW_FIELDS_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 particleCount = Math.floor(map(S.volume, 0, 100, 1500, 8200));
|
|
14
|
+
const maxSteps = Math.floor(map(S.rhythmicity, 0, 100, 200, 680));
|
|
15
|
+
const weightMin = map(S.volume, 0, 100, 0.5, 1.8);
|
|
16
|
+
const weightMax = map(S.treble, 0, 100, 1.2, 3.2);
|
|
17
|
+
const angleMult = map(max(0, S.harmonicity - 5), 0, 95, 2.5, 7.0);
|
|
18
|
+
const stepJitter = map(S.aggression, 0, 100, 0.5, 2.5);
|
|
19
|
+
const skewOffset = map(S.hue, 0, 100, -PI / 6, PI / 6);
|
|
20
|
+
const alphaBase = map(S.brightness, 0, 100, 0.4, 0.7);
|
|
21
|
+
const scaleF = map(S.harmonicity, 0, 100, 0.0001, 0.0024);
|
|
22
|
+
|
|
23
|
+
noFill();
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < particleCount; i++) {
|
|
26
|
+
let x = random() * width;
|
|
27
|
+
let y = random() * height;
|
|
28
|
+
const hueShift = (i / particleCount) * 360 + (S.hue * 3.6);
|
|
29
|
+
const h = hueShift % 360;
|
|
30
|
+
const sat = map(S.aggression, 0, 100, 70, 100);
|
|
31
|
+
const bri = map(S.brightness, 0, 100, 60, 100);
|
|
32
|
+
|
|
33
|
+
stroke('hsla(' + h + ',' + sat + '%,' + bri + '%,' + alphaBase + ')');
|
|
34
|
+
strokeWeight(map(random(), 0, 1, weightMin, weightMax));
|
|
35
|
+
|
|
36
|
+
beginShape();
|
|
37
|
+
vertex(x, y);
|
|
38
|
+
for (let j = 0; j < maxSteps; j++) {
|
|
39
|
+
const angle = noise(x * scaleF, y * scaleF) * PI * 4 + skewOffset;
|
|
40
|
+
const dx = cos(angle) * (angleMult + (random() - 0.5) * stepJitter);
|
|
41
|
+
const dy = sin(angle) * (angleMult + (random() - 0.5) * stepJitter);
|
|
42
|
+
x += dx;
|
|
43
|
+
y += dy;
|
|
44
|
+
if (x < 0 || x > width || y < 0 || y > height) break;
|
|
45
|
+
vertex(x, y);
|
|
46
|
+
}
|
|
47
|
+
endShape();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
export default PRISM_FLOW_FIELDS_SKETCH;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const RADIAL_BURST_SKETCH = "\nfunction setup() {\n const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';\n if (bgMode === 'white') background(245, 245, 245);\n else if (bgMode === 'black') background(10, 10, 10);\n else {\n const r = Math.floor((S.brightness / 100) * 255);\n const g = Math.floor((S.rhythmicity / 100) * 255);\n const b = Math.floor((S.harmonicity / 100) * 255);\n background(r, g, b);\n }\n\n const centerX = width / 2;\n const centerY = height / 2;\n const baseN = Math.floor(map(S.rhythmicity, 0, 100, 90, 320));\n const rhythmMask = 0.4 + (S.rhythmicity / 100) * 0.6;\n\n const palette = [];\n const mainHue = (S.brightness * 3.6) % 360;\n for (let i = 0; i < 16; i++) {\n const h = (mainHue + i * 22.5) % 360;\n const sat = map(S.treble, 0, 100, 60, 90);\n const bri = map(S.bass, 0, 100, 70, 95);\n palette.push('hsl(' + h + ',' + sat + '%,' + bri + '%)');\n }\n\n noFill();\n\n for (let i = 0; i < baseN; i++) {\n if ((i % 3) && random() > rhythmMask) continue;\n\n const angle = (i / baseN) * PI * 2;\n const col = palette[i % palette.length];\n\n const lenJit = map(S.dynamicRange, 0, 100, 0, height * 2.45);\n const rayLength = (S.amplitude / 100) * (height * 1.65) + random() * lenJit;\n\n const waveAmp = map(S.harmonicity, 0, 100, 0, 42);\n const waveFreq = map(S.treble, 0, 100, 1, 48);\n const segments = 28;\n\n const thickness = 1.2 + (S.attack / 100) * 7 + (S.aggression / 100) * 5 + sin(i * 0.9) * 1.4;\n\n stroke(col);\n strokeWeight(thickness);\n\n beginShape();\n for (let s = 0; s <= segments; s++) {\n const t = s / segments;\n const radius = t * rayLength;\n const wobble = sin(t * PI * waveFreq + i * 0.2) * waveAmp * (1 - t);\n const wx = centerX + cos(angle + wobble * 0.01) * radius;\n const wy = centerY + sin(angle + wobble * 0.01) * radius;\n vertex(wx, wy);\n }\n endShape();\n }\n}\n";
|
|
2
|
+
export default RADIAL_BURST_SKETCH;
|
|
3
|
+
//# sourceMappingURL=radialBurst.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radialBurst.d.ts","sourceRoot":"","sources":["../../soundart-sketches/radialBurst.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,+5DA0D/B,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const RADIAL_BURST_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 centerX = width / 2;
|
|
14
|
+
const centerY = height / 2;
|
|
15
|
+
const baseN = Math.floor(map(S.rhythmicity, 0, 100, 90, 320));
|
|
16
|
+
const rhythmMask = 0.4 + (S.rhythmicity / 100) * 0.6;
|
|
17
|
+
|
|
18
|
+
const palette = [];
|
|
19
|
+
const mainHue = (S.brightness * 3.6) % 360;
|
|
20
|
+
for (let i = 0; i < 16; i++) {
|
|
21
|
+
const h = (mainHue + i * 22.5) % 360;
|
|
22
|
+
const sat = map(S.treble, 0, 100, 60, 90);
|
|
23
|
+
const bri = map(S.bass, 0, 100, 70, 95);
|
|
24
|
+
palette.push('hsl(' + h + ',' + sat + '%,' + bri + '%)');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
noFill();
|
|
28
|
+
|
|
29
|
+
for (let i = 0; i < baseN; i++) {
|
|
30
|
+
if ((i % 3) && random() > rhythmMask) continue;
|
|
31
|
+
|
|
32
|
+
const angle = (i / baseN) * PI * 2;
|
|
33
|
+
const col = palette[i % palette.length];
|
|
34
|
+
|
|
35
|
+
const lenJit = map(S.dynamicRange, 0, 100, 0, height * 2.45);
|
|
36
|
+
const rayLength = (S.amplitude / 100) * (height * 1.65) + random() * lenJit;
|
|
37
|
+
|
|
38
|
+
const waveAmp = map(S.harmonicity, 0, 100, 0, 42);
|
|
39
|
+
const waveFreq = map(S.treble, 0, 100, 1, 48);
|
|
40
|
+
const segments = 28;
|
|
41
|
+
|
|
42
|
+
const thickness = 1.2 + (S.attack / 100) * 7 + (S.aggression / 100) * 5 + sin(i * 0.9) * 1.4;
|
|
43
|
+
|
|
44
|
+
stroke(col);
|
|
45
|
+
strokeWeight(thickness);
|
|
46
|
+
|
|
47
|
+
beginShape();
|
|
48
|
+
for (let s = 0; s <= segments; s++) {
|
|
49
|
+
const t = s / segments;
|
|
50
|
+
const radius = t * rayLength;
|
|
51
|
+
const wobble = sin(t * PI * waveFreq + i * 0.2) * waveAmp * (1 - t);
|
|
52
|
+
const wx = centerX + cos(angle + wobble * 0.01) * radius;
|
|
53
|
+
const wy = centerY + sin(angle + wobble * 0.01) * radius;
|
|
54
|
+
vertex(wx, wy);
|
|
55
|
+
}
|
|
56
|
+
endShape();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
60
|
+
export default RADIAL_BURST_SKETCH;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const RESONANT_SOUND_BODIES_SKETCH = "\nfunction setup() {\n const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';\n if (bgMode === 'white') background(245, 245, 245);\n else if (bgMode === 'black') background(10, 10, 10);\n else {\n const r = Math.floor((S.brightness / 100) * 255);\n const g = Math.floor((S.rhythmicity / 100) * 255);\n const b = Math.floor((S.harmonicity / 100) * 255);\n background(r, g, b);\n }\n\n const cx = width / 2;\n const cy = height / 2;\n const maxR = min(width, height) * 0.45;\n const shapeSeed = S.bass * 17.3 + S.treble * 23.7 + S.rhythmicity * 11.1;\n\n const numBodies = Math.floor(8 + (S.volume / 100) * 12 + (S.bass / 100) * 8);\n \n noFill();\n\n for (let i = 0; i < numBodies; i++) {\n const t = i / numBodies;\n const radius = maxR * (0.15 + t * 0.85);\n \n const hue = (((S.hue / 100) + t * 0.3 + (S.harmonicity / 100) * 0.2) % 1) * 360;\n const sat = lerp(50, 80, S.brightness / 100);\n const lum = lerp(30, 60, S.brightness / 100);\n \n const alpha = lerp(0.4, 0.15, t) * (0.5 + (S.volume / 100) * 0.5);\n stroke('hsla(' + hue + ',' + sat + '%,' + lum + '%,' + alpha + ')');\n strokeWeight(lerp(3, 1, t) * (1 + (S.aggression / 100) * 2));\n \n beginShape();\n const points = Math.floor(64 + (S.aggression / 100) * 64);\n \n for (let j = 0; j <= points; j++) {\n const angle = (j / points) * PI * 2;\n \n const wobble = noise(\n cos(angle) * 3 + i * 0.5 + shapeSeed * 0.001,\n sin(angle) * 3 + i * 0.5\n );\n \n const bassWobble = sin(angle * (2 + Math.floor((S.bass / 100) * 6))) * (S.bass / 100) * 0.15;\n const trebleWobble = sin(angle * (8 + Math.floor((S.treble / 100) * 12))) * (S.treble / 100) * 0.08;\n \n const r = radius * (1 + (wobble - 0.5) * 0.3 * (S.aggression / 100) + bassWobble + trebleWobble);\n \n const x = cx + cos(angle) * r;\n const y = cy + sin(angle) * r;\n \n vertex(x, y);\n }\n endShape(CLOSE);\n \n if (i % 3 === 0) {\n const fillAlpha = alpha * 0.1;\n fill('hsla(' + hue + ',' + sat + '%,' + lum + '%,' + fillAlpha + ')');\n beginShape();\n for (let j = 0; j <= points; j++) {\n const angle = (j / points) * PI * 2;\n const wobble = noise(cos(angle) * 3 + i * 0.5 + shapeSeed * 0.001, sin(angle) * 3 + i * 0.5);\n const bodyR = radius * (1 + (wobble - 0.5) * 0.3 * (S.aggression / 100));\n vertex(cx + cos(angle) * bodyR, cy + sin(angle) * bodyR);\n }\n endShape(CLOSE);\n noFill();\n }\n }\n\n const numNodes = Math.floor(12 + (S.rhythmicity / 100) * 20);\n for (let i = 0; i < numNodes; i++) {\n const angle = (i / numNodes) * PI * 2 + shapeSeed * 0.001;\n const dist = maxR * (0.3 + noise(i * 0.1, shapeSeed * 0.001) * 0.6);\n \n const x = cx + cos(angle) * dist;\n const y = cy + sin(angle) * dist;\n \n const nodeSize = lerp(2, 8, S.volume / 100) * (1 + (S.bass / 100) * 2);\n const hue = ((((S.hue / 100) + i * 0.05 + (S.treble / 100) * 0.3) % 1)) * 360;\n \n fill('hsla(' + hue + ',70%,' + lerp(40, 70, S.brightness / 100) + '%,' + lerp(0.3, 0.7, S.harmonicity / 100) + ')');\n noStroke();\n ellipse(x, y, nodeSize * 2, nodeSize * 2);\n }\n}\n";
|
|
2
|
+
export default RESONANT_SOUND_BODIES_SKETCH;
|
|
3
|
+
//# sourceMappingURL=resonantSoundBodies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resonantSoundBodies.d.ts","sourceRoot":"","sources":["../../soundart-sketches/resonantSoundBodies.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,wtGAuFxC,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export const RESONANT_SOUND_BODIES_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 cx = width / 2;
|
|
14
|
+
const cy = height / 2;
|
|
15
|
+
const maxR = min(width, height) * 0.45;
|
|
16
|
+
const shapeSeed = S.bass * 17.3 + S.treble * 23.7 + S.rhythmicity * 11.1;
|
|
17
|
+
|
|
18
|
+
const numBodies = Math.floor(8 + (S.volume / 100) * 12 + (S.bass / 100) * 8);
|
|
19
|
+
|
|
20
|
+
noFill();
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < numBodies; i++) {
|
|
23
|
+
const t = i / numBodies;
|
|
24
|
+
const radius = maxR * (0.15 + t * 0.85);
|
|
25
|
+
|
|
26
|
+
const hue = (((S.hue / 100) + t * 0.3 + (S.harmonicity / 100) * 0.2) % 1) * 360;
|
|
27
|
+
const sat = lerp(50, 80, S.brightness / 100);
|
|
28
|
+
const lum = lerp(30, 60, S.brightness / 100);
|
|
29
|
+
|
|
30
|
+
const alpha = lerp(0.4, 0.15, t) * (0.5 + (S.volume / 100) * 0.5);
|
|
31
|
+
stroke('hsla(' + hue + ',' + sat + '%,' + lum + '%,' + alpha + ')');
|
|
32
|
+
strokeWeight(lerp(3, 1, t) * (1 + (S.aggression / 100) * 2));
|
|
33
|
+
|
|
34
|
+
beginShape();
|
|
35
|
+
const points = Math.floor(64 + (S.aggression / 100) * 64);
|
|
36
|
+
|
|
37
|
+
for (let j = 0; j <= points; j++) {
|
|
38
|
+
const angle = (j / points) * PI * 2;
|
|
39
|
+
|
|
40
|
+
const wobble = noise(
|
|
41
|
+
cos(angle) * 3 + i * 0.5 + shapeSeed * 0.001,
|
|
42
|
+
sin(angle) * 3 + i * 0.5
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const bassWobble = sin(angle * (2 + Math.floor((S.bass / 100) * 6))) * (S.bass / 100) * 0.15;
|
|
46
|
+
const trebleWobble = sin(angle * (8 + Math.floor((S.treble / 100) * 12))) * (S.treble / 100) * 0.08;
|
|
47
|
+
|
|
48
|
+
const r = radius * (1 + (wobble - 0.5) * 0.3 * (S.aggression / 100) + bassWobble + trebleWobble);
|
|
49
|
+
|
|
50
|
+
const x = cx + cos(angle) * r;
|
|
51
|
+
const y = cy + sin(angle) * r;
|
|
52
|
+
|
|
53
|
+
vertex(x, y);
|
|
54
|
+
}
|
|
55
|
+
endShape(CLOSE);
|
|
56
|
+
|
|
57
|
+
if (i % 3 === 0) {
|
|
58
|
+
const fillAlpha = alpha * 0.1;
|
|
59
|
+
fill('hsla(' + hue + ',' + sat + '%,' + lum + '%,' + fillAlpha + ')');
|
|
60
|
+
beginShape();
|
|
61
|
+
for (let j = 0; j <= points; j++) {
|
|
62
|
+
const angle = (j / points) * PI * 2;
|
|
63
|
+
const wobble = noise(cos(angle) * 3 + i * 0.5 + shapeSeed * 0.001, sin(angle) * 3 + i * 0.5);
|
|
64
|
+
const bodyR = radius * (1 + (wobble - 0.5) * 0.3 * (S.aggression / 100));
|
|
65
|
+
vertex(cx + cos(angle) * bodyR, cy + sin(angle) * bodyR);
|
|
66
|
+
}
|
|
67
|
+
endShape(CLOSE);
|
|
68
|
+
noFill();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const numNodes = Math.floor(12 + (S.rhythmicity / 100) * 20);
|
|
73
|
+
for (let i = 0; i < numNodes; i++) {
|
|
74
|
+
const angle = (i / numNodes) * PI * 2 + shapeSeed * 0.001;
|
|
75
|
+
const dist = maxR * (0.3 + noise(i * 0.1, shapeSeed * 0.001) * 0.6);
|
|
76
|
+
|
|
77
|
+
const x = cx + cos(angle) * dist;
|
|
78
|
+
const y = cy + sin(angle) * dist;
|
|
79
|
+
|
|
80
|
+
const nodeSize = lerp(2, 8, S.volume / 100) * (1 + (S.bass / 100) * 2);
|
|
81
|
+
const hue = ((((S.hue / 100) + i * 0.05 + (S.treble / 100) * 0.3) % 1)) * 360;
|
|
82
|
+
|
|
83
|
+
fill('hsla(' + hue + ',70%,' + lerp(40, 70, S.brightness / 100) + '%,' + lerp(0.3, 0.7, S.harmonicity / 100) + ')');
|
|
84
|
+
noStroke();
|
|
85
|
+
ellipse(x, y, nodeSize * 2, nodeSize * 2);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
`;
|
|
89
|
+
export default RESONANT_SOUND_BODIES_SKETCH;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flow Grid Rings - SoundArt Style as Code Mode Sketch
|
|
3
|
+
*
|
|
4
|
+
* This is the first SoundArt style converted to a Code Mode sketch.
|
|
5
|
+
* It uses S.* globals (sound snapshot) instead of direct sound data.
|
|
6
|
+
*
|
|
7
|
+
* Original: client/src/pages/soundart/engine/styles_impl.ts - drawFlowGridRings
|
|
8
|
+
*/
|
|
9
|
+
export declare const RINGS_SKETCH = "\n// Flow Grid Rings - SoundArt Style\n// Uses S.* sound globals and standard p5-like functions\n\nfunction setup() {\n // Set background based on mode (rgb derived from sound, black, or white)\n const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';\n \n if (bgMode === 'white') {\n background(245, 245, 245);\n } else if (bgMode === 'black') {\n background(10, 10, 10);\n } else {\n // Deterministic RGB background derived from sound snapshot\n // Previously used clock time, now uses sound parameters for reproducibility\n const r = Math.floor((S.brightness / 100) * 255);\n const g = Math.floor((S.rhythmicity / 100) * 255);\n const b = Math.floor((S.harmonicity / 100) * 255);\n background(r, g, b);\n }\n \n // Grid dimensions based on sound volume\n const cols = Math.floor(map(S.volume, 0, 100, 2, 32));\n const rows = Math.floor(cols * 1.5);\n const margin = map(S.length, 0, 100, width * 0.05, width * 0.1);\n const innerW = width - margin * 2;\n const innerH = height - margin * 2;\n const cellW = innerW / cols;\n const cellH = innerH / rows;\n const gap = Math.min(cellW, cellH) * 0.25;\n const maxRadius = (Math.min(cellW, cellH) - gap) / 2;\n \n // Palette Harmony based on sound\n const mainHue = (S.brightness * 3.6) % 360;\n const hueShift = map(S.harmonicity, 0, 100, 20, 60);\n const sat = map(S.treble, 0, 100, 60, 90);\n const bri = map(S.bass, 0, 100, 70, 95);\n \n // Generate palette\n const palette = [\n hslColor(mainHue, sat, bri),\n hslColor((mainHue + hueShift) % 360, sat - 10, bri + 5),\n hslColor((mainHue - hueShift + 360) % 360, sat - 10, bri + 5),\n hslColor((mainHue + 180) % 360, sat - 20, bri - 10),\n hslColor((mainHue + 120) % 360, sat, bri - 5),\n hslColor((mainHue + 240) % 360, sat, bri - 5),\n ];\n \n // Flow field parameters\n const noiseScale = 0.15;\n const noiseStrength = map(S.aggression, 0, 100, 0.5, 4.0);\n const jitter = map(S.rhythmicity, 0, 100, 0, 0.15);\n const ringBias = map(S.attack, 0, 100, 0.85, 1.15);\n \n noStroke();\n \n // Render Grid\n for (let gx = 0; gx < cols; gx++) {\n for (let gy = 0; gy < rows; gy++) {\n const cx = margin + gx * cellW + cellW / 2 + (random() - 0.5) * jitter * cellW;\n const cy = margin + gy * cellH + cellH / 2 + (random() - 0.5) * jitter * cellH;\n \n const n = noise(gx * noiseScale, gy * noiseScale);\n const angle = n * PI * 2 * noiseStrength;\n const rings = Math.max(1, Math.floor(map(sin(angle), -1, 1, 1, 6)));\n const step = (maxRadius / rings) * ringBias * 0.9;\n \n for (let i = rings; i > 0; i--) {\n fill(palette[(rings - i) % palette.length]);\n ellipse(cx, cy, i * step * 2, i * step * 2);\n }\n }\n }\n}\n\n// Helper function for HSL colors\nfunction hslColor(h, s, l) {\n return 'hsl(' + h + ',' + s + '%,' + l + '%)';\n}\n";
|
|
10
|
+
export default RINGS_SKETCH;
|
|
11
|
+
//# sourceMappingURL=rings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rings.d.ts","sourceRoot":"","sources":["../../soundart-sketches/rings.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,YAAY,u2FA+ExB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flow Grid Rings - SoundArt Style as Code Mode Sketch
|
|
3
|
+
*
|
|
4
|
+
* This is the first SoundArt style converted to a Code Mode sketch.
|
|
5
|
+
* It uses S.* globals (sound snapshot) instead of direct sound data.
|
|
6
|
+
*
|
|
7
|
+
* Original: client/src/pages/soundart/engine/styles_impl.ts - drawFlowGridRings
|
|
8
|
+
*/
|
|
9
|
+
export const RINGS_SKETCH = `
|
|
10
|
+
// Flow Grid Rings - SoundArt Style
|
|
11
|
+
// Uses S.* sound globals and standard p5-like functions
|
|
12
|
+
|
|
13
|
+
function setup() {
|
|
14
|
+
// Set background based on mode (rgb derived from sound, black, or white)
|
|
15
|
+
const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';
|
|
16
|
+
|
|
17
|
+
if (bgMode === 'white') {
|
|
18
|
+
background(245, 245, 245);
|
|
19
|
+
} else if (bgMode === 'black') {
|
|
20
|
+
background(10, 10, 10);
|
|
21
|
+
} else {
|
|
22
|
+
// Deterministic RGB background derived from sound snapshot
|
|
23
|
+
// Previously used clock time, now uses sound parameters for reproducibility
|
|
24
|
+
const r = Math.floor((S.brightness / 100) * 255);
|
|
25
|
+
const g = Math.floor((S.rhythmicity / 100) * 255);
|
|
26
|
+
const b = Math.floor((S.harmonicity / 100) * 255);
|
|
27
|
+
background(r, g, b);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Grid dimensions based on sound volume
|
|
31
|
+
const cols = Math.floor(map(S.volume, 0, 100, 2, 32));
|
|
32
|
+
const rows = Math.floor(cols * 1.5);
|
|
33
|
+
const margin = map(S.length, 0, 100, width * 0.05, width * 0.1);
|
|
34
|
+
const innerW = width - margin * 2;
|
|
35
|
+
const innerH = height - margin * 2;
|
|
36
|
+
const cellW = innerW / cols;
|
|
37
|
+
const cellH = innerH / rows;
|
|
38
|
+
const gap = Math.min(cellW, cellH) * 0.25;
|
|
39
|
+
const maxRadius = (Math.min(cellW, cellH) - gap) / 2;
|
|
40
|
+
|
|
41
|
+
// Palette Harmony based on sound
|
|
42
|
+
const mainHue = (S.brightness * 3.6) % 360;
|
|
43
|
+
const hueShift = map(S.harmonicity, 0, 100, 20, 60);
|
|
44
|
+
const sat = map(S.treble, 0, 100, 60, 90);
|
|
45
|
+
const bri = map(S.bass, 0, 100, 70, 95);
|
|
46
|
+
|
|
47
|
+
// Generate palette
|
|
48
|
+
const palette = [
|
|
49
|
+
hslColor(mainHue, sat, bri),
|
|
50
|
+
hslColor((mainHue + hueShift) % 360, sat - 10, bri + 5),
|
|
51
|
+
hslColor((mainHue - hueShift + 360) % 360, sat - 10, bri + 5),
|
|
52
|
+
hslColor((mainHue + 180) % 360, sat - 20, bri - 10),
|
|
53
|
+
hslColor((mainHue + 120) % 360, sat, bri - 5),
|
|
54
|
+
hslColor((mainHue + 240) % 360, sat, bri - 5),
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
// Flow field parameters
|
|
58
|
+
const noiseScale = 0.15;
|
|
59
|
+
const noiseStrength = map(S.aggression, 0, 100, 0.5, 4.0);
|
|
60
|
+
const jitter = map(S.rhythmicity, 0, 100, 0, 0.15);
|
|
61
|
+
const ringBias = map(S.attack, 0, 100, 0.85, 1.15);
|
|
62
|
+
|
|
63
|
+
noStroke();
|
|
64
|
+
|
|
65
|
+
// Render Grid
|
|
66
|
+
for (let gx = 0; gx < cols; gx++) {
|
|
67
|
+
for (let gy = 0; gy < rows; gy++) {
|
|
68
|
+
const cx = margin + gx * cellW + cellW / 2 + (random() - 0.5) * jitter * cellW;
|
|
69
|
+
const cy = margin + gy * cellH + cellH / 2 + (random() - 0.5) * jitter * cellH;
|
|
70
|
+
|
|
71
|
+
const n = noise(gx * noiseScale, gy * noiseScale);
|
|
72
|
+
const angle = n * PI * 2 * noiseStrength;
|
|
73
|
+
const rings = Math.max(1, Math.floor(map(sin(angle), -1, 1, 1, 6)));
|
|
74
|
+
const step = (maxRadius / rings) * ringBias * 0.9;
|
|
75
|
+
|
|
76
|
+
for (let i = rings; i > 0; i--) {
|
|
77
|
+
fill(palette[(rings - i) % palette.length]);
|
|
78
|
+
ellipse(cx, cy, i * step * 2, i * step * 2);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Helper function for HSL colors
|
|
85
|
+
function hslColor(h, s, l) {
|
|
86
|
+
return 'hsl(' + h + ',' + s + '%,' + l + '%)';
|
|
87
|
+
}
|
|
88
|
+
`;
|
|
89
|
+
export default RINGS_SKETCH;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const SQUARES_SKETCH = "\nfunction setup() {\n const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';\n if (bgMode === 'white') background(245, 245, 245);\n else if (bgMode === 'black') background(10, 10, 10);\n else {\n const r = Math.floor((S.brightness / 100) * 255);\n const g = Math.floor((S.rhythmicity / 100) * 255);\n const b = Math.floor((S.harmonicity / 100) * 255);\n background(r, g, b);\n }\n\n const numSquares = Math.floor(map(S.length, 0, 100, 40, 300));\n let size = Math.min(width, height) * 0.9;\n const shrinkFactor = map(S.dynamicRange, 0, 100, 0.92, 1.08);\n const rotationStep = map(S.aggression, 0, 100, 0.01, 0.07);\n const strokeMin = map(S.volume, 0, 100, 1.0, 6.0);\n const strokeMax = map(S.bass, 0, 100, 2.0, 8.0);\n\n const colors = [];\n for (let i = 0; i < 5; i++) {\n const baseHue = (S.hue + i * 60 + random() * 20) % 360;\n const sat = constrain(map(S.treble, 0, 100, 60, 95), 50, 100);\n const bri = constrain(map(S.brightness, 0, 100, 40, 85), 30, 90);\n colors.push(hslColor(baseHue, sat, bri));\n }\n\n noFill();\n translate(width / 2, height / 2);\n\n let angle = 0;\n for (let i = 0; i < numSquares; i++) {\n const strokeW = strokeMin + (i / numSquares) * (strokeMax - strokeMin);\n strokeWeight(strokeW);\n stroke(colors[i % colors.length]);\n\n push();\n rotate(angle);\n rect(-size / 2, -size / 2, size, size);\n pop();\n\n angle += rotationStep;\n size *= shrinkFactor;\n if (size < 4) break;\n }\n}\n\nfunction hslColor(h, s, l) {\n return 'hsl(' + h + ',' + s + '%,' + l + '%)';\n}\n";
|
|
2
|
+
export default SQUARES_SKETCH;
|
|
3
|
+
//# sourceMappingURL=squares.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"squares.d.ts","sourceRoot":"","sources":["../../soundart-sketches/squares.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,0kDAkD1B,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export const SQUARES_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 numSquares = Math.floor(map(S.length, 0, 100, 40, 300));
|
|
14
|
+
let size = Math.min(width, height) * 0.9;
|
|
15
|
+
const shrinkFactor = map(S.dynamicRange, 0, 100, 0.92, 1.08);
|
|
16
|
+
const rotationStep = map(S.aggression, 0, 100, 0.01, 0.07);
|
|
17
|
+
const strokeMin = map(S.volume, 0, 100, 1.0, 6.0);
|
|
18
|
+
const strokeMax = map(S.bass, 0, 100, 2.0, 8.0);
|
|
19
|
+
|
|
20
|
+
const colors = [];
|
|
21
|
+
for (let i = 0; i < 5; i++) {
|
|
22
|
+
const baseHue = (S.hue + i * 60 + random() * 20) % 360;
|
|
23
|
+
const sat = constrain(map(S.treble, 0, 100, 60, 95), 50, 100);
|
|
24
|
+
const bri = constrain(map(S.brightness, 0, 100, 40, 85), 30, 90);
|
|
25
|
+
colors.push(hslColor(baseHue, sat, bri));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
noFill();
|
|
29
|
+
translate(width / 2, height / 2);
|
|
30
|
+
|
|
31
|
+
let angle = 0;
|
|
32
|
+
for (let i = 0; i < numSquares; i++) {
|
|
33
|
+
const strokeW = strokeMin + (i / numSquares) * (strokeMax - strokeMin);
|
|
34
|
+
strokeWeight(strokeW);
|
|
35
|
+
stroke(colors[i % colors.length]);
|
|
36
|
+
|
|
37
|
+
push();
|
|
38
|
+
rotate(angle);
|
|
39
|
+
rect(-size / 2, -size / 2, size, size);
|
|
40
|
+
pop();
|
|
41
|
+
|
|
42
|
+
angle += rotationStep;
|
|
43
|
+
size *= shrinkFactor;
|
|
44
|
+
if (size < 4) break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function hslColor(h, s, l) {
|
|
49
|
+
return 'hsl(' + h + ',' + s + '%,' + l + '%)';
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
export default SQUARES_SKETCH;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const WAVE_STRIPES_SKETCH = "\nfunction setup() {\n const bgMode = typeof backgroundMode !== 'undefined' ? backgroundMode : 'rgb';\n if (bgMode === 'white') background(245, 245, 245);\n else if (bgMode === 'black') background(10, 10, 10);\n else {\n const r = Math.floor((S.brightness / 100) * 255);\n const g = Math.floor((S.rhythmicity / 100) * 255);\n const b = Math.floor((S.harmonicity / 100) * 255);\n background(r, g, b);\n }\n\n const numLines = Math.floor(map(S.length, 0, 100, 5, 100));\n const amp = map(S.volume, 0, 100, 0.012, 0.09);\n const lineNoise = map(S.harmonicity, 0, 100, 0.1, 0.8);\n const freqNoise = map(S.aggression, 0, 100, 0.004, 0.02);\n const waveFreq = map(S.rhythmicity, 0, 100, 0.0003, 0.003);\n const strokeW = map(S.bass, 0, 100, 2, 6.0);\n const vividBoost = constrain(map(S.brightness, 0, 100, 0.6, 1.2), 0.6, 1.4);\n\n noFill();\n strokeWeight(strokeW);\n\n for (let j = 0; j < numLines; j++) {\n const yBase = map(j, 0, numLines - 1, 0.05 * height, 0.95 * height);\n const lineTreble = constrain(S.treble + noise(j, 99) * 20 - 10, 0, 100);\n const hue = ((map(lineTreble, 60, 100, 0, 360) + map(S.attack, 0, 100, 0, 120) + noise(j, 100) * 20 - 10) % 360 + 360) % 360;\n \n stroke('hsl(' + hue + ',85%,' + constrain(vividBoost * 55, 40, 70) + '%)');\n \n beginShape();\n const pointSpacing = constrain(map(S.harmonicity, 0, 100, 20, 4), 4, 20);\n for (let i = 0; i <= width; i += pointSpacing) {\n const shimmer = sin(i * 0.05 + j * 0.1) * 0.05;\n const offsetY = sin(i * waveFreq + j * 0.2 + shimmer) * amp * height;\n const localNoiseVal = (noise(i * freqNoise, j * lineNoise) - 0.5) * amp * height;\n const y = yBase + offsetY + localNoiseVal;\n vertex(i, y);\n }\n endShape();\n }\n}\n";
|
|
2
|
+
export default WAVE_STRIPES_SKETCH;
|
|
3
|
+
//# sourceMappingURL=waveStripes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waveStripes.d.ts","sourceRoot":"","sources":["../../soundart-sketches/waveStripes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,6vDA0C/B,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const WAVE_STRIPES_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 numLines = Math.floor(map(S.length, 0, 100, 5, 100));
|
|
14
|
+
const amp = map(S.volume, 0, 100, 0.012, 0.09);
|
|
15
|
+
const lineNoise = map(S.harmonicity, 0, 100, 0.1, 0.8);
|
|
16
|
+
const freqNoise = map(S.aggression, 0, 100, 0.004, 0.02);
|
|
17
|
+
const waveFreq = map(S.rhythmicity, 0, 100, 0.0003, 0.003);
|
|
18
|
+
const strokeW = map(S.bass, 0, 100, 2, 6.0);
|
|
19
|
+
const vividBoost = constrain(map(S.brightness, 0, 100, 0.6, 1.2), 0.6, 1.4);
|
|
20
|
+
|
|
21
|
+
noFill();
|
|
22
|
+
strokeWeight(strokeW);
|
|
23
|
+
|
|
24
|
+
for (let j = 0; j < numLines; j++) {
|
|
25
|
+
const yBase = map(j, 0, numLines - 1, 0.05 * height, 0.95 * height);
|
|
26
|
+
const lineTreble = constrain(S.treble + noise(j, 99) * 20 - 10, 0, 100);
|
|
27
|
+
const hue = ((map(lineTreble, 60, 100, 0, 360) + map(S.attack, 0, 100, 0, 120) + noise(j, 100) * 20 - 10) % 360 + 360) % 360;
|
|
28
|
+
|
|
29
|
+
stroke('hsl(' + hue + ',85%,' + constrain(vividBoost * 55, 40, 70) + '%)');
|
|
30
|
+
|
|
31
|
+
beginShape();
|
|
32
|
+
const pointSpacing = constrain(map(S.harmonicity, 0, 100, 20, 4), 4, 20);
|
|
33
|
+
for (let i = 0; i <= width; i += pointSpacing) {
|
|
34
|
+
const shimmer = sin(i * 0.05 + j * 0.1) * 0.05;
|
|
35
|
+
const offsetY = sin(i * waveFreq + j * 0.2 + shimmer) * amp * height;
|
|
36
|
+
const localNoiseVal = (noise(i * freqNoise, j * lineNoise) - 0.5) * amp * height;
|
|
37
|
+
const y = yBase + offsetY + localNoiseVal;
|
|
38
|
+
vertex(i, y);
|
|
39
|
+
}
|
|
40
|
+
endShape();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
export default WAVE_STRIPES_SKETCH;
|
package/dist/static-engine.d.ts
CHANGED
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Determinism Guarantee:
|
|
9
9
|
* Same code + same seed + same VARs = identical PNG output
|
|
10
|
+
*
|
|
11
|
+
* Security:
|
|
12
|
+
* All external entropy sources are blocked at runtime via execution sandbox.
|
|
13
|
+
*
|
|
14
|
+
* Oracle Support:
|
|
15
|
+
* When returnImageData is true, returns raw ImageData for determinism hashing.
|
|
16
|
+
* Works in both browser (HTMLCanvasElement) and Node (canvas package) environments.
|
|
10
17
|
*/
|
|
11
18
|
import type { EngineConfig, RunOptions } from './types';
|
|
12
19
|
export declare function runStaticMode(config: EngineConfig, options: RunOptions): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-engine.d.ts","sourceRoot":"","sources":["../static-engine.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"static-engine.d.ts","sourceRoot":"","sources":["../static-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAgB,MAAM,SAAS,CAAC;AAoCtE,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,IAAI,CAAC,CA6Hf"}
|
package/dist/static-engine.js
CHANGED
|
@@ -7,11 +7,44 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Determinism Guarantee:
|
|
9
9
|
* Same code + same seed + same VARs = identical PNG output
|
|
10
|
+
*
|
|
11
|
+
* Security:
|
|
12
|
+
* All external entropy sources are blocked at runtime via execution sandbox.
|
|
13
|
+
*
|
|
14
|
+
* Oracle Support:
|
|
15
|
+
* When returnImageData is true, returns raw ImageData for determinism hashing.
|
|
16
|
+
* Works in both browser (HTMLCanvasElement) and Node (canvas package) environments.
|
|
10
17
|
*/
|
|
18
|
+
import { createRequire } from 'module';
|
|
11
19
|
import { DEFAULT_CONFIG } from './types';
|
|
12
20
|
import { createP5Runtime, injectTimeVariables, injectProtocolVariables } from './p5-runtime';
|
|
21
|
+
import { FORBIDDEN_APIS, createSafeMath } from './execution-sandbox';
|
|
22
|
+
const require = createRequire(import.meta.url);
|
|
23
|
+
/**
|
|
24
|
+
* Create a runtime canvas that works in both browser and Node environments.
|
|
25
|
+
* Browser: uses HTMLCanvasElement
|
|
26
|
+
* Node/Headless: uses `canvas` npm package
|
|
27
|
+
*/
|
|
28
|
+
function createRuntimeCanvas(width, height) {
|
|
29
|
+
// Browser environment
|
|
30
|
+
if (typeof document !== 'undefined' && typeof document.createElement === 'function') {
|
|
31
|
+
const canvas = document.createElement('canvas');
|
|
32
|
+
canvas.width = width;
|
|
33
|
+
canvas.height = height;
|
|
34
|
+
return canvas;
|
|
35
|
+
}
|
|
36
|
+
// Node / headless environment (oracle, CI)
|
|
37
|
+
try {
|
|
38
|
+
const { createCanvas } = require('canvas');
|
|
39
|
+
return createCanvas(width, height);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
throw new Error('[Code Mode Protocol Error] Headless canvas unavailable. ' +
|
|
43
|
+
'Install `canvas` for oracle execution.');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
13
46
|
export async function runStaticMode(config, options) {
|
|
14
|
-
const { code, seed, vars, onPreview, onProgress, onComplete, onError } = options;
|
|
47
|
+
const { code, seed, vars, onPreview, onProgress, onComplete, onError, returnImageData } = options;
|
|
15
48
|
const width = config.width ?? DEFAULT_CONFIG.width;
|
|
16
49
|
const height = config.height ?? DEFAULT_CONFIG.height;
|
|
17
50
|
try {
|
|
@@ -20,10 +53,8 @@ export async function runStaticMode(config, options) {
|
|
|
20
53
|
percent: 0,
|
|
21
54
|
message: 'Initializing canvas...',
|
|
22
55
|
});
|
|
23
|
-
// Create
|
|
24
|
-
const canvas =
|
|
25
|
-
canvas.width = width;
|
|
26
|
-
canvas.height = height;
|
|
56
|
+
// Create runtime canvas (browser or Node)
|
|
57
|
+
const canvas = createRuntimeCanvas(width, height);
|
|
27
58
|
// Create p5 runtime with optional seed for determinism
|
|
28
59
|
const p = createP5Runtime(canvas, width, height, { seed });
|
|
29
60
|
// Inject time variables (static = frame 0, t = 0, totalFrames = 1)
|
|
@@ -56,18 +87,43 @@ export async function runStaticMode(config, options) {
|
|
|
56
87
|
percent: 30,
|
|
57
88
|
message: 'Executing setup()...',
|
|
58
89
|
});
|
|
59
|
-
// Create
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
90
|
+
// Create sandboxed execution context
|
|
91
|
+
// All forbidden APIs are injected as parameters to override globals
|
|
92
|
+
const safeMath = createSafeMath();
|
|
93
|
+
const forbiddenKeys = Object.keys(FORBIDDEN_APIS);
|
|
94
|
+
// Create wrapped setup function with p5 context, VAR, and blocked globals
|
|
95
|
+
const wrappedSetup = new Function('p', 'frameCount', 't', 'time', 'tGlobal', 'VAR', 'Math', ...forbiddenKeys, `with(p) { ${setupCode} }`);
|
|
96
|
+
// Execute setup() only with sandboxed context
|
|
97
|
+
const forbiddenValues = forbiddenKeys.map(k => FORBIDDEN_APIS[k]);
|
|
98
|
+
wrappedSetup(p, 0, 0, 0, 0, p.VAR, safeMath, ...forbiddenValues);
|
|
63
99
|
// Provide preview callback
|
|
64
100
|
onPreview?.(canvas);
|
|
65
101
|
onProgress?.({
|
|
66
102
|
phase: 'encoding',
|
|
67
103
|
percent: 70,
|
|
68
|
-
message: 'Capturing PNG...',
|
|
104
|
+
message: returnImageData ? 'Capturing ImageData...' : 'Capturing PNG...',
|
|
69
105
|
});
|
|
70
|
-
//
|
|
106
|
+
// Get 2D context for pixel access
|
|
107
|
+
const ctx = canvas.getContext('2d');
|
|
108
|
+
if (!ctx) {
|
|
109
|
+
throw new Error('Failed to acquire 2D context');
|
|
110
|
+
}
|
|
111
|
+
// Always capture pixel data first
|
|
112
|
+
const imageData = ctx.getImageData(0, 0, width, height);
|
|
113
|
+
// ORACLE / NODE PATH — MUST NOT TOUCH toBlob
|
|
114
|
+
if (returnImageData) {
|
|
115
|
+
onProgress?.({
|
|
116
|
+
phase: 'complete',
|
|
117
|
+
percent: 100,
|
|
118
|
+
message: 'Complete',
|
|
119
|
+
});
|
|
120
|
+
onComplete({
|
|
121
|
+
type: 'image',
|
|
122
|
+
imageData,
|
|
123
|
+
});
|
|
124
|
+
return; // Early return - never touch toBlob in oracle mode
|
|
125
|
+
}
|
|
126
|
+
// BROWSER / UI PATH ONLY
|
|
71
127
|
const blob = await new Promise((resolve, reject) => {
|
|
72
128
|
canvas.toBlob((b) => b ? resolve(b) : reject(new Error('Failed to capture PNG')), 'image/png');
|
|
73
129
|
});
|
|
@@ -76,11 +132,10 @@ export async function runStaticMode(config, options) {
|
|
|
76
132
|
percent: 100,
|
|
77
133
|
message: 'Complete',
|
|
78
134
|
});
|
|
79
|
-
|
|
135
|
+
onComplete({
|
|
80
136
|
type: 'image',
|
|
81
137
|
blob,
|
|
82
|
-
};
|
|
83
|
-
onComplete(result);
|
|
138
|
+
});
|
|
84
139
|
}
|
|
85
140
|
catch (error) {
|
|
86
141
|
const err = error instanceof Error ? error : new Error(String(error));
|