mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-13 14:26:58 -04:00
Merge remote-tracking branch 'origin/main' into example-fixes
This commit is contained in:
@@ -13,7 +13,7 @@ https://strudel.cc/
|
||||
|
||||
After cloning the project, you can run the REPL locally:
|
||||
|
||||
1. Install [Node.js](https://nodejs.org/)
|
||||
1. Install [Node.js](https://nodejs.org/) 18 or newer
|
||||
2. Install [pnpm](https://pnpm.io/installation)
|
||||
3. Install dependencies by running the following command:
|
||||
```bash
|
||||
|
||||
@@ -20,5 +20,8 @@
|
||||
"@strudel/tonal": "1.2.5",
|
||||
"@strudel/transpiler": "1.2.5",
|
||||
"@strudel/webaudio": "1.2.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@strudel/web": "1.2.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,5 +18,8 @@
|
||||
"@strudel/transpiler": "workspace:*",
|
||||
"@strudel/webaudio": "workspace:*",
|
||||
"@strudel/tonal": "workspace:*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,5 +32,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -73,5 +73,8 @@
|
||||
"prettier": "^3.4.2",
|
||||
"vitest": "^3.0.4",
|
||||
"vite-plugin-bundle-audioworklet": "workspace:*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,5 +54,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,5 +37,8 @@
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11",
|
||||
"vitest": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,8 @@
|
||||
"@strudel/core": "workspace:*",
|
||||
"@tauri-apps/api": "^2.2.0"
|
||||
},
|
||||
"homepage": "https://codeberg.org/uzu/strudel#readme"
|
||||
"homepage": "https://codeberg.org/uzu/strudel#readme",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,5 +20,8 @@
|
||||
"bugs": {
|
||||
"url": "https://codeberg.org/uzu/strudel/issues"
|
||||
},
|
||||
"homepage": "https://codeberg.org/uzu/strudel#readme"
|
||||
"homepage": "https://codeberg.org/uzu/strudel#readme",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,5 +34,8 @@
|
||||
"devDependencies": {
|
||||
"tree-sitter-haskell": "^0.23.1",
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,5 +40,8 @@
|
||||
"devDependencies": {
|
||||
"pkg": "^5.8.1",
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,5 +35,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,8 @@
|
||||
"peggy": "^4.2.0",
|
||||
"vite": "^6.0.11",
|
||||
"vitest": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,8 @@
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11",
|
||||
"vitest": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,5 +40,8 @@
|
||||
"mondo": "*",
|
||||
"vite": "^6.0.11",
|
||||
"vitest": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,5 +34,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,5 +44,8 @@
|
||||
"devDependencies": {
|
||||
"pkg": "^5.8.1",
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,8 @@
|
||||
"homepage": "https://codeberg.org/uzu/strudel#readme",
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,5 +48,8 @@
|
||||
"@rollup/plugin-replace": "^6.0.2",
|
||||
"vite": "^6.0.11",
|
||||
"vite-plugin-bundle-audioworklet": "workspace:*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,5 +15,8 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,5 +37,8 @@
|
||||
"devDependencies": {
|
||||
"node-fetch": "^3.3.2",
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,5 +37,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"nanostores": "^0.11.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// this is dough, the superdough without dependencies
|
||||
// @ts-check
|
||||
// @ts-nocheck
|
||||
// @ts-ignore ignore next line because sampleRate is unknown
|
||||
const SAMPLE_RATE = typeof sampleRate !== 'undefined' ? sampleRate : 48000;
|
||||
const PI_DIV_SR = Math.PI / SAMPLE_RATE;
|
||||
const ISR = 1 / SAMPLE_RATE;
|
||||
|
||||
let gainCurveFunc = (val) => Math.pow(val, 2);
|
||||
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
|
||||
|
||||
function applyGainCurve(val) {
|
||||
return gainCurveFunc(val);
|
||||
@@ -151,7 +152,8 @@ export class TwoPoleFilter {
|
||||
resonance = Math.max(resonance, 0);
|
||||
|
||||
cutoff = Math.min(cutoff, 20000);
|
||||
const c = 2 * Math.sin(cutoff * PI_DIV_SR);
|
||||
let c = 2 * Math.sin(cutoff * PI_DIV_SR);
|
||||
c = clamp(c, 0, 1.14); // this line prevents instability TODO: test
|
||||
|
||||
const r = Math.pow(0.5, (resonance + 0.125) / 0.125);
|
||||
const mrc = 1 - r * c;
|
||||
|
||||
@@ -32,5 +32,8 @@
|
||||
"vite": "^6.0.11",
|
||||
"vite-plugin-bundle-audioworklet": "workspace:*",
|
||||
"wav-encoder": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,8 @@
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11",
|
||||
"vitest": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,5 +39,8 @@
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11",
|
||||
"vitest": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,8 @@
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ initStrudel();
|
||||
document.getElementById('play').addEventListener('click',
|
||||
() => evaluate('note("c a f e").jux(rev)')
|
||||
);
|
||||
document.getElementById('play').addEventListener('stop',
|
||||
document.getElementById('stop').addEventListener('click',
|
||||
() => hush()
|
||||
);
|
||||
```
|
||||
|
||||
@@ -43,5 +43,8 @@
|
||||
"@rollup/plugin-replace": "^6.0.2",
|
||||
"vite": "^6.0.11",
|
||||
"vite-plugin-bundle-audioworklet": "workspace:*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,5 +40,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,5 +35,8 @@
|
||||
"devDependencies": {
|
||||
"vite": "^6.0.11",
|
||||
"vitest": "^3.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
+6336
-6336
File diff suppressed because it is too large
Load Diff
+15
-1
@@ -4,11 +4,25 @@ import { describe, it } from 'vitest';
|
||||
|
||||
const tuneKeys = Object.keys(tunes);
|
||||
|
||||
// Node 24 tightened Number→string rounding; clamp decimals so snapshots stay stable across engines.
|
||||
const roundFloatStrings = (input, precision = 12) => {
|
||||
// if matches a decimal number ex: 12.34, -0.5, 0.123, 99.0, 1.932093850293
|
||||
const regex = /-?\d+\.\d+/g;
|
||||
return input.replace(regex, (match) => {
|
||||
// converts the literal to a number, performs round to nearest (ties to even)
|
||||
// at the requested precision, and returns the rounded decimal string
|
||||
const rounded = Number(match).toFixed(precision);
|
||||
// trims trailing zeros (and a dangling dot) after rounding, so the displayed string looks tidy
|
||||
return rounded.replace(/\.?0+$/, '').replace(/\.$/, '');
|
||||
});
|
||||
};
|
||||
|
||||
describe('renders tunes', () => {
|
||||
tuneKeys.forEach((key) => {
|
||||
it(`tune: ${key}`, async ({ expect }) => {
|
||||
const haps = await queryCode(tunes[key], testCycles[key] || 1);
|
||||
expect(haps).toMatchSnapshot();
|
||||
const normalized = haps.map((hap) => roundFloatStrings(hap));
|
||||
expect(normalized).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"csv": "^6.3.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,5 +75,8 @@
|
||||
"sharp": "^0.33.5",
|
||||
"workbox-window": "^7.3.0",
|
||||
"vite-plugin-bundle-audioworklet": "workspace:*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ There are 3 quick ways to embed strudel in your website:
|
||||
|
||||
### Inside an iframe
|
||||
|
||||
Using an iframe is the most easy way to embed a studel tune.
|
||||
Using an iframe is the most easy way to embed a strudel tune.
|
||||
You can embed any pattern of your choice via an iframe and the URL of the pattern of your choice:
|
||||
|
||||
```html
|
||||
@@ -133,7 +133,7 @@ If you'd rather use your own UI, you can use the `@strudel/web` package:
|
||||
</script>
|
||||
```
|
||||
|
||||
For more info on this package, see the [@strudel/web README]https://codeberg.org/uzu/strudel/src/branch/main/packages/web#strudel-web).
|
||||
For more info on this package, see the [@strudel/web README](https://codeberg.org/uzu/strudel/src/branch/main/packages/web#strudel-web).
|
||||
|
||||
## Via npm
|
||||
|
||||
|
||||
Reference in New Issue
Block a user