color-synth

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

commit df9fd70e935d842b8da4b8910bfc577e99df8fd5
parent 5e6139f8e0eabb75dee9d65edf842d9939f5fd92
Author: massi <mdsiboldi@gmail.com>
Date:   Wed, 19 Jul 2023 02:20:56 -0700

combinators are gone, rescalers are gone

combinators are embedded in input logic now
rescalers will eventually be replaced by volume knobs on each unit.

Diffstat:
Msrc/lib/Slider.svelte | 31+------------------------------
Msrc/lib/engine.worker.ts | 33++++++++++++---------------------
Msrc/lib/types.ts | 35++++++++++++++++++++++++-----------
Msrc/routes/+page.svelte | 22+++++++---------------
4 files changed, 44 insertions(+), 77 deletions(-)

diff --git a/src/lib/Slider.svelte b/src/lib/Slider.svelte @@ -8,8 +8,6 @@ export let handleInput: (id: string, value: number) => void; export let handleChange: () => void; - $: props = { units, handleInput, handleChange }; - $: getUnit = _getUnit.bind(null, units); $: unit = getUnit(id); $: sliderValue = @@ -21,7 +19,6 @@ }; const onInput = (e: WithTarget<Event, HTMLInputElement>) => { - console.log(e.currentTarget); _handleInput(Number(e.currentTarget?.value)); }; </script> @@ -40,42 +37,16 @@ on:input={onInput} on:change={handleChange} /> - {:else if unit.kind === 'combinator'} - <h3>{unit.kind}</h3> - <div class="combinator-container"> - {#each unit.sources as input} - <svelte:self id={input.id} {...props} /> - {/each} - </div> - {:else if unit.kind === 'noise'} - <h3>{unit.kind}</h3> - <svelte:self id={unit.amount.id} {...props} /> - {:else if unit.kind === 'osc'} - <h3>{unit.kind}</h3> - <h4>rate</h4> - coarse - <svelte:self id={unit.coarse[0].id} {...props} /> - fine - <svelte:self id={unit.fine.id} {...props} /> - superfine - <svelte:self id={unit.superfine.id} {...props} /> - <h4>amount</h4> - <svelte:self id={unit.amount.id} {...props} /> {/if} </div> <style> - .combinator-container { - display: flex; - flex-direction: row; - } .unit-container { background: rgba(255, 255, 255, 0.3); padding: 10px; display: flexbox; } - h3, - h4 { + h3 { padding: 0; margin: 0; } diff --git a/src/lib/engine.worker.ts b/src/lib/engine.worker.ts @@ -19,10 +19,8 @@ let config: SynthConfig | undefined = undefined; let unitState: UnitStateMap = new Map(); -// @ts-ignore dunno how to get OffscreenCanvas working let canvas: OffscreenCanvas = new OffscreenCanvas(1, 1); -// @ts-ignore dunno how to get message working onmessage = (message: { data: EngineMessage }) => { const { data } = message; switch (data.kind) { @@ -31,9 +29,7 @@ onmessage = (message: { data: EngineMessage }) => { break; } case "window": { - console.log(data.content); - // @ts-ignore dunno how to get OffscreenCanvas working - canvas = new OffscreenCanvas(content.width, content.height); + canvas = new OffscreenCanvas(data.content.width, data.content.height); } } }; @@ -66,18 +62,9 @@ function setUnitState(id: UnitId, state: UnitState) { unitState.set(id, state); } -function v(inOrIns: Input | Input[]): number { - if (!config) { - throw new Error("no config, can't get unit value.") - } - - if (Array.isArray(inOrIns)) { - return inOrIns.reduce((a, b) => a + v(b), 0); - } - - - const { id } = inOrIns; - const unit: Unit = getUnit(config.units, id); +function vUnit(x: { id: UnitId }): number { + const { id } = x; + const unit: Unit = getUnit(config!.units, id); switch (unit.kind) { case "osc": { const position = getUnitState(id); @@ -96,15 +83,19 @@ function v(inOrIns: Input | Input[]): number { // range is whatever the control for it is??? return unit.value; } - case "combinator": { - return unit.sources.reduce((a, b) => a + v(b), 0); - } case "noise": { return Math.random() * v(unit.amount); } } } +function v(input: Input): number { + if (typeof input === "number") { + return input; + } + return input.reduce((a, b) => a + vUnit(b), 0); +} + function update() { // update all unit states if (!config) { @@ -121,7 +112,7 @@ function update() { const superfine = rescale( v(unit.superfine), range.signal, - range.osc.superfine, + range.osc.superfine ); setUnitState( id, diff --git a/src/lib/types.ts b/src/lib/types.ts @@ -26,7 +26,6 @@ export type EngineMessage = { export type HigherUnit = | OscUnit - | CombinatorUnit | NoiseUnit; export type Unit = @@ -35,13 +34,14 @@ export type Unit = export type UnitId = string; -export type Input = { id: UnitId }; +export type Output = { id: UnitId }; +export type Input = number | Output[]; export type Pos = { x: number; y: number }; export type OscUnit = { kind: "osc"; - coarse: Input[]; + coarse: Input; fine: Input; superfine: Input; amount: Input; @@ -59,18 +59,13 @@ export type ConstUnit = { pos: Pos; }; -export type CombinatorUnit = { - kind: "combinator"; - sources: Input[]; -}; - export type UnitMap = Map<UnitId, Unit>; export type UnitStateMap = Map<UnitId, UnitState>; export type UnitState = any; export type Sinks = { - l: Input | null; - c: Input | null; - h: Input | null; + l: Input; + c: Input; + h: Input; }; type Range = { @@ -219,3 +214,21 @@ export const ensure = { }, }, }; + +export const inp = { + toggle: (input: Input, output: Output): Input => { + if (typeof input === "number") { + return [output] + } + else { + const deduped = input.filter((o) => o.id !== output.id) + if (input.length === deduped.length) { + return [...input, output]; + } + else { + // it's there and we removed it + return deduped; + } + } + } +} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte @@ -3,8 +3,8 @@ import { debounce } from 'lodash'; import Sink from '$lib/Sink.svelte'; import Slider from '$lib/Slider.svelte'; - import { ensure, rescale, range, is, getUnit as _getUnit } from '$lib/types'; - import type { Input, Unit, UnitId, ConstUnit, UnitMap, Sinks } from '$lib/types'; + import { inp, ensure, rescale, range, is, getUnit as _getUnit } from '$lib/types'; + import type { Output, Input, Unit, UnitId, ConstUnit, UnitMap, Sinks } from '$lib/types'; let cvs: HTMLCanvasElement | undefined; let offscreenCanvas: OffscreenCanvas | undefined; @@ -61,7 +61,7 @@ $: getUnit = _getUnit.bind(null, units); let uid = 0; let units: UnitMap = new Map(); - let sinks: Sinks = { l: null, c: null, h: null }; + let sinks: Sinks = { l: 0, c: 0, h: 0 }; onMount(() => { const doc: SerializedState = fromUrl(); @@ -100,7 +100,7 @@ const id = String(uid++); units.set(id, unit); units = units; - return { id }; + return [{ id }]; } type EzUnit = Input | number | undefined; @@ -130,18 +130,12 @@ ): Input { return addUnit({ kind: 'osc', - coarse: [ez(coarse)], + coarse: ez(coarse), fine: ez(fine), superfine: superfine ? ez(superfine) : mk.c(0), amount: ez(amount) }); }, - add: function com(...ids: EzUnit[]) { - return addUnit({ - kind: 'combinator', - sources: ids.map(ez) - }); - }, n: function noise(amt: EzUnit) { return addUnit({ kind: 'noise', amount: ez(amt) }); } @@ -155,8 +149,6 @@ } }; - sinks = { l: null, c: null, h: null }; - function updateUnit(k: UnitId, value: number) { const unit = get.constUnit(k); unit.value = value; @@ -192,7 +184,7 @@ document.addEventListener('mouseup', handleMouseUp); }; - let signalDragging: false | { id: UnitId } = false; + let signalDragging: false | Output = false; const handleSignalStart = (obj: { id: UnitId }) => { console.log('signal start', obj); @@ -211,7 +203,7 @@ if (!signalDragging) { throw new Error('cant connect sink to nonexistant signal'); } - sinks[ch] = { id: signalDragging.id }; + sinks[ch] = inp.toggle(sinks[ch], signalDragging); engineWorker && engineWorker.postMessage({ kind: 'config', content: { sinks, units } }); console.log(sinks); signalDragging = false;