From de00212bb6ed586d604bfa7fddf7ce0a99934065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81mbar=20Tenorio=20Forn=C3=A9s?= Date: Wed, 22 Nov 2023 12:27:18 +0100 Subject: [PATCH 01/12] fix hydra performance issues --- packages/hydra/hydra.mjs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index 692e4c14..b63ca423 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -4,11 +4,11 @@ export async function initHydra() { if (!document.getElementById('hydra-canvas')) { const { canvas: testCanvas } = getDrawContext(); await import('https://unpkg.com/hydra-synth'); - const hydraCanvas = testCanvas.cloneNode(true); - hydraCanvas.id = 'hydra-canvas'; - testCanvas.after(hydraCanvas); - new Hydra({ canvas: hydraCanvas, detectAudio: false }); - s0.init({ src: testCanvas }); + h = new Hydra({detectAudio: false }); + h.canvas.id = 'hydra-canvas'; + h.canvas.style.position = 'absolute'; + h.canvas.style.top = '0px'; + testCanvas.after(h.canvas); } } From 66fd20ace5bd8e54bf76c3013dd73f31df91fde8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81mbar=20Tenorio=20Forn=C3=A9s?= Date: Wed, 22 Nov 2023 12:36:43 +0100 Subject: [PATCH 02/12] add hydra audio capture option --- packages/hydra/README.md | 7 +++++++ packages/hydra/hydra.mjs | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/hydra/README.md b/packages/hydra/README.md index d300bb88..e36a421b 100644 --- a/packages/hydra/README.md +++ b/packages/hydra/README.md @@ -12,6 +12,13 @@ await initHydra(); Then you can use hydra below! +### Enable audio capture +Use `{audio: true}` param to enable Hydra's audio capture: + +```js +await initHydra({audio: true}); +``` + ## Usage via npm ```sh diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index b63ca423..e105b440 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -1,10 +1,10 @@ import { getDrawContext } from '@strudel.cycles/core'; -export async function initHydra() { +export async function initHydra(config) { if (!document.getElementById('hydra-canvas')) { const { canvas: testCanvas } = getDrawContext(); await import('https://unpkg.com/hydra-synth'); - h = new Hydra({detectAudio: false }); + h = new Hydra({detectAudio: config?.audio }); h.canvas.id = 'hydra-canvas'; h.canvas.style.position = 'absolute'; h.canvas.style.top = '0px'; From ebc6723f55d4879b3bfcb4853363fd14885a6228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81mbar=20Tenorio=20Forn=C3=A9s?= Date: Wed, 22 Nov 2023 13:51:01 +0100 Subject: [PATCH 03/12] enable hydra options update --- packages/hydra/hydra.mjs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index e105b440..778f3361 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -1,6 +1,10 @@ import { getDrawContext } from '@strudel.cycles/core'; +let options = "" + export async function initHydra(config) { + + //load and init hydra if (!document.getElementById('hydra-canvas')) { const { canvas: testCanvas } = getDrawContext(); await import('https://unpkg.com/hydra-synth'); @@ -10,6 +14,17 @@ export async function initHydra(config) { h.canvas.style.top = '0px'; testCanvas.after(h.canvas); } + + // update options + if (options != JSON.stringify(config)) { + options = JSON.stringify(config); + + new Hydra( + { + canvas: document.getElementById('hydra-canvas'), + detectAudio: config?.audio + }) + } } export const H = (p) => () => p.queryArc(getTime(), getTime())[0].value; From a58ac967a620246b6432834cc7df4a80b87aa487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81mbar=20Tenorio=20Forn=C3=A9s?= Date: Wed, 22 Nov 2023 13:51:42 +0100 Subject: [PATCH 04/12] add Hydra audio example to documentation --- website/src/pages/learn/hydra.mdx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/website/src/pages/learn/hydra.mdx b/website/src/pages/learn/hydra.mdx index a506e53c..dd892ff7 100644 --- a/website/src/pages/learn/hydra.mdx +++ b/website/src/pages/learn/hydra.mdx @@ -48,7 +48,23 @@ There is a special function `H` that allows you to use a pattern as an input to tune={`await initHydra() let pattern = "3 4 5 [6 7]*2" shape(H(pattern)).out(o0) -n(pattern).scale("A:minor").piano().room(1) +n(pattern).scale("A:minor").piano().room(1) +`} +/> + +To use hydra audio capture, call `initHydra` with `{audio:true}` configuration param: + + a.fft[0]*.25 + ) + .add(src(o0).color(.71 ).scrollX(.005),.95) +.out(o0) +n(pattern).scale("A:minor").piano().room(1) `} /> From 0a280e939927ad4956ce14b3e42139935cdf83be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81mbar=20Tenorio=20Forn=C3=A9s?= Date: Wed, 22 Nov 2023 15:47:16 +0100 Subject: [PATCH 05/12] prettier code formatting --- packages/hydra/hydra.mjs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index 778f3361..25d69c93 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -1,14 +1,13 @@ import { getDrawContext } from '@strudel.cycles/core'; -let options = "" +let options = ''; export async function initHydra(config) { - //load and init hydra if (!document.getElementById('hydra-canvas')) { const { canvas: testCanvas } = getDrawContext(); await import('https://unpkg.com/hydra-synth'); - h = new Hydra({detectAudio: config?.audio }); + h = new Hydra({ detectAudio: config?.audio }); h.canvas.id = 'hydra-canvas'; h.canvas.style.position = 'absolute'; h.canvas.style.top = '0px'; @@ -19,11 +18,10 @@ export async function initHydra(config) { if (options != JSON.stringify(config)) { options = JSON.stringify(config); - new Hydra( - { - canvas: document.getElementById('hydra-canvas'), - detectAudio: config?.audio - }) + new Hydra({ + canvas: document.getElementById('hydra-canvas'), + detectAudio: config?.audio, + }); } } From e0e896d4b534627a7539458339868ee03157ca68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81mbar=20Tenorio=20Forn=C3=A9s?= Date: Wed, 22 Nov 2023 17:39:16 +0100 Subject: [PATCH 06/12] improve hydra audio detection initialization --- packages/hydra/hydra.mjs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index 25d69c93..3f41e256 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -1,27 +1,33 @@ import { getDrawContext } from '@strudel.cycles/core'; -let options = ''; +let audio = false; +let hydra; + +function appendCanvas(c){ + const { canvas: testCanvas } = getDrawContext(); + c.canvas.id = 'hydra-canvas'; + c.canvas.style.position = 'absolute'; + c.canvas.style.top = '0px'; + testCanvas.after(c.canvas); +} export async function initHydra(config) { + audio = config?.audio || false; //load and init hydra if (!document.getElementById('hydra-canvas')) { - const { canvas: testCanvas } = getDrawContext(); await import('https://unpkg.com/hydra-synth'); - h = new Hydra({ detectAudio: config?.audio }); - h.canvas.id = 'hydra-canvas'; - h.canvas.style.position = 'absolute'; - h.canvas.style.top = '0px'; - testCanvas.after(h.canvas); + hydra = new Hydra({ detectAudio: audio }); + appendCanvas(hydra); } - // update options - if (options != JSON.stringify(config)) { - options = JSON.stringify(config); - - new Hydra({ - canvas: document.getElementById('hydra-canvas'), - detectAudio: config?.audio, - }); + // if config.audio is true + // and current canvas des not detect audio + if (config?.audio && !hydra.detectAudio ){ + //remove previous canvas without audio detection + document.getElementById('hydra-canvas').remove() + // create and append a new audio responsive canvas + hydra = new Hydra({ detectAudio: audio}); + appendCanvas(hydra) } } From fb7a9e2083c10226acfb7f29991076f64ea477c4 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 24 Nov 2023 10:28:40 +0100 Subject: [PATCH 07/12] format --- packages/hydra/hydra.mjs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index 3f41e256..a75614ec 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -3,7 +3,7 @@ import { getDrawContext } from '@strudel.cycles/core'; let audio = false; let hydra; -function appendCanvas(c){ +function appendCanvas(c) { const { canvas: testCanvas } = getDrawContext(); c.canvas.id = 'hydra-canvas'; c.canvas.style.position = 'absolute'; @@ -22,12 +22,12 @@ export async function initHydra(config) { // if config.audio is true // and current canvas des not detect audio - if (config?.audio && !hydra.detectAudio ){ + if (config?.audio && !hydra.detectAudio) { //remove previous canvas without audio detection - document.getElementById('hydra-canvas').remove() + document.getElementById('hydra-canvas').remove(); // create and append a new audio responsive canvas - hydra = new Hydra({ detectAudio: audio}); - appendCanvas(hydra) + hydra = new Hydra({ detectAudio: audio }); + appendCanvas(hydra); } } From 456be920d345c3d6b6874a2b88a176fcbfe11e1a Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 24 Nov 2023 11:17:30 +0100 Subject: [PATCH 08/12] else clause --- packages/hydra/hydra.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index b63fc46c..b2f60ddf 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -21,10 +21,9 @@ export async function initHydra(options = {}) { appendCanvas(hydra); // s0.init({ src: hydraCanvas }); // whats that? } - // if options.detectAudio is true // and current canvas des not detect audio - if (options?.detectAudio && !hydra?.detectAudio) { + else if (options?.detectAudio && !hydra?.detectAudio) { //remove previous canvas without audio detection document.getElementById('hydra-canvas').remove(); return initHydra(options); From 9045ce05da102bdcc2b5a76922807ed1c56230b0 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 24 Nov 2023 11:28:20 +0100 Subject: [PATCH 09/12] comment --- packages/hydra/hydra.mjs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index b2f60ddf..e2614ac0 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -16,14 +16,12 @@ export async function initHydra(options = {}) { if (!document.getElementById('hydra-canvas')) { const { src = 'https://unpkg.com/hydra-synth', ...opts } = options; await import(src); - hydra = new Hydra(opts); appendCanvas(hydra); - // s0.init({ src: hydraCanvas }); // whats that? - } - // if options.detectAudio is true - // and current canvas des not detect audio - else if (options?.detectAudio && !hydra?.detectAudio) { + // hydra.synth.s0.init({ src: testCanvas }); // is this needed? + } else if (options?.detectAudio && !hydra?.detectAudio) { + // if options.detectAudio is true + // and current canvas des not detect audio //remove previous canvas without audio detection document.getElementById('hydra-canvas').remove(); return initHydra(options); From 508a6c92b28695d50e24e8c4619c525393780c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81mbar=20Tenorio=20Forn=C3=A9s?= Date: Fri, 24 Nov 2023 12:21:04 +0100 Subject: [PATCH 10/12] default hydra config without audio detection --- packages/hydra/hydra.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index e2614ac0..c97f3a48 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -11,7 +11,7 @@ function appendCanvas(c) { return testCanvas; } -export async function initHydra(options = {}) { +export async function initHydra(options = {detectAudio: false}) { //load and init hydra if (!document.getElementById('hydra-canvas')) { const { src = 'https://unpkg.com/hydra-synth', ...opts } = options; From f7a283f87dd4597fdbaf527acf828f93cfa58887 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 24 Nov 2023 12:49:05 +0100 Subject: [PATCH 11/12] add feedStrudel option + smarter reinit logic --- packages/hydra/hydra.mjs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/hydra/hydra.mjs b/packages/hydra/hydra.mjs index c97f3a48..97ca5ac4 100644 --- a/packages/hydra/hydra.mjs +++ b/packages/hydra/hydra.mjs @@ -1,6 +1,6 @@ import { getDrawContext } from '@strudel.cycles/core'; -let hydra; +let latestOptions; function appendCanvas(c) { const { canvas: testCanvas } = getDrawContext(); @@ -11,20 +11,28 @@ function appendCanvas(c) { return testCanvas; } -export async function initHydra(options = {detectAudio: false}) { +export async function initHydra(options = {}) { + // reset if options have changed since last init + if (latestOptions && JSON.stringify(latestOptions) !== JSON.stringify(options)) { + document.getElementById('hydra-canvas').remove(); + } + latestOptions = options; //load and init hydra if (!document.getElementById('hydra-canvas')) { - const { src = 'https://unpkg.com/hydra-synth', ...opts } = options; + console.log('reinit..'); + const { + src = 'https://unpkg.com/hydra-synth', + feedStrudel = false, + ...hydraConfig + } = { detectAudio: false, ...options }; await import(src); - hydra = new Hydra(opts); + const hydra = new Hydra(hydraConfig); + if (feedStrudel) { + const { canvas } = getDrawContext(); + canvas.style.display = 'none'; + hydra.synth.s0.init({ src: canvas }); + } appendCanvas(hydra); - // hydra.synth.s0.init({ src: testCanvas }); // is this needed? - } else if (options?.detectAudio && !hydra?.detectAudio) { - // if options.detectAudio is true - // and current canvas des not detect audio - //remove previous canvas without audio detection - document.getElementById('hydra-canvas').remove(); - return initHydra(options); } } From 407510e265a28a479b45af47efd42622c05ee393 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sat, 25 Nov 2023 15:20:19 +0100 Subject: [PATCH 12/12] document feedStrudel --- packages/hydra/README.md | 9 ++++----- website/src/pages/learn/hydra.mdx | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/packages/hydra/README.md b/packages/hydra/README.md index e36a421b..0b238692 100644 --- a/packages/hydra/README.md +++ b/packages/hydra/README.md @@ -12,12 +12,11 @@ await initHydra(); Then you can use hydra below! -### Enable audio capture -Use `{audio: true}` param to enable Hydra's audio capture: +### options -```js -await initHydra({audio: true}); -``` +You can also pass options to the `initHydra` function. These can be used to set [hydra options](https://github.com/hydra-synth/hydra-synth#api) + these strudel specific options: + +- `feedStrudel`: sends the strudel canvas to `s0`. The strudel canvas is used to draw `pianoroll`, `spiral`, `scope` etc.. ## Usage via npm diff --git a/website/src/pages/learn/hydra.mdx b/website/src/pages/learn/hydra.mdx index d5219e6f..f1ace48b 100644 --- a/website/src/pages/learn/hydra.mdx +++ b/website/src/pages/learn/hydra.mdx @@ -41,6 +41,8 @@ note("[a,c,e,,b4]/4").s("sawtooth").vib(2) `} /> +## H patterns + There is a special function `H` that allows you to use a pattern as an input to hydra: +## detectAudio + To use hydra audio capture, call `initHydra` with `{detectAudio:true}` configuration param: You might now be able to see this properly here: [open in REPL](/#YXdhaXQgaW5pdEh5ZHJhKCkKbGV0IHBhdHRlcm4gPSAiMyA0IDUgWzYgN10qMiIKc2hhcGUoSChwYXR0ZXJuKSkub3V0KG8wKQpuKHBhdHRlcm4pLnNjYWxlKCJBOm1pbm9yIikucGlhbm8oKS5yb29tKDEpIA%3D%3D) + +Similar to `detectAudio`, all the [available hydra options](https://github.com/hydra-synth/hydra-synth#api) can be passed to `initHydra`. + +## feedStrudel + +Using the `feedStrudel` option, you can transform strudel visualizations with hydra: + +")) + .diff(osc(1,0.5,5)) + .modulateScale(osc(2,-0.25,1)) + .out() +// +stack( + s("bd*2,[hh:0:<.5 1>]*4,~ rim").bank("RolandTR909").speed(.9), + note("[>>]*3").s("sawtooth") + .room(.75).sometimes(add(note(12))).clip(.3) + .lpa(.05).lpenv(-4).lpf(2000).lpq(8).ftype('24db') +).fft(4) + .scope({pos:0,smear:.95})`} +/>