From 03f28aa3d9a48fd7624e0b0b2b1bdcd1dee10d1c Mon Sep 17 00:00:00 2001 From: Leo Mozoloa Date: Fri, 19 Jan 2024 22:59:48 +0100 Subject: [PATCH 1/4] Initial fix & storing events --- dsp/main.js | 22 +++++++++++----------- src/main.jsx | 26 +++++++++++++++----------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/dsp/main.js b/dsp/main.js index 7057940..445d9b1 100644 --- a/dsp/main.js +++ b/dsp/main.js @@ -1,5 +1,5 @@ -import {Renderer, el} from '@elemaudio/core'; -import {RefMap} from './RefMap'; +import { Renderer, el } from '@elemaudio/core'; +import { RefMap } from './RefMap'; import srvb from './srvb'; @@ -36,19 +36,19 @@ globalThis.__receiveStateChange__ = (serializedState) => { let stats = core.render(...srvb({ key: 'srvb', sampleRate: state.sampleRate, - size: refs.getOrCreate('size', 'const', {value: state.size}, []), - decay: refs.getOrCreate('decay', 'const', {value: state.decay}, []), - mod: refs.getOrCreate('mod', 'const', {value: state.mod}, []), - mix: refs.getOrCreate('mix', 'const', {value: state.mix}, []), - }, el.in({channel: 0}), el.in({channel: 1}))); + size: refs.getOrCreate('size', 'const', { value: state.size }, []), + decay: refs.getOrCreate('decay', 'const', { value: state.decay }, []), + mod: refs.getOrCreate('mod', 'const', { value: state.mod }, []), + mix: refs.getOrCreate('mix', 'const', { value: state.mix }, []), + }, el.in({ channel: 0 }), el.in({ channel: 1 }))); console.log(stats); } else { console.log('Updating refs'); - refs.update('size', {value: state.size}); - refs.update('decay', {value: state.decay}); - refs.update('mod', {value: state.mod}); - refs.update('mix', {value: state.mix}); + refs.update('size', { value: state.size }); + refs.update('decay', { value: state.decay }); + refs.update('mod', { value: state.mod }); + refs.update('mix', { value: state.mix }); } prevState = state; diff --git a/src/main.jsx b/src/main.jsx index 3152a19..e2fa5e2 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -2,18 +2,16 @@ import React from 'react' import ReactDOM from 'react-dom/client' import Interface from './Interface.jsx' -import createHooks from 'zustand' -import createStore from 'zustand/vanilla' +import { useStore } from 'zustand' +import { createStore } from 'zustand/vanilla' import './index.css' // Initial state management -const store = createStore(() => {}); -const useStore = createHooks(store); - +const store = createStore(() => { }); +const eventStore = createStore(() => { }); const errorStore = createStore(() => ({ error: null })); -const useErrorStore = createHooks(errorStore); // Interop bindings function requestParamValueUpdate(paramId, value) { @@ -35,12 +33,16 @@ if (process.env.NODE_ENV !== 'production') { }); } -globalThis.__receiveStateChange__ = function(state) { +globalThis.__receiveStateChange__ = function (state) { store.setState(JSON.parse(state)); }; -globalThis.__receiveGraphEvents__ = function(eventBatch) { - console.log(JSON.parse(eventBatch)); +globalThis.__receiveGraphEvents__ = function (eventBatch) { + const batch = JSON.parse(eventBatch); + if (batch.length > 0) { + const map = batch.reduce((acc, event) => { acc[event.event.source] = event; return acc; }, {}); + eventStore.setState(map); + } }; globalThis.__receiveError__ = (err) => { @@ -49,12 +51,14 @@ globalThis.__receiveError__ = (err) => { // Mount the interface function App(props) { - let state = useStore(); - let {error} = useErrorStore(); + let state = useStore(store); + let events = useStore(eventStore); + let { error } = useStore(errorStore); return ( errorStore.setState({ error: null })} /> From e1654c355337f6cdeb73190295a2e985f29c5642 Mon Sep 17 00:00:00 2001 From: Leo Mozoloa Date: Mon, 3 Feb 2025 00:50:26 +0100 Subject: [PATCH 2/4] Removing my ghetto thing --- src/main.jsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/main.jsx b/src/main.jsx index e2fa5e2..1613fe7 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -37,14 +37,9 @@ globalThis.__receiveStateChange__ = function (state) { store.setState(JSON.parse(state)); }; -globalThis.__receiveGraphEvents__ = function (eventBatch) { - const batch = JSON.parse(eventBatch); - if (batch.length > 0) { - const map = batch.reduce((acc, event) => { acc[event.event.source] = event; return acc; }, {}); - eventStore.setState(map); - } +globalThis.__receiveGraphEvents__ = function(eventBatch) { + console.log(JSON.parse(eventBatch)); }; - globalThis.__receiveError__ = (err) => { errorStore.setState({ error: err }); }; @@ -52,13 +47,11 @@ globalThis.__receiveError__ = (err) => { // Mount the interface function App(props) { let state = useStore(store); - let events = useStore(eventStore); let { error } = useStore(errorStore); return ( errorStore.setState({ error: null })} /> From 56d0e587508049b6af746a5fb23bc6e9a9b77ed8 Mon Sep 17 00:00:00 2001 From: Leo Mozoloa Date: Mon, 3 Feb 2025 00:50:59 +0100 Subject: [PATCH 3/4] Delete dsp/main.js --- dsp/main.js | 84 ----------------------------------------------------- 1 file changed, 84 deletions(-) delete mode 100644 dsp/main.js diff --git a/dsp/main.js b/dsp/main.js deleted file mode 100644 index 445d9b1..0000000 --- a/dsp/main.js +++ /dev/null @@ -1,84 +0,0 @@ -import { Renderer, el } from '@elemaudio/core'; -import { RefMap } from './RefMap'; -import srvb from './srvb'; - - -// This project demonstrates writing a small FDN reverb effect in Elementary. -// -// First, we initialize a custom Renderer instance that marshals our instruction -// batches through the __postNativeMessage__ function to direct the underlying native -// engine. -let core = new Renderer((batch) => { - __postNativeMessage__(JSON.stringify(batch)); -}); - -// Next, a RefMap for coordinating our refs -let refs = new RefMap(core); - -// Holding onto the previous state allows us a quick way to differentiate -// when we need to fully re-render versus when we can just update refs -let prevState = null; - -function shouldRender(prevState, nextState) { - return (prevState === null) || (prevState.sampleRate !== nextState.sampleRate); -} - -// The important piece: here we register a state change callback with the native -// side. This callback will be hit with the current processor state any time that -// state changes. -// -// Given the new state, we simply update our refs or perform a full render depending -// on the result of our `shouldRender` check. -globalThis.__receiveStateChange__ = (serializedState) => { - const state = JSON.parse(serializedState); - - if (shouldRender(prevState, state)) { - let stats = core.render(...srvb({ - key: 'srvb', - sampleRate: state.sampleRate, - size: refs.getOrCreate('size', 'const', { value: state.size }, []), - decay: refs.getOrCreate('decay', 'const', { value: state.decay }, []), - mod: refs.getOrCreate('mod', 'const', { value: state.mod }, []), - mix: refs.getOrCreate('mix', 'const', { value: state.mix }, []), - }, el.in({ channel: 0 }), el.in({ channel: 1 }))); - - console.log(stats); - } else { - console.log('Updating refs'); - refs.update('size', { value: state.size }); - refs.update('decay', { value: state.decay }); - refs.update('mod', { value: state.mod }); - refs.update('mix', { value: state.mix }); - } - - prevState = state; -}; - -// NOTE: This is highly experimental and should not yet be relied on -// as a consistent feature. -// -// This hook allows the native side to inject serialized graph state from -// the running elem::Runtime instance so that we can throw away and reinitialize -// the JavaScript engine and then inject necessary state for coordinating with -// the underlying engine. -globalThis.__receiveHydrationData__ = (data) => { - const payload = JSON.parse(data); - const nodeMap = core._delegate.nodeMap; - - for (let [k, v] of Object.entries(payload)) { - nodeMap.set(parseInt(k, 16), { - symbol: '__ELEM_NODE__', - kind: '__HYDRATED__', - hash: parseInt(k, 16), - props: v, - generation: { - current: 0, - }, - }); - } -}; - -// Finally, an error callback which just logs back to native -globalThis.__receiveError__ = (err) => { - console.log(`[Error: ${err.name}] ${err.message}`); -}; From b0cc70a2174138e2785e43d0a04a52863d960105 Mon Sep 17 00:00:00 2001 From: Leo Mozoloa Date: Mon, 3 Feb 2025 00:53:54 +0100 Subject: [PATCH 4/4] bringing back dsp main lmao --- dsp/main.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 dsp/main.js diff --git a/dsp/main.js b/dsp/main.js new file mode 100644 index 0000000..146a395 --- /dev/null +++ b/dsp/main.js @@ -0,0 +1,84 @@ +import {Renderer, el} from '@elemaudio/core'; +import {RefMap} from './RefMap'; +import srvb from './srvb'; + + +// This project demonstrates writing a small FDN reverb effect in Elementary. +// +// First, we initialize a custom Renderer instance that marshals our instruction +// batches through the __postNativeMessage__ function to direct the underlying native +// engine. +let core = new Renderer((batch) => { + __postNativeMessage__(JSON.stringify(batch)); +}); + +// Next, a RefMap for coordinating our refs +let refs = new RefMap(core); + +// Holding onto the previous state allows us a quick way to differentiate +// when we need to fully re-render versus when we can just update refs +let prevState = null; + +function shouldRender(prevState, nextState) { + return (prevState === null) || (prevState.sampleRate !== nextState.sampleRate); +} + +// The important piece: here we register a state change callback with the native +// side. This callback will be hit with the current processor state any time that +// state changes. +// +// Given the new state, we simply update our refs or perform a full render depending +// on the result of our `shouldRender` check. +globalThis.__receiveStateChange__ = (serializedState) => { + const state = JSON.parse(serializedState); + + if (shouldRender(prevState, state)) { + let stats = core.render(...srvb({ + key: 'srvb', + sampleRate: state.sampleRate, + size: refs.getOrCreate('size', 'const', {value: state.size}, []), + decay: refs.getOrCreate('decay', 'const', {value: state.decay}, []), + mod: refs.getOrCreate('mod', 'const', {value: state.mod}, []), + mix: refs.getOrCreate('mix', 'const', {value: state.mix}, []), + }, el.in({channel: 0}), el.in({channel: 1}))); + + console.log(stats); + } else { + console.log('Updating refs'); + refs.update('size', {value: state.size}); + refs.update('decay', {value: state.decay}); + refs.update('mod', {value: state.mod}); + refs.update('mix', {value: state.mix}); + } + + prevState = state; +}; + +// NOTE: This is highly experimental and should not yet be relied on +// as a consistent feature. +// +// This hook allows the native side to inject serialized graph state from +// the running elem::Runtime instance so that we can throw away and reinitialize +// the JavaScript engine and then inject necessary state for coordinating with +// the underlying engine. +globalThis.__receiveHydrationData__ = (data) => { + const payload = JSON.parse(data); + const nodeMap = core._delegate.nodeMap; + + for (let [k, v] of Object.entries(payload)) { + nodeMap.set(parseInt(k, 16), { + symbol: '__ELEM_NODE__', + kind: '__HYDRATED__', + hash: parseInt(k, 16), + props: v, + generation: { + current: 0, + }, + }); + } +}; + +// Finally, an error callback which just logs back to native +globalThis.__receiveError__ = (err) => { + console.log(`[Error: ${err.name}] ${err.message}`); +};