From 5dbbc7b9e164215347abe58aae8da3383da36af2 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 18 Aug 2026 13:19:47 +0200 Subject: [PATCH 1/5] basic dough integration with onTrigger --- packages/dough/dough.mjs | 75 +++++++++++++++++++++++++++++++++++++ packages/dough/package.json | 42 +++++++++++++++++++++ pnpm-lock.yaml | 38 ++++++++++++++++++- website/astro.config.mjs | 9 +++++ website/package.json | 1 + website/src/repl/util.mjs | 1 + 6 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 packages/dough/dough.mjs create mode 100644 packages/dough/package.json diff --git a/packages/dough/dough.mjs b/packages/dough/dough.mjs new file mode 100644 index 000000000..02d657d6f --- /dev/null +++ b/packages/dough/dough.mjs @@ -0,0 +1,75 @@ +/* +dough.mjs +Copyright (C) 2022 Strudel contributors - see +This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . +*/ + +import { register, noteToMidi } from '@strudel/core'; +import { Dough, doughsamples } from 'dough-synth'; +import { getAudioContext } from '@strudel/webaudio'; +import wasm from 'dough-synth/dough.wasm?url'; +import workletCode from 'dough-synth/dough.js?raw'; + +Object.assign(globalThis, { doughsamples }); + +let D; +/** + * + * initializes dough ahead of time. you don't need to use this, but if you do, you can await it, so dough is ready before the pattern starts. + * + * @name initDough + * @tags external_io + * @memberof Pattern + * @example + * await initDough() + * $: chord("").offset("<-1 0 1 0>").voicing() + * .phaser(3).fm(1.4).fmh(1.01) + * .dough() + */ +export function initDough() { + if (!D || D.audioContext !== getAudioContext()) { + D = new Dough({ + wasm, + workletCode, + audioContext: getAudioContext(), + }); + } + return D.ready; +} + +export async function doughTrigger(hap, _currentTime, cps = 1, targetTime) { + const offset = D.context_offset?.[0]; + if (!offset) { + return; // not ready + } + hap.ensureObjectValue(); + const event = { + dough: 'play', + ...hap.value, + time: targetTime - offset, + duration: hap.duration / cps, + }; + if (typeof event.note === 'string') { + event.note = noteToMidi(event.note); + } + D.evaluate(event); +} + +/** + * + * Uses dough as the audio engine. more info at https://dough.strudel.cc + * + * @name dough + * @tags external_io + * @memberof Pattern + * @returns Pattern + * @example + * $: chord("").offset("<-1 0 1 0>").voicing() + * .phaser(3).fm(1.4).fmh(1.01) + * .dough() + */ +export const dough = register('dough', (pat) => { + initDough(); + ensureMinimalOutput(); + return pat.onTrigger(doughTrigger); +}); diff --git a/packages/dough/package.json b/packages/dough/package.json new file mode 100644 index 000000000..abbb543be --- /dev/null +++ b/packages/dough/package.json @@ -0,0 +1,42 @@ +{ + "name": "@strudel/dough", + "version": "1.3.2", + "description": "dough synth integration for strudel", + "main": "dough.mjs", + "type": "module", + "publishConfig": { + "main": "dist/index.mjs" + }, + "scripts": { + "build": "vite build", + "prepublishOnly": "npm run build" + }, + "repository": { + "type": "git", + "url": "git+https://codeberg.org/uzu/strudel.git" + }, + "keywords": [ + "tidalcycles", + "strudel", + "pattern", + "livecoding", + "algorave" + ], + "author": "Felix Roos ", + "license": "AGPL-3.0-or-later", + "bugs": { + "url": "https://codeberg.org/uzu/strudel/issues" + }, + "homepage": "https://codeberg.org/uzu/strudel#readme", + "dependencies": { + "@strudel/core": "workspace:*", + "@strudel/webaudio": "workspace:*", + "dough-synth": "0.2.4" + }, + "devDependencies": { + "vite": "^6.0.11" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b086a3d0..f7911b435 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -303,6 +303,22 @@ importers: specifier: ^2.2.0 version: 2.2.0 + packages/dough: + dependencies: + '@strudel/core': + specifier: workspace:* + version: link:../core + '@strudel/webaudio': + specifier: workspace:* + version: link:../webaudio + dough-synth: + specifier: 0.2.4 + version: 0.2.4 + devDependencies: + vite: + specifier: ^6.0.11 + version: 6.0.11(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0) + packages/draw: dependencies: '@strudel/core': @@ -808,6 +824,9 @@ importers: '@strudel/desktopbridge': specifier: workspace:* version: link:../packages/desktopbridge + '@strudel/dough': + specifier: workspace:* + version: link:../packages/dough '@strudel/draw': specifier: workspace:* version: link:../packages/draw @@ -2066,6 +2085,7 @@ packages: '@lerna/create@8.1.9': resolution: {integrity: sha512-DPnl5lPX4v49eVxEbJnAizrpMdMTBz1qykZrAbBul9rfgk531v8oAt+Pm6O/rpAleRombNM7FJb5rYGzBJatOQ==} engines: {node: '>=18.0.0'} + deprecated: This package is an implementation detail of Lerna and is no longer published separately. '@lezer/common@1.2.3': resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} @@ -3065,6 +3085,7 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher '@vite-pwa/astro@0.5.0': resolution: {integrity: sha512-Yd3Pug/c1EUQJXWvzYh6eTtoqzmSKcdCqWCcNquZeaD13tLWpBb2FIPJ4HMULVY6+GfxMvrT+OBuMrbHQCvftw==} @@ -3716,6 +3737,7 @@ packages: conventional-changelog-core@5.0.1: resolution: {integrity: sha512-Rvi5pH+LvgsqGwZPZ3Cq/tz4ty7mjijhr3qR4m9IBXNbxGGYgTVVO+duXzz9aArmHxFtwZ+LRkrNIMDQzgoY4A==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Please use conventional-changelog instead. conventional-changelog-preset-loader@3.0.0: resolution: {integrity: sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==} @@ -4047,6 +4069,10 @@ packages: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} + dough-synth@0.2.4: + resolution: {integrity: sha512-qMnMKVj1B2ivUgobNCwqJqNzZHOMN+5339OmCOk07zIDEK7iCYdufa+ZDE2BEgmKrWDyhGS7oTNFjHtTwzEv9w==} + hasBin: true + dset@3.1.4: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} engines: {node: '>=4'} @@ -4579,6 +4605,7 @@ packages: git-raw-commits@3.0.0: resolution: {integrity: sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead. hasBin: true git-remote-origin-url@2.0.0: @@ -4588,6 +4615,7 @@ packages: git-semver-tags@5.0.1: resolution: {integrity: sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==} engines: {node: '>=14'} + deprecated: Deprecated and no longer maintained. Use @conventional-changelog/git-client instead. hasBin: true git-up@7.0.0: @@ -4615,15 +4643,17 @@ packages: glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me glob@9.3.5: resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} engines: {node: '>=16 || 14 >=14.17'} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me globalize@0.1.1: resolution: {integrity: sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==} @@ -6406,6 +6436,7 @@ packages: prebuild-install@7.1.1: resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} engines: {node: '>=10'} + deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. hasBin: true precinct@12.1.2: @@ -7230,6 +7261,7 @@ packages: tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me temp-dir@1.0.0: resolution: {integrity: sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==} @@ -7357,6 +7389,7 @@ packages: tsconfck@3.1.4: resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==} engines: {node: ^18 || >=20} + deprecated: unmaintained hasBin: true peerDependencies: typescript: ^5.0.0 @@ -7636,6 +7669,7 @@ packages: uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true validate-npm-package-license@3.0.4: @@ -11757,6 +11791,8 @@ snapshots: dotenv@16.4.7: {} + dough-synth@0.2.4: {} + dset@3.1.4: {} dunder-proto@1.0.1: diff --git a/website/astro.config.mjs b/website/astro.config.mjs index e62f13c7f..de08502dd 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -145,4 +145,13 @@ export default defineConfig({ // external: ['fraction.js'], // https://github.com/infusion/Fraction.js/issues/51 }, }, + server: { + // these are needed for dough, which uses shared memory + // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements + // this is only for the dev server, so the server strudel runs on, also needs those + headers: { + 'Cross-Origin-Opener-Policy': 'same-origin', + 'Cross-Origin-Embedder-Policy': 'credentialless', + }, + }, }); diff --git a/website/package.json b/website/package.json index 7258f150e..3bc8b7bce 100644 --- a/website/package.json +++ b/website/package.json @@ -41,6 +41,7 @@ "@strudel/motion": "workspace:*", "@strudel/mqtt": "workspace:*", "@strudel/osc": "workspace:*", + "@strudel/dough": "workspace:*", "@strudel/serial": "workspace:*", "@strudel/soundfonts": "workspace:*", "@strudel/tidal": "workspace:*", diff --git a/website/src/repl/util.mjs b/website/src/repl/util.mjs index c141257f9..bd1a85f24 100644 --- a/website/src/repl/util.mjs +++ b/website/src/repl/util.mjs @@ -85,6 +85,7 @@ export function loadModules() { import('@strudel/motion'), import('@strudel/mqtt'), import('@strudel/mondo'), + import('@strudel/dough'), ]; if (isTauri()) { modules = modules.concat([ From d6f0b863f06ee3840a99b7f57f938eae8c59c69c Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 18 Aug 2026 20:26:29 +0200 Subject: [PATCH 2/5] avoid "doughsamples" name collision with old supradough --- packages/webaudio/supradough.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webaudio/supradough.mjs b/packages/webaudio/supradough.mjs index f97251a07..042a002c5 100644 --- a/packages/webaudio/supradough.mjs +++ b/packages/webaudio/supradough.mjs @@ -114,7 +114,7 @@ async function fetchSample(url) { return { channels, sampleRate: buffer.sampleRate }; } -export async function doughsamples(sampleMap, baseUrl) { +export async function supradoughsamples(sampleMap, baseUrl) { if (typeof sampleMap === 'string') { const [json, base] = await fetchSampleMap(sampleMap); // console.log('json', json, 'base', base); From f1dd2097494d0cb519c6e384c92fca0a76f6ff8d Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 18 Aug 2026 20:29:23 +0200 Subject: [PATCH 3/5] fix ci check errors --- packages/dough/dough.mjs | 2 +- packages/webaudio/supradough.mjs | 2 +- test/__snapshots__/examples.test.mjs.snap | 48 +++++++++++++++++++++++ test/runtime.mjs | 1 + 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/packages/dough/dough.mjs b/packages/dough/dough.mjs index 02d657d6f..908138bae 100644 --- a/packages/dough/dough.mjs +++ b/packages/dough/dough.mjs @@ -6,7 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th import { register, noteToMidi } from '@strudel/core'; import { Dough, doughsamples } from 'dough-synth'; -import { getAudioContext } from '@strudel/webaudio'; +import { getAudioContext, ensureMinimalOutput } from '@strudel/webaudio'; import wasm from 'dough-synth/dough.wasm?url'; import workletCode from 'dough-synth/dough.js?raw'; diff --git a/packages/webaudio/supradough.mjs b/packages/webaudio/supradough.mjs index 042a002c5..d55957ced 100644 --- a/packages/webaudio/supradough.mjs +++ b/packages/webaudio/supradough.mjs @@ -118,7 +118,7 @@ export async function supradoughsamples(sampleMap, baseUrl) { if (typeof sampleMap === 'string') { const [json, base] = await fetchSampleMap(sampleMap); // console.log('json', json, 'base', base); - return doughsamples(json, base); + return supradoughsamples(json, base); } Object.entries(sampleMap).map(async ([key, urls]) => { if (key !== '_base') { diff --git a/test/__snapshots__/examples.test.mjs.snap b/test/__snapshots__/examples.test.mjs.snap index 539843f49..ccb91377f 100644 --- a/test/__snapshots__/examples.test.mjs.snap +++ b/test/__snapshots__/examples.test.mjs.snap @@ -3422,6 +3422,30 @@ exports[`runs examples > example "djf" example index 0 1`] = ` ] `; +exports[`runs examples > example "dough" example index 0 1`] = ` +[ + "[ 0/1 → 1/1 | note:F3 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 0/1 → 1/1 | note:C4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 0/1 → 1/1 | note:D4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 0/1 → 1/1 | note:E4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 0/1 → 1/1 | note:A4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 1/1 → 2/1 | note:A3 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 1/1 → 2/1 | note:D4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 1/1 → 2/1 | note:G4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 1/1 → 2/1 | note:C5 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:A4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:C5 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:D5 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:F5 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:C6 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:A3 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:D4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:E4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:F4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:C5 phaserrate:3 fmi:1.4 fmh:1.01 ]", +] +`; + exports[`runs examples > example "drawLine" example index 0 1`] = `[]`; exports[`runs examples > example "drive" example index 0 1`] = ` @@ -5930,6 +5954,30 @@ exports[`runs examples > example "inhabit" example index 1 1`] = ` ] `; +exports[`runs examples > example "initDough" example index 0 1`] = ` +[ + "[ 0/1 → 1/1 | note:F3 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 0/1 → 1/1 | note:C4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 0/1 → 1/1 | note:D4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 0/1 → 1/1 | note:E4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 0/1 → 1/1 | note:A4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 1/1 → 2/1 | note:A3 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 1/1 → 2/1 | note:D4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 1/1 → 2/1 | note:G4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 1/1 → 2/1 | note:C5 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:A4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:C5 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:D5 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:F5 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 2/1 → 3/1 | note:C6 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:A3 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:D4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:E4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:F4 phaserrate:3 fmi:1.4 fmh:1.01 ]", + "[ 3/1 → 4/1 | note:C5 phaserrate:3 fmi:1.4 fmh:1.01 ]", +] +`; + exports[`runs examples > example "inside" example index 0 1`] = ` [ "[ 0/1 → 1/8 | note:D3 ]", diff --git a/test/runtime.mjs b/test/runtime.mjs index e06f91620..521fb6474 100644 --- a/test/runtime.mjs +++ b/test/runtime.mjs @@ -174,6 +174,7 @@ evalScope( getDuration, setcps: id, setcpm: id, + initDough: id, Clock: {}, // whatever }, ); From d65b24db8f09ed15ddc354dcf50a643333e7b9f6 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Tue, 18 Aug 2026 20:44:35 +0200 Subject: [PATCH 4/5] rename old dough function to rawdsp + mock dough in test runtime --- packages/superdough/dspworklet.mjs | 4 ++-- packages/webaudio/webaudio.mjs | 6 +++--- test/runtime.mjs | 1 + undocumented.json | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/superdough/dspworklet.mjs b/packages/superdough/dspworklet.mjs index aac08061e..ed6d0c7b3 100644 --- a/packages/superdough/dspworklet.mjs +++ b/packages/superdough/dspworklet.mjs @@ -67,13 +67,13 @@ if (typeof window !== 'undefined') { }); } -export const dough = async (code) => { +export const rawdsp = async (code) => { const ac = getAudioContext(); stop(); worklet = await dspWorklet(ac, code); worklet.node.connect(ac.destination); }; -export function doughTrigger(hap, currentTime, cps, targetTime) { +export function rawdspTrigger(hap, currentTime, cps, targetTime) { window.postMessage({ time: targetTime, dough: hap.value, currentTime, duration: hap.duration, cps }); } diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs index 54ee9bcb3..4f7256fe7 100644 --- a/packages/webaudio/webaudio.mjs +++ b/packages/webaudio/webaudio.mjs @@ -9,7 +9,7 @@ import { superdough, getAudioContext, setLogger, - doughTrigger, + rawdspTrigger, registerWorklet, setAudioContext, initAudio, @@ -173,8 +173,8 @@ export function webaudioRepl(options = {}) { return repl(options); } -Pattern.prototype.dough = function () { - return this.onTrigger(doughTrigger, 1); +Pattern.prototype.rawdsp = function () { + return this.onTrigger(rawdspTrigger, 1); }; function audioBufferToWav(buffer, opt) { diff --git a/test/runtime.mjs b/test/runtime.mjs index 521fb6474..e8f346df7 100644 --- a/test/runtime.mjs +++ b/test/runtime.mjs @@ -99,6 +99,7 @@ const toneHelpersMocked = { '_spectrum', 'markcss', 'p', + 'dough', ].forEach((mock) => { strudel.Pattern.prototype[mock] = function () { return this; diff --git a/undocumented.json b/undocumented.json index 3f5a3be30..5e4116871 100644 --- a/undocumented.json +++ b/undocumented.json @@ -597,8 +597,8 @@ ], "/packages/superdough/dspworklet.mjs": [ "dspWorklet", - "dough", - "doughTrigger" + "rawdsp", + "rawdspTrigger" ], "/packages/superdough/index.mjs": [], "/packages/tonal/tonleiter.mjs": [ From 8120fc72ab47df9e1cffdf6a886d1daecd02ee9b Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Wed, 19 Aug 2026 18:09:05 +0200 Subject: [PATCH 5/5] dummy commit to force service worker refresh --- website/src/components/HeadCommon.astro | 2 +- website/src/components/HeadCommonNext.astro | 2 +- website/src/components/HeadSEO.astro | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/website/src/components/HeadCommon.astro b/website/src/components/HeadCommon.astro index 550222e44..57a425f3f 100644 --- a/website/src/components/HeadCommon.astro +++ b/website/src/components/HeadCommon.astro @@ -24,7 +24,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL - + diff --git a/website/src/components/HeadCommonNext.astro b/website/src/components/HeadCommonNext.astro index f477cd8f0..852c2051d 100644 --- a/website/src/components/HeadCommonNext.astro +++ b/website/src/components/HeadCommonNext.astro @@ -23,7 +23,7 @@ const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL - + diff --git a/website/src/components/HeadSEO.astro b/website/src/components/HeadSEO.astro index 413668c16..ecaedd134 100644 --- a/website/src/components/HeadSEO.astro +++ b/website/src/components/HeadSEO.astro @@ -16,7 +16,7 @@ const imageAlt = frontmatter.image?.alt ?? OPEN_GRAPH.image.alt; - +