From 7286b2cf7796eb65c6f95da480c310ab122b1929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Tue, 24 Dec 2024 22:51:08 +0100 Subject: [PATCH 01/12] Add strudelFft to hydras function scope. It will hook into strudels analyze engine and expose that data to the hydra scope. Caveats from this is, that only patterns with a '.scope()' (or similar) call will be included into the resulting fft data --- packages/web/src/lib/hydra-wrapper.ts | 24 ++++++++++++++++++++++++ packages/web/src/lib/strudel-wrapper.ts | 6 +++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/web/src/lib/hydra-wrapper.ts b/packages/web/src/lib/hydra-wrapper.ts index 1ce2f6b6..f3f007aa 100644 --- a/packages/web/src/lib/hydra-wrapper.ts +++ b/packages/web/src/lib/hydra-wrapper.ts @@ -7,6 +7,7 @@ declare global { src: Function; H: Function; P5: Function; + strudelFft: (index: number, buckets: number) => number; } } @@ -64,6 +65,29 @@ export class HydraWrapper { window.H = this._hydra; + const clamp = (num: number, min: number, max: number) => Math.min(Math.max(num, min), max); + + + // Enables Hydra to use Strudel frequency data + // with `.scrollX(() => strudelFft(1,0)` it will influence the x-axis, according to the fft data + // first number is the index of the bucket, second is the number of buckets to aggregate the number too + window.strudelFft = (index: number, buckets: number = 8) => { + const freq = window.strudel.webaudio.getAnalyzerData("frequency") as Array + const bucketSize = (freq.length) / buckets + + // inspired from https://github.com/tidalcycles/strudel/blob/a7728e3d81fb7a0a2dff9f2f4bd9e313ddf138cd/packages/webaudio/scope.mjs#L53 + const min = -150 + const scale = .25 + const max = 0 + const normalized = freq.map((it: number) => { + const norm = clamp((it - min) / (max - min), 0, 1); + return norm * scale; + }) + + return normalized.slice(bucketSize * index, bucketSize * (index + 1)) + .reduce((a, b) => a + b, 0) / bucketSize + } + this.initialized = true; console.log("Hydra initialized"); } diff --git a/packages/web/src/lib/strudel-wrapper.ts b/packages/web/src/lib/strudel-wrapper.ts index acb4e530..450ef81a 100644 --- a/packages/web/src/lib/strudel-wrapper.ts +++ b/packages/web/src/lib/strudel-wrapper.ts @@ -33,6 +33,7 @@ export class StrudelWrapper { protected _docPatterns: any; protected _audioInitialized: boolean; protected framer?: any; + protected webaudio?: any; constructor({ onError, @@ -49,6 +50,9 @@ export class StrudelWrapper { async importModules() { // import desired modules and add them to the eval scope + + this.webaudio = await import("@strudel/webaudio"); + await evalScope( import("@strudel/core"), import("@strudel/midi"), @@ -57,7 +61,7 @@ export class StrudelWrapper { import("@strudel/osc"), import("@strudel/serial"), import("@strudel/soundfonts"), - import("@strudel/webaudio"), + this.webaudio, controls ); try { From e680c8e40f469a42467dad4b632e61cdbfc60fe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Fri, 27 Dec 2024 12:53:56 +0100 Subject: [PATCH 02/12] Rename strudelFft to fft --- packages/web/src/lib/hydra-wrapper.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/web/src/lib/hydra-wrapper.ts b/packages/web/src/lib/hydra-wrapper.ts index f3f007aa..ae1b6ad1 100644 --- a/packages/web/src/lib/hydra-wrapper.ts +++ b/packages/web/src/lib/hydra-wrapper.ts @@ -7,7 +7,7 @@ declare global { src: Function; H: Function; P5: Function; - strudelFft: (index: number, buckets: number) => number; + fft: (index: number, buckets: number) => number; } } @@ -69,9 +69,9 @@ export class HydraWrapper { // Enables Hydra to use Strudel frequency data - // with `.scrollX(() => strudelFft(1,0)` it will influence the x-axis, according to the fft data + // with `.scrollX(() => fft(1,0)` it will influence the x-axis, according to the fft data // first number is the index of the bucket, second is the number of buckets to aggregate the number too - window.strudelFft = (index: number, buckets: number = 8) => { + window.fft = (index: number, buckets: number = 8) => { const freq = window.strudel.webaudio.getAnalyzerData("frequency") as Array const bucketSize = (freq.length) / buckets From 42e70f13ba170531da88440a8c4bbd3d707edef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Fri, 27 Dec 2024 13:36:21 +0100 Subject: [PATCH 03/12] Expose min, max and scale options for fft --- packages/web/src/lib/hydra-wrapper.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/web/src/lib/hydra-wrapper.ts b/packages/web/src/lib/hydra-wrapper.ts index ae1b6ad1..bc0d11ec 100644 --- a/packages/web/src/lib/hydra-wrapper.ts +++ b/packages/web/src/lib/hydra-wrapper.ts @@ -71,14 +71,14 @@ export class HydraWrapper { // Enables Hydra to use Strudel frequency data // with `.scrollX(() => fft(1,0)` it will influence the x-axis, according to the fft data // first number is the index of the bucket, second is the number of buckets to aggregate the number too - window.fft = (index: number, buckets: number = 8) => { + window.fft = (index: number, buckets: number = 8, options?: { min?: number; max?: number, scale?: number }) => { const freq = window.strudel.webaudio.getAnalyzerData("frequency") as Array const bucketSize = (freq.length) / buckets // inspired from https://github.com/tidalcycles/strudel/blob/a7728e3d81fb7a0a2dff9f2f4bd9e313ddf138cd/packages/webaudio/scope.mjs#L53 - const min = -150 - const scale = .25 - const max = 0 + const min = options?.min ?? -150; + const scale = options?.scale ?? 1 + const max = options?.max ?? 0 const normalized = freq.map((it: number) => { const norm = clamp((it - min) / (max - min), 0, 1); return norm * scale; From b871b44ae1d3c622175edd448713f29f644ffbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Fri, 27 Dec 2024 21:23:29 +0100 Subject: [PATCH 04/12] Expose strudel instance in the parent window, and patch it through to hydra --- packages/web/src/routes/frames/hydra.tsx | 1 + packages/web/src/routes/frames/strudel.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/web/src/routes/frames/hydra.tsx b/packages/web/src/routes/frames/hydra.tsx index e9f3fade..38c20ac3 100644 --- a/packages/web/src/routes/frames/hydra.tsx +++ b/packages/web/src/routes/frames/hydra.tsx @@ -56,6 +56,7 @@ export function Component() { useAnimationFrame( useCallback(() => { window.m = window.parent?.mercury?.m; + window.strudel = window.parent?.strudel?.strudel; }, []) ); diff --git a/packages/web/src/routes/frames/strudel.tsx b/packages/web/src/routes/frames/strudel.tsx index 229b6938..da796a78 100644 --- a/packages/web/src/routes/frames/strudel.tsx +++ b/packages/web/src/routes/frames/strudel.tsx @@ -34,6 +34,8 @@ export function Component() { } }; + window.strudel = instance; + window.addEventListener("message", handleWindowMessage); return () => { From d3de34fdd247a474f075c9620fb4e257ba195f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Fri, 27 Dec 2024 23:01:11 +0100 Subject: [PATCH 05/12] Add analysers to all strudel patterns by default, enabling them all for fft Thanks @felixroos for the idea! --- packages/web/src/lib/hydra-wrapper.ts | 12 +++++++----- packages/web/src/lib/strudel-wrapper.ts | 4 +++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/web/src/lib/hydra-wrapper.ts b/packages/web/src/lib/hydra-wrapper.ts index bc0d11ec..c39c60b3 100644 --- a/packages/web/src/lib/hydra-wrapper.ts +++ b/packages/web/src/lib/hydra-wrapper.ts @@ -71,14 +71,16 @@ export class HydraWrapper { // Enables Hydra to use Strudel frequency data // with `.scrollX(() => fft(1,0)` it will influence the x-axis, according to the fft data // first number is the index of the bucket, second is the number of buckets to aggregate the number too - window.fft = (index: number, buckets: number = 8, options?: { min?: number; max?: number, scale?: number }) => { - const freq = window.strudel.webaudio.getAnalyzerData("frequency") as Array - const bucketSize = (freq.length) / buckets - - // inspired from https://github.com/tidalcycles/strudel/blob/a7728e3d81fb7a0a2dff9f2f4bd9e313ddf138cd/packages/webaudio/scope.mjs#L53 + window.fft = (index: number, buckets: number = 8, options?: { min?: number; max?: number, scale?: number, analyserId?: string }) => { + const analyserId = options?.analyserId ?? "flok-master" const min = options?.min ?? -150; const scale = options?.scale ?? 1 const max = options?.max ?? 0 + + const freq = window.strudel.webaudio.getAnalyzerData("frequency", analyserId) as Array; + const bucketSize = (freq.length) / buckets + + // inspired from https://github.com/tidalcycles/strudel/blob/a7728e3d81fb7a0a2dff9f2f4bd9e313ddf138cd/packages/webaudio/scope.mjs#L53 const normalized = freq.map((it: number) => { const norm = clamp((it - min) / (max - min), 0, 1); return norm * scale; diff --git a/packages/web/src/lib/strudel-wrapper.ts b/packages/web/src/lib/strudel-wrapper.ts index 450ef81a..432ecc26 100644 --- a/packages/web/src/lib/strudel-wrapper.ts +++ b/packages/web/src/lib/strudel-wrapper.ts @@ -154,7 +154,9 @@ export class StrudelWrapper { try { const { body: code, docId } = msg; // little hack that injects the docId at the end of the code to make it available in afterEval - const pattern = await this._repl.evaluate(`${code}//${docId}`); + // also add ann analyser node to all patterns, for fft data in hydra + const pattern = await this._repl.evaluate(`${code}\nall(x => x.analyze("flok-master"))//${docId}`); + if (pattern) { this._docPatterns[docId] = pattern.docId(docId); // docId is needed for highlighting const allPatterns = stack(...Object.values(this._docPatterns)); From 99a9be6a1bf985a129d3c54b6327d39d3abbbdb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Sat, 28 Dec 2024 11:40:48 +0100 Subject: [PATCH 06/12] Fix overwrite of analyer not possible --- packages/web/src/lib/hydra-wrapper.ts | 9 ++++++--- packages/web/src/lib/strudel-wrapper.ts | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/web/src/lib/hydra-wrapper.ts b/packages/web/src/lib/hydra-wrapper.ts index c39c60b3..f3b531fe 100644 --- a/packages/web/src/lib/hydra-wrapper.ts +++ b/packages/web/src/lib/hydra-wrapper.ts @@ -71,13 +71,16 @@ export class HydraWrapper { // Enables Hydra to use Strudel frequency data // with `.scrollX(() => fft(1,0)` it will influence the x-axis, according to the fft data // first number is the index of the bucket, second is the number of buckets to aggregate the number too - window.fft = (index: number, buckets: number = 8, options?: { min?: number; max?: number, scale?: number, analyserId?: string }) => { - const analyserId = options?.analyserId ?? "flok-master" + window.fft = (index: number, buckets: number = 8, options?: { min?: number; max?: number, scale?: number, analyzerId?: string }) => { + const analyzerId = options?.analyzerId ?? "flok-master" const min = options?.min ?? -150; const scale = options?.scale ?? 1 const max = options?.max ?? 0 - const freq = window.strudel.webaudio.getAnalyzerData("frequency", analyserId) as Array; + if(window.strudel.webaudio.analysers[analyzerId] == undefined) { + return .5 + } + const freq = window.strudel.webaudio.getAnalyzerData("frequency", analyzerId) as Array; const bucketSize = (freq.length) / buckets // inspired from https://github.com/tidalcycles/strudel/blob/a7728e3d81fb7a0a2dff9f2f4bd9e313ddf138cd/packages/webaudio/scope.mjs#L53 diff --git a/packages/web/src/lib/strudel-wrapper.ts b/packages/web/src/lib/strudel-wrapper.ts index 432ecc26..62508bbd 100644 --- a/packages/web/src/lib/strudel-wrapper.ts +++ b/packages/web/src/lib/strudel-wrapper.ts @@ -149,14 +149,25 @@ export class StrudelWrapper { } } + hapAnalyzeSnippet = ` + all(x => + x.fmap(hap => { + if(hap.analyze == undefined) { + // all strings get converted to mini patterns, but we do just need the raw string. + hap.analyze = "flok-master".__pure; + } + return hap + }) + ) + `; + async tryEval(msg: EvalMessage) { if (!this.initialized) await this.initialize(); try { const { body: code, docId } = msg; // little hack that injects the docId at the end of the code to make it available in afterEval // also add ann analyser node to all patterns, for fft data in hydra - const pattern = await this._repl.evaluate(`${code}\nall(x => x.analyze("flok-master"))//${docId}`); - + const pattern = await this._repl.evaluate(`${code}\n${this.hapAnalyzeSnippet}\n//${docId}`); if (pattern) { this._docPatterns[docId] = pattern.docId(docId); // docId is needed for highlighting const allPatterns = stack(...Object.values(this._docPatterns)); From 2d4a062f348b7909b9e2f114240dfa8c9532c32f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Sat, 28 Dec 2024 12:59:40 +0100 Subject: [PATCH 07/12] Add display settings to disable or enable fft --- .../components/display-settings-dialog.tsx | 20 +++++++++++++++++++ packages/web/src/lib/display-settings.ts | 3 +++ packages/web/src/lib/hydra-wrapper.ts | 20 +++++++++++++++++++ packages/web/src/lib/strudel-wrapper.ts | 15 ++------------ packages/web/src/routes/frames/hydra.tsx | 5 +++++ 5 files changed, 50 insertions(+), 13 deletions(-) diff --git a/packages/web/src/components/display-settings-dialog.tsx b/packages/web/src/components/display-settings-dialog.tsx index dcf35ad1..894a7cc5 100644 --- a/packages/web/src/components/display-settings-dialog.tsx +++ b/packages/web/src/components/display-settings-dialog.tsx @@ -77,6 +77,26 @@ export default function DisplaySettingsDialog({ } /> +
+
+ + + sanitizeAndSetUnsavedSettings({ + ...unsavedSettings, + enableFft: e.target.checked, + }) + } + /> +
+

You need to reload the page to apply changes to fft

+
diff --git a/packages/web/src/lib/display-settings.ts b/packages/web/src/lib/display-settings.ts index eff98651..071934c9 100644 --- a/packages/web/src/lib/display-settings.ts +++ b/packages/web/src/lib/display-settings.ts @@ -1,11 +1,13 @@ export interface DisplaySettings { canvasPixelSize: number; showCanvas: boolean; + enableFft: boolean; } export const defaultDisplaySettings: DisplaySettings = { canvasPixelSize: 1, showCanvas: true, + enableFft: true, } export function sanitizeDisplaySettings(settings: DisplaySettings): DisplaySettings { @@ -16,6 +18,7 @@ export function sanitizeDisplaySettings(settings: DisplaySettings): DisplaySetti // canvas; should be low enough const maxPixelSize = 50; + return { ...settings, canvasPixelSize: Math.max( diff --git a/packages/web/src/lib/hydra-wrapper.ts b/packages/web/src/lib/hydra-wrapper.ts index f3b531fe..d15ad3b2 100644 --- a/packages/web/src/lib/hydra-wrapper.ts +++ b/packages/web/src/lib/hydra-wrapper.ts @@ -1,5 +1,6 @@ import Hydra from "hydra-synth"; import { isWebglSupported } from "@/lib/webgl-detector.js"; +import {DisplaySettings} from "@/lib/display-settings.ts"; declare global { interface Window { @@ -20,19 +21,27 @@ export class HydraWrapper { protected _hydra: any; protected _onError: ErrorHandler; protected _onWarning: ErrorHandler; + protected _displaySettings: DisplaySettings; constructor({ canvas, onError, onWarning, + displaySettings, }: { canvas: HTMLCanvasElement; onError?: ErrorHandler; onWarning?: ErrorHandler; + displaySettings: DisplaySettings; }) { this._canvas = canvas; this._onError = onError || (() => {}); this._onWarning = onWarning || (() => {}); + this._displaySettings = displaySettings; + } + + setDisplaySettings(displaySettings: DisplaySettings) { + this._displaySettings = displaySettings; } async initialize() { @@ -77,9 +86,20 @@ export class HydraWrapper { const scale = options?.scale ?? 1 const max = options?.max ?? 0 + // Strudel is not initialized yet, so we just return a default value + if(window.strudel == undefined) return .5; + + // If display settings are not enabled, we just return a default value + if(!this._displaySettings.enableFft) return .5; + + // Enable auto-analyze + window.strudel.enableAutoAnalyze = true; + + // If the analyzerId is not defined, we just return a default value if(window.strudel.webaudio.analysers[analyzerId] == undefined) { return .5 } + const freq = window.strudel.webaudio.getAnalyzerData("frequency", analyzerId) as Array; const bucketSize = (freq.length) / buckets diff --git a/packages/web/src/lib/strudel-wrapper.ts b/packages/web/src/lib/strudel-wrapper.ts index 62508bbd..e099559d 100644 --- a/packages/web/src/lib/strudel-wrapper.ts +++ b/packages/web/src/lib/strudel-wrapper.ts @@ -149,25 +149,14 @@ export class StrudelWrapper { } } - hapAnalyzeSnippet = ` - all(x => - x.fmap(hap => { - if(hap.analyze == undefined) { - // all strings get converted to mini patterns, but we do just need the raw string. - hap.analyze = "flok-master".__pure; - } - return hap - }) - ) - `; async tryEval(msg: EvalMessage) { if (!this.initialized) await this.initialize(); try { - const { body: code, docId } = msg; + const {body: code, docId} = msg; // little hack that injects the docId at the end of the code to make it available in afterEval // also add ann analyser node to all patterns, for fft data in hydra - const pattern = await this._repl.evaluate(`${code}\n${this.hapAnalyzeSnippet}\n//${docId}`); + const pattern = await this._repl.evaluate(`${code}\n${this.enableAutoAnalyze ? this.hapAnalyzeSnippet : ""}\n//${docId}`); if (pattern) { this._docPatterns[docId] = pattern.docId(docId); // docId is needed for highlighting const allPatterns = stack(...Object.values(this._docPatterns)); diff --git a/packages/web/src/routes/frames/hydra.tsx b/packages/web/src/routes/frames/hydra.tsx index 38c20ac3..273168f6 100644 --- a/packages/web/src/routes/frames/hydra.tsx +++ b/packages/web/src/routes/frames/hydra.tsx @@ -43,6 +43,7 @@ export function Component() { onWarning: (msg) => { sendToast("warning", "Hydra warning", msg); }, + displaySettings: displaySettings, }); await hydra.initialize(); @@ -60,6 +61,10 @@ export function Component() { }, []) ); + useEffect(() => { + instance?.setDisplaySettings(displaySettings); + }, [displaySettings]); + useEvalHandler( useCallback( (msg) => { From c5249f7ffa85bd06c01febc6f842582205b2889b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Sat, 28 Dec 2024 13:03:20 +0100 Subject: [PATCH 08/12] Default to true for fft setting --- packages/web/src/lib/hydra-wrapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/lib/hydra-wrapper.ts b/packages/web/src/lib/hydra-wrapper.ts index d15ad3b2..6fcfaf41 100644 --- a/packages/web/src/lib/hydra-wrapper.ts +++ b/packages/web/src/lib/hydra-wrapper.ts @@ -90,7 +90,7 @@ export class HydraWrapper { if(window.strudel == undefined) return .5; // If display settings are not enabled, we just return a default value - if(!this._displaySettings.enableFft) return .5; + if(!(this._displaySettings.enableFft ?? true)) return .5; // Enable auto-analyze window.strudel.enableAutoAnalyze = true; From 0466e5f9563ad666c2447d20f71f268215f0bd95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Sat, 28 Dec 2024 13:04:59 +0100 Subject: [PATCH 09/12] Add missing properties of strudel wrapper --- packages/web/src/lib/strudel-wrapper.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/web/src/lib/strudel-wrapper.ts b/packages/web/src/lib/strudel-wrapper.ts index e099559d..0f6bea27 100644 --- a/packages/web/src/lib/strudel-wrapper.ts +++ b/packages/web/src/lib/strudel-wrapper.ts @@ -35,6 +35,18 @@ export class StrudelWrapper { protected framer?: any; protected webaudio?: any; + enableAutoAnalyze = false; + hapAnalyzeSnippet = ` + all(x => + x.fmap(hap => { + if(hap.analyze == undefined) { + hap.analyze = 'flok-master'; + } + return hap + }) + ) + `; + constructor({ onError, onWarning, From 99bce8d03e7639a9ab209ede57d3915008787e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Silvani?= Date: Mon, 30 Dec 2024 20:51:17 -0300 Subject: [PATCH 10/12] docs: Add docs about `fft()` for hydra --- README.md | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 76d781d7..8a321ed0 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ run Flok in secure mode by passing the `--secure` parameter: ```sh npx flok-web@latest --secure -``` +``` #### Note about remote users (not LAN) @@ -159,7 +159,7 @@ object, like this: #### Sardine -Use `flok-repl` with the `-t sardine` parameter. In order to make it work, +Use `flok-repl` with the `-t sardine` parameter. In order to make it work, the `sardine` REPL must be included to your PATH. It should already be the case if you followed a regular install. @@ -217,14 +217,51 @@ installing and using it. #### Hydra -[Hydra](https://hydra.ojack.xyz/) is a video synth and coding environment, inspired in -analog video synthesis, that runs directly in the browser and is already included in +[Hydra](https://hydra.ojack.xyz/) is a video synth and coding environment, inspired in +analog video synthesis, that runs directly in the browser and is already included in the web App. You don't need to install anything as it runs on the browser. Just use the `hydra` target to execute Hydra code. -You can also use [p5.js](https://p5js.org/) within a `hydra` target, like you would in +You can also use [p5.js](https://p5js.org/) within a `hydra` target, like you would in the official Hydra editor. +##### `fft()` function + +The `fft()` function is a special function that allows you to get the FFT data +from web targets. Note: Only Strudel is supported at the moment. + +```ts +fft(index: number, + buckets: number = 8, + options?: { min?: number; max?: number, scale?: number, analyzerId?: string }): number +``` + +Parameters: +- `index: number` : The index of the bucket to return the value from. +- `buckets: number`: The number of buckets to combine the underlying FFT data + too. Defaults to 8. +- `options?: { min?: number; max?: number, scale?: number }`: + - `min?: number`: Minimum clamp value of the underlying data. Defaults to + -150. + - `max?: number`: Maximum clamp value of the underlying data. Defaults to 0. + - `scale?: number`: Scale of the output. Defaults to 1 (so the output is + from 0 to 1) + - `analyzerId?: string`: Which Strudel analyser to listen to. Defaults to + `flok-master`, which is also automatically added to all strudel patterns. + Can be used to route different patterns to different parts of the hydra + visualiser + +Example: +```js + solid(() => fft(0,1), 0) + .mask(shape(5,.05)) + .rotate(() => 50 * fft(0, 40)) // we need to supply a function for the parameter, for it to update automaticaly +``` + +**Caveat**: Because of how we setup the analyze node on Strudel, every Strudel pane +needs a re-eval after the Hydra code decides that we need to get the fft data. +This does not happen automatically, manual re-eval is necessary. + #### Mercury [Mercury](https://github.com/tmhglnd/mercury) is a minimal and human readable From c8054a33bf688bbebb5286d4117d06609762047a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Silvani?= Date: Mon, 30 Dec 2024 20:56:46 -0300 Subject: [PATCH 11/12] docs: Update --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8a321ed0..8f1b043f 100644 --- a/README.md +++ b/README.md @@ -228,7 +228,9 @@ the official Hydra editor. ##### `fft()` function The `fft()` function is a special function that allows you to get the FFT data -from web targets. Note: Only Strudel is supported at the moment. +from web targets. + +**Note: Only Strudel is supported at the moment.** ```ts fft(index: number, @@ -253,9 +255,10 @@ Parameters: Example: ```js - solid(() => fft(0,1), 0) +solid(() => fft(0,1), 0) .mask(shape(5,.05)) - .rotate(() => 50 * fft(0, 40)) // we need to supply a function for the parameter, for it to update automaticaly + .rotate(() => 50 * fft(0, 40)) // we need to supply a function + // for the parameter, for it to update automaticaly. ``` **Caveat**: Because of how we setup the analyze node on Strudel, every Strudel pane From 763a0cac41cdc90a530bcfaee9141f40afc487ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20G=C3=BCdelh=C3=B6fer?= Date: Wed, 1 Jan 2025 12:56:49 +0100 Subject: [PATCH 12/12] Add Sentence about performance to FFT section in readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8f1b043f..34694bf5 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,8 @@ from web targets. **Note: Only Strudel is supported at the moment.** +**You can disable the FFT visualizer in the display settings. This might help with performance.** + ```ts fft(index: number, buckets: number = 8,