color-synth

a synth that generates colors instead of sounds
Log | Files | Refs | README

commit 1431d5787eec2c5b224900f22e03f6a8be3aeb43
parent bd4581677a1717e16d44d76e5bd297265aeb1477
Author: massi <mdsiboldi@gmail.com>
Date:   Mon, 21 Aug 2023 22:07:36 -0700

things

Diffstat:
Mpackage-lock.json | 16+++++++++++++++-
Mpackage.json | 3++-
Msrc/lib/engine.worker.ts | 27++++++++++++---------------
Msrc/lib/stores.ts | 27++++++++++++++++++++-------
Msrc/lib/types.ts | 23++++++++++++++++++-----
Msrc/routes/+page.svelte | 31+++++++++++++++++++++++--------
6 files changed, 90 insertions(+), 37 deletions(-)

diff --git a/package-lock.json b/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.1", "dependencies": { "@sveltejs/adapter-static": "^2.0.2", - "lodash": "^4.17.21" + "lodash": "^4.17.21", + "uuid": "^9.0.0" }, "devDependencies": { "@sveltejs/adapter-auto": "^2.0.0", @@ -2874,6 +2875,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vite": { "version": "4.3.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", @@ -4830,6 +4839,11 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + }, "vite": { "version": "4.3.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", diff --git a/package.json b/package.json @@ -32,6 +32,7 @@ "type": "module", "dependencies": { "@sveltejs/adapter-static": "^2.0.2", - "lodash": "^4.17.21" + "lodash": "^4.17.21", + "uuid": "^9.0.0" } } diff --git a/src/lib/engine.worker.ts b/src/lib/engine.worker.ts @@ -8,7 +8,17 @@ import type { UnitStateMap } from '$lib/types'; import { oklch } from '$lib/color'; -import { ROWS, COLS, getUnit, LOOP_CYCLES, RANGE, rescale, wrangle, unitRange } from '$lib/types'; +import { + ROWS, + COLS, + getUnit, + LOOP_CYCLES, + RANGE, + rescale, + wrangle, + unitRange, + oscShapes +} from '$lib/types'; let config: SynthConfig | undefined = undefined; let unitState: UnitStateMap = new Map(); @@ -59,19 +69,6 @@ function setUnitState(id: UnitId, state: UnitState) { unitState.set(id, state); } -type OscShapes = { - [k: string]: (p: number, a: number) => number; -}; -const oscShapes: OscShapes = { - sine: (position: number, amount: number) => { - return Math.sin(2 * Math.PI * position) * amount; - }, - square: (p, a) => { - return (p < 0.5 ? -1 : 1) * a; - }, - triangle: (p, a) => p * a -}; - function vUnit(x: { id: UnitId }): number { const { id } = x; const unit: Unit = getUnit(null, config!.units, id); @@ -144,7 +141,7 @@ function update() { ); setUnitState( id, - (position + (coarse * LOOP_CYCLES) / 100 + fine * 20000 + superfine * 10) % LOOP_CYCLES + (position + (coarse * LOOP_CYCLES) / 100 + fine * 20000 + superfine) % LOOP_CYCLES ); break; } diff --git a/src/lib/stores.ts b/src/lib/stores.ts @@ -10,11 +10,13 @@ import { type Units, RANGE, wrangle, - unitRange + unitRange, + type Pos } from '$lib/types'; -import { writable } from 'svelte/store'; +import { v4 as uuidv4 } from 'uuid'; -let uuid = 0; +import { writable } from 'svelte/store'; +import UnitControl from './UnitControl.svelte'; const randConst = () => { const sliderVal = Math.round(rescale(Math.random(), { min: 0, max: 1 }, RANGE.slider)); @@ -43,7 +45,6 @@ const mkUnitStore = () => { }, setControl, addUnit<K extends UnitKind>(kind: K): UnitId { - const id = uuid++; let unit: Unit; switch (kind) { case 'const': { @@ -53,7 +54,12 @@ const mkUnitStore = () => { case 'osc': { unit = { kind: 'osc', - controls: { coarse: 0, fine: 0, superfine: 0, amount: RANGE.signal.max }, + controls: { + coarse: wrangle(1, unitRange.osc.coarse, RANGE.signal), + fine: wrangle(1, unitRange.osc.coarse, RANGE.signal), + superfine: 0, + amount: RANGE.signal.max + }, pos: { x: 0, y: 0 } }; break; @@ -71,12 +77,19 @@ const mkUnitStore = () => { break; } } - update((units) => ({ ...units, [id]: unit })); - return String(id); + + const uuid = uuidv4(); + update((units) => { + return { ...units, [uuid]: unit }; + }); + return String(uuid); } }; }; export const unitToConnect = writable<UnitToConnect>(false); +export type UnitDragging = null | { initPos: Pos; pos: Pos; id: UnitId }; +export const unitDragging = writable<UnitDragging>(null); + export const unitStore = mkUnitStore(); diff --git a/src/lib/types.ts b/src/lib/types.ts @@ -34,7 +34,7 @@ export type EngineMessage = content: OffscreenCanvas; }; -type Pos = { +export type Pos = { x: number; y: number; }; @@ -134,8 +134,8 @@ export const unitRange: { max: 50 }, superfine: { - min: -50, - max: 50 + min: -10_000, + max: 10_000 }, amount: { min: -50, @@ -144,8 +144,8 @@ export const unitRange: { }, const: { value: { - min: -5_000_000, - max: 5_000_000 + min: -50_000_000, + max: 50_000_000 } }, noise: { @@ -242,3 +242,16 @@ export const inp = { }; export type UnitToConnect = Output | false; + +type OscShapes = { + [k: string]: (p: number, a: number) => number; +}; +export const oscShapes: OscShapes = { + sine: (position: number, amount: number) => { + return Math.sin(2 * Math.PI * position) * amount; + }, + square: (p, a) => { + return (p < 0.5 ? -1 : 1) * a; + }, + triangle: (p, a) => p * a +}; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte @@ -4,7 +4,17 @@ import { debounce } from 'lodash'; import Sink from '$lib/Sink.svelte'; import { COLS, ROWS, inp, rescale, RANGE, is, getUnit as _getUnit, unitKinds } from '$lib/types'; - import type { Output, Input, Unit, UnitId, ConstUnit, Units, Sinks, UnitKind } from '$lib/types'; + import type { + Output, + Input, + Unit, + UnitId, + ConstUnit, + Units, + Sinks, + UnitKind, + Pos + } from '$lib/types'; import OscUnitComponent from '$lib/OscUnit.svelte'; import NoiseUnitComponent from '$lib/NoiseUnit.svelte'; import ConstUnitComponent from '$lib/ConstUnit.svelte'; @@ -115,15 +125,15 @@ return id; } - let dragging: false | UnitId = false; + let dragging: false | { initPos: Pos; id: UnitId } = false; const handleMouseMove = (e: MouseEvent) => { if (!dragging) return; - unitStore.setUnit(dragging, { - ...getUnit(dragging), + unitStore.setUnit(dragging.id, { + ...getUnit(dragging.id), pos: { - x: e.clientX, - y: e.clientY + x: e.clientX - dragging.initPos.x, + y: e.clientY - dragging.initPos.y } }); }; @@ -134,8 +144,12 @@ document.removeEventListener('mouseup', handleMouseUp); }; - const handleMouseDown = (id: UnitId) => { - dragging = id; + const handleMouseDown = (id: UnitId, e: MouseEvent) => { + e.preventDefault(); + e.stopPropagation(); + const pos = { x: e.offsetX, y: e.offsetY }; + console.log({ pos }); + dragging = { initPos: pos, id }; document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); }; @@ -188,6 +202,7 @@ {#each unitKinds as kind} <button on:click={() => unitStore.addUnit(kind)}>add {kind}</button> {/each} + <button on:click={updateUrl}>save</button> </div> <div id="sinks">