Compare commits

..

1 Commits

Author SHA1 Message Date
Jade (Rose) Rowland 1cbf14bcdb working 2024-02-24 23:47:17 -05:00
86 changed files with 171 additions and 644 deletions
-1
View File
@@ -10,5 +10,4 @@ paper
pnpm-lock.yaml
pnpm-workspace.yaml
**/dev-dist
superdough-wasm
website/.astro
@@ -6,7 +6,7 @@
<script type="module">
import { initStrudel } from 'https://cdn.skypack.dev/@strudel/web@0.8.2';
initStrudel({
prebake: () => samples('github:tidalcycles/dirt-samples'),
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
});
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
click('a', () => evaluate(`s('bd,jvbass(3,8)').jux(rev)`));
+1 -1
View File
@@ -52,7 +52,7 @@
});
function getTune() {
return `samples('github:tidalcycles/dirt-samples')
return `await samples('github:tidalcycles/Dirt-Samples/master')
stack(
// amen
@@ -1,4 +1,4 @@
<script src="https://unpkg.com/@strudel/repl@1.0.2"></script>
<script src="https://unpkg.com/@strudel/repl@0.9.4"></script>
<strudel-editor>
<!--
// @date 23-08-15
-8
View File
@@ -1,8 +0,0 @@
<script src="https://unpkg.com/@strudel/web@1.0.3"></script>
<button id="play">PLAY</button>
<script>
initStrudel({
prebake: () => samples('github:tidalcycles/dirt-samples'),
});
document.getElementById('play').addEventListener('click', () => s('bd sd').play());
</script>
+6 -6
View File
@@ -1,6 +1,6 @@
export const bumpStreet = `// froos - "22 bump street", licensed with CC BY-NC-SA 4.0
samples('github:felixroos/samples')
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
await samples('github:felixroos/samples/main')
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
"<[0,<6 7 9>,13,<17 20 22 26>]!2>/2"
// make it 22 edo
@@ -33,8 +33,8 @@ samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-dru
export const trafficFlam = `// froos - "traffic flam", licensed with CC BY-NC-SA 4.0
samples('github:felixroos/samples')
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
await samples('github:felixroos/samples/main')
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
addVoicings('hip', {
m11: ['2M 3m 4P 7m'],
@@ -69,8 +69,8 @@ export const funk42 = `// froos - how to funk in 42 lines of code
// adapted from "how to funk in two minutes" by marc rebillet https://www.youtube.com/watch?v=3vBwRfQbXkg
// thanks to peach for the transcription: https://www.youtube.com/watch?v=8eiPXvIgda4
samples('github:felixroos/samples')
samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
await samples('github:felixroos/samples/main')
await samples('https://strudel.cc/tidal-drum-machines.json', 'github:ritchse/tidal-drum-machines/main/machines/')
setcps(.5)
+1 -1
View File
@@ -15,7 +15,7 @@
<script type="module">
import { initStrudel } from '@strudel/web';
initStrudel({
prebake: () => samples('github:tidalcycles/dirt-samples'),
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
});
const click = (id, action) => document.getElementById(id).addEventListener('click', action);
+1 -1
View File
@@ -1,4 +1,4 @@
export default `samples('github:tidalcycles/dirt-samples')
export default `await samples('github:tidalcycles/Dirt-Samples/master')
stack(
// amen
+1 -1
View File
@@ -12,7 +12,7 @@
const init = Promise.all([
initAudioOnFirstClick(),
samples('github:tidalcycles/dirt-samples'),
samples('github:tidalcycles/Dirt-Samples/master'),
registerSynthSounds(),
]);
+1 -6
View File
@@ -2,7 +2,7 @@ import { closeBrackets } from '@codemirror/autocomplete';
// import { search, highlightSelectionMatches } from '@codemirror/search';
import { history } from '@codemirror/commands';
import { javascript } from '@codemirror/lang-javascript';
import { defaultHighlightStyle, syntaxHighlighting, bracketMatching } from '@codemirror/language';
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
import { Compartment, EditorState, Prec } from '@codemirror/state';
import {
EditorView,
@@ -24,7 +24,6 @@ import { persistentAtom } from '@nanostores/persistent';
const extensions = {
isLineWrappingEnabled: (on) => (on ? EditorView.lineWrapping : []),
isBracketMatchingEnabled: (on) => (on ? bracketMatching({ brackets: '()[]{}<>' }) : []),
isLineNumbersDisplayed: (on) => (on ? lineNumbers() : []),
theme,
isAutoCompletionEnabled,
@@ -38,7 +37,6 @@ const compartments = Object.fromEntries(Object.keys(extensions).map((key) => [ke
export const defaultSettings = {
keybindings: 'codemirror',
isBracketMatchingEnabled: false,
isLineNumbersDisplayed: true,
isActiveLineHighlighted: false,
isAutoCompletionEnabled: false,
@@ -292,9 +290,6 @@ export class StrudelMirror {
setLineWrappingEnabled(enabled) {
this.reconfigureExtension('isLineWrappingEnabled', enabled);
}
setBracketMatchingEnabled(enabled) {
this.reconfigureExtension('isBracketMatchingEnabled', enabled);
}
setLineNumbersDisplayed(enabled) {
this.reconfigureExtension('isLineNumbersDisplayed', enabled);
}
+3 -2
View File
@@ -1,10 +1,11 @@
{
"name": "@strudel/codemirror",
"version": "1.0.1",
"version": "1.0.0",
"description": "Codemirror Extensions for Strudel",
"main": "index.mjs",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+1 -1
View File
@@ -292,7 +292,7 @@ const generic_params = [
* @name begin
* @param {number | Pattern} amount between 0 and 1, where 1 is the length of the sample
* @example
* samples({ rave: 'rave/AREUREADY.wav' }, 'github:tidalcycles/dirt-samples')
* samples({ rave: 'rave/AREUREADY.wav' }, 'github:tidalcycles/Dirt-Samples/master/')
* s("rave").begin("<0 .25 .5 .75>").fast(2)
*
*/
+14 -8
View File
@@ -10,9 +10,8 @@ https://rohandrape.net/?t=hmt
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 <https://www.gnu.org/licenses/>.
*/
import { Pattern, timeCat, register, silence } from './pattern.mjs';
import { timeCat, register, silence } from './pattern.mjs';
import { rotate, flatten, splitAt, zipWith } from './util.mjs';
import Fraction from './fraction.mjs';
const left = function (n, x) {
const [ons, offs] = n;
@@ -58,6 +57,7 @@ export const bjork = function (ons, steps) {
*
* @memberof Pattern
* @name euclid
* @synonyms euc
* @param {number} pulses the number of onsets / beats
* @param {number} steps the number of steps to fill
* @returns Pattern
@@ -70,6 +70,7 @@ export const bjork = function (ons, steps) {
* Like `euclid`, but has an additional parameter for 'rotating' the resulting sequence.
* @memberof Pattern
* @name euclidRot
* @synonyms eucr
* @param {number} pulses the number of onsets / beats
* @param {number} steps the number of steps to fill
* @param {number} rotation offset in steps
@@ -132,18 +133,22 @@ const _euclidRot = function (pulses, steps, rotation) {
return b;
};
export const euclid = register('euclid', function (pulses, steps, pat) {
export const euclid = register(['euclid', 'euc'], function (pulses, steps, pat) {
return pat.struct(_euclidRot(pulses, steps, 0));
});
export const { euclidrot, euclidRot } = register(['euclidrot', 'euclidRot'], function (pulses, steps, rotation, pat) {
return pat.struct(_euclidRot(pulses, steps, rotation));
});
export const { euclidrot, euclidRot } = register(
['euclidrot', 'euclidRot', 'eucr'],
function (pulses, steps, rotation, pat) {
return pat.struct(_euclidRot(pulses, steps, rotation));
},
);
/**
* Similar to `euclid`, but each pulse is held until the next pulse,
* so there will be no gaps.
* @name euclidLegato
* @synonyms eucl
* @memberof Pattern
* @param {number} pulses the number of onsets / beats
* @param {number} steps the number of steps to fill
@@ -164,7 +169,7 @@ const _euclidLegato = function (pulses, steps, rotation, pat) {
return pat.struct(timeCat(...gapless));
};
export const euclidLegato = register(['euclidLegato'], function (pulses, steps, pat) {
export const euclidLegato = register(['euclidLegato', 'eucl'], function (pulses, steps, pat) {
return _euclidLegato(pulses, steps, 0, pat);
});
@@ -173,6 +178,7 @@ export const euclidLegato = register(['euclidLegato'], function (pulses, steps,
* so there will be no gaps, and has an additional parameter for 'rotating'
* the resulting sequence
* @name euclidLegatoRot
* @synonyms euclr
* @memberof Pattern
* @param {number} pulses the number of onsets / beats
* @param {number} steps the number of steps to fill
@@ -180,6 +186,6 @@ export const euclidLegato = register(['euclidLegato'], function (pulses, steps,
* @example
* note("c3").euclidLegatoRot(3,5,2)
*/
export const euclidLegatoRot = register(['euclidLegatoRot'], function (pulses, steps, rotation, pat) {
export const euclidLegatoRot = register(['euclidLegatoRot', 'euclr'], function (pulses, steps, rotation, pat) {
return _euclidLegato(pulses, steps, rotation, pat);
});
+3 -2
View File
@@ -1,11 +1,12 @@
{
"name": "@strudel/core",
"version": "1.0.1",
"version": "1.0.0",
"description": "Port of Tidal Cycles to JavaScript",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"test": "vitest run",
+3 -3
View File
@@ -2322,10 +2322,10 @@ const _loopAt = function (factor, pat, cps = 0.5) {
* @memberof Pattern
* @returns Pattern
* @example
* samples('github:tidalcycles/dirt-samples')
* await samples('github:tidalcycles/Dirt-Samples/master')
* s("breaks165").slice(8, "0 1 <2 2*2> 3 [4 0] 5 6 7".every(3, rev)).slow(0.75)
* @example
* samples('github:tidalcycles/dirt-samples')
* await samples('github:tidalcycles/Dirt-Samples/master')
* s("breaks125").fit().slice([0,.25,.5,.75], "0 1 1 <2 3>")
*/
@@ -2351,7 +2351,7 @@ export const slice = register(
* Works the same as slice, but changes the playback speed of each slice to match the duration of its step.
* @name splice
* @example
* samples('github:tidalcycles/dirt-samples')
* await samples('github:tidalcycles/Dirt-Samples/master')
* s("breaks165")
* .splice(8, "0 1 [2 3 0]@2 3 0@2 7")
*/
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "@strudel/csound",
"version": "1.0.1",
"version": "1.0.0",
"description": "csound bindings for strudel",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+2 -2
View File
@@ -6,11 +6,11 @@ const OFF_MESSAGE = 0x80;
const CC_MESSAGE = 0xb0;
Pattern.prototype.midi = function (output) {
return this.onTrigger((time, hap, currentTime, cps) => {
return this.onTrigger((time, hap, currentTime) => {
const { note, nrpnn, nrpv, ccn, ccv } = hap.value;
const offset = (time - currentTime) * 1000;
const velocity = Math.floor((hap.context?.velocity ?? 0.9) * 100); // TODO: refactor velocity
const duration = Math.floor((hap.duration.valueOf() / cps) * 1000 - 10);
const duration = Math.floor(hap.duration.valueOf() * 1000 - 10);
const roundedOffset = Math.round(offset);
const midichan = (hap.value.midichan ?? 1) - 1;
const requestedport = output ?? 'IAC';
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "@strudel/hydra",
"version": "1.0.1",
"version": "1.0.0",
"description": "Hydra integration for strudel",
"main": "hydra.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"server": "node server.js",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'hydra.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+3 -9
View File
@@ -129,7 +129,7 @@ Pattern.prototype.midi = function (output) {
const velocity = hap.context?.velocity ?? 0.9; // TODO: refactor velocity
// note off messages will often a few ms arrive late, try to prevent glitching by subtracting from the duration length
const duration = Math.floor((hap.duration.valueOf() / cps) * 1000 - 10);
const duration = Math.floor(hap.duration.valueOf() * 1000 - 10);
if (note != null) {
const midiNumber = typeof note === 'number' ? note : noteToMidi(note);
const midiNote = new Note(midiNumber, { attack: velocity, duration });
@@ -167,16 +167,10 @@ let listeners = {};
const refs = {};
export async function midin(input) {
if (isPattern(input)) {
throw new Error(
`.midi does not accept Pattern input. Make sure to pass device name with single quotes. Example: .midi('${
WebMidi.outputs?.[0]?.name || 'IAC Driver Bus 1'
}')`,
);
}
const initial = await enableWebMidi(); // only returns on first init
const device = getDevice(input, WebMidi.inputs);
if (initial || WebMidi.enabled) {
if (initial) {
const otherInputs = WebMidi.inputs.filter((o) => o.name !== device.name);
logger(
`Midi enabled! Using "${device.name}". ${
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "@strudel/midi",
"version": "1.0.1",
"version": "1.0.0",
"description": "Midi API for strudel",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+3 -2
View File
@@ -1,11 +1,12 @@
{
"name": "@strudel/mini",
"version": "1.0.1",
"version": "1.0.0",
"description": "Mini notation for strudel",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"test": "vitest run",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "@strudel/osc",
"version": "1.0.1",
"version": "1.0.0",
"description": "OSC messaging for strudel",
"main": "osc.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"server": "node server.js",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'osc.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
-2
View File
@@ -1,5 +1,3 @@
# @strudel/repl
The Strudel REPL as a web component.
[Usage example](https://github.com/tidalcycles/strudel/blob/main/examples/buildless/web-component-no-iframe.html)
+2 -2
View File
@@ -1,8 +1,8 @@
{
"name": "@strudel/repl",
"version": "1.0.2",
"version": "1.0.0",
"description": "Strudel REPL as a Web Component",
"module": "index.mjs",
"main": "index.mjs",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/index.mjs"
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "@strudel/serial",
"version": "1.0.1",
"version": "1.0.0",
"description": "Webserial API for strudel",
"main": "serial.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'serial.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+3 -2
View File
@@ -1,10 +1,11 @@
{
"name": "@strudel/soundfonts",
"version": "1.0.1",
"version": "1.0.0",
"description": "Soundsfont support for strudel",
"main": "index.mjs",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
-1
View File
@@ -1 +0,0 @@
rustsaw/target
-57
View File
@@ -1,57 +0,0 @@
# superdough-wasm
This is just a very early experiment to find out how to run wasm in an AudioWorklet.
WASM can be compiled from several languages, which are tested here..
## zig
<https://dev.to/sleibrock/webassembly-with-zig-part-1-4onm>
```sh
# (re)compile dsp.zig
brew install zig # prequisite
cd zigsaw
zig build-lib zigsaw.zig -target wasm32-freestanding -dynamic -rdynamic -O ReleaseSmall # build
npx http-server .. -o # run
```
wasm file size: 690B
## rust
<https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_Wasm>
```sh
# https://www.rust-lang.org/tools/install
cargo install wasm-pack # prequisite
cd rustsaw
wasm-pack build --target bundler # build
npx http-server .. -o # run
```
wasm file size: 653B
## c
<https://emscripten.org/docs/getting_started/Tutorial.html>
```sh
# brew install emscripten
cd csaw
emcc -O2 csaw.c -o csaw # build
npx http-server .. -o
```
wasm file size: 680B
## assemblyscript
<https://www.assemblyscript.org/getting-started.html#setting-up-a-new-project>
```sh
cd ascsaw
# npm i
npm run asbuild # build
```
wasm file size: 122B !
@@ -1,22 +0,0 @@
{
"targets": {
"debug": {
"outFile": "build/debug.wasm",
"textFile": "build/debug.wat",
"sourceMap": true,
"debug": true
},
"release": {
"outFile": "build/release.wasm",
"textFile": "build/release.wat",
"sourceMap": true,
"optimizeLevel": 3,
"shrinkLevel": 2,
"converge": false,
"noAssert": false
}
},
"options": {
"bindings": "esm"
}
}
@@ -1,3 +0,0 @@
export function saw(t: f64, f: f64): f64 {
return (((f * t * 1.0) % 1.0) - 0.5) * 2.0;
}
@@ -1,6 +0,0 @@
{
"extends": "assemblyscript/std/assembly.json",
"include": [
"./**/*.ts"
]
}
@@ -1,2 +0,0 @@
*
!.gitignore
-54
View File
@@ -1,54 +0,0 @@
{
"name": "ascsaw",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ascsaw",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"assemblyscript": "^0.27.22"
}
},
"node_modules/assemblyscript": {
"version": "0.27.22",
"resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.27.22.tgz",
"integrity": "sha512-6ClobsR4Hxn6K0daYp/+n9qWTqVbpdVeSGSVDqRvUEz66vvFb8atS6nLm+fnQ54JXuXmzLQy0uWYYgB8G59btQ==",
"dev": true,
"dependencies": {
"binaryen": "116.0.0-nightly.20231102",
"long": "^5.2.1"
},
"bin": {
"asc": "bin/asc.js",
"asinit": "bin/asinit.js"
},
"engines": {
"node": ">=16",
"npm": ">=7"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/assemblyscript"
}
},
"node_modules/binaryen": {
"version": "116.0.0-nightly.20231102",
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-116.0.0-nightly.20231102.tgz",
"integrity": "sha512-aPU9tlKdw/gcXx6u4PxtDgOtGjg/ZKnYdk23ctYb70GxZgPhWnGWmnBt01aV5dt5yFFo2V4rbB7SzpSFhViFQA==",
"dev": true,
"bin": {
"wasm-opt": "bin/wasm-opt",
"wasm2js": "bin/wasm2js"
}
},
"node_modules/long": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==",
"dev": true
}
}
}
@@ -1,25 +0,0 @@
{
"name": "ascsaw",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "node tests",
"asbuild:debug": "asc assembly/index.ts --target debug",
"asbuild:release": "asc assembly/index.ts --target release",
"asbuild": "npm run asbuild:debug && npm run asbuild:release",
"start": "npx serve ."
},
"author": "",
"license": "ISC",
"devDependencies": {
"assemblyscript": "^0.27.22"
},
"type": "module",
"exports": {
".": {
"import": "./build/release.js",
"types": "./build/release.d.ts"
}
}
}
-1
View File
@@ -1 +0,0 @@
csaw
-7
View File
@@ -1,7 +0,0 @@
#include <math.h>
#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
double saw(double t, double f) {
return fmod((f * t * 1.0), 1.0) - 0.5 * 2.0;
}
Binary file not shown.
-11
View File
@@ -1,11 +0,0 @@
<!doctype html>
<html>
<head>
<title>WASM AudioWorklet Demo</title>
</head>
<body>
<button id="play">play</button>
<input type="range" min="55" max="880" id="freq" />
</body>
<script src="./main.js"></script>
</html>
-24
View File
@@ -1,24 +0,0 @@
let ac;
document.getElementById('play').addEventListener('click', async () => {
ac = ac || new AudioContext();
await ac.resume();
await ac.audioWorklet.addModule('./worklet.js');
const node = new AudioWorkletNode(ac, 'saw-processor');
//let res = await fetch('./zigsaw/zigsaw.wasm');
// let res = await fetch('./csaw/csaw.wasm');
let res = await fetch('./ascsaw/build/release.wasm');
//let res = await fetch('./rustsaw/pkg/rustsaw_bg.wasm');
const buffer = await res.arrayBuffer();
node.port.onmessage = (e) => {
if (e.data === 'OK') {
console.log('worklet ready');
}
};
node.port.postMessage({ webassembly: buffer });
node.connect(ac.destination);
document.getElementById('freq').addEventListener('input', async (e) => {
node.port.postMessage({ frequency: e.target.value });
});
});
-123
View File
@@ -1,123 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bumpalo"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "proc-macro2"
version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustsaw"
version = "0.1.0"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "wasm-bindgen"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
@@ -1,13 +0,0 @@
[package]
name = "rustsaw"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
description = "A sample project with wasm-pack"
license = "MIT/Apache-2.0"
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
@@ -1,6 +0,0 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn saw(t: f64, f: f64) -> f64 {
return (((f * t * 1.0) % 1.0) - 0.5) * 2.0;
}
-38
View File
@@ -1,38 +0,0 @@
class SawProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.t = 0; // samples passed
this.f = 110;
this.port.onmessage = (e) => {
const key = Object.keys(e.data)[0];
const value = e.data[key];
switch (key) {
case 'webassembly':
WebAssembly.instantiate(value, this.importObject).then((result) => {
this.api = result.instance.exports;
this.port.postMessage('OK');
});
break;
case 'frequency':
this.f = value;
}
};
}
process(inputs, outputs, parameters) {
if (this.api) {
const output = outputs[0];
for (let i = 0; i < output[0].length; i++) {
let t = this.t;
let out = 0;
out = this.api.saw(t / 44100, this.f);
output.forEach((channel) => {
channel[i] = out;
});
this.t++;
}
}
return true;
}
}
registerProcessor('saw-processor', SawProcessor);
Binary file not shown.
@@ -1,5 +0,0 @@
const std = @import("std");
export fn saw(t: f64, f: f64) f64 {
return ((@mod(f * t, 1.0)) - 0.5) * 2.0;
}
+2 -2
View File
@@ -19,7 +19,7 @@ import { superdough, samples, initAudioOnFirstClick, registerSynthSounds } from
const init = Promise.all([
initAudioOnFirstClick(),
samples('github:tidalcycles/dirt-samples'),
samples('github:tidalcycles/Dirt-Samples/master'),
registerSynthSounds(),
]);
@@ -148,7 +148,7 @@ The json file is expected to have the same format as described above.
Because it is common to use github for samples, there is a short way to load a sample map from github:
```js
samples('github:tidalcycles/dirt-samples')
samples('github:tidalcycles/Dirt-Samples/master')
```
The format is `github:<user>/<repo>/<branch>`.
+3 -2
View File
@@ -1,11 +1,12 @@
{
"name": "superdough",
"version": "1.0.1",
"version": "1.0.0",
"description": "simple web audio synth and sampler intended for live coding. inspired by superdirt and webdirt.",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.cjs",
"module": "dist/index.mjs"
},
"directories": {
"example": "examples"
+15 -31
View File
@@ -99,27 +99,6 @@ export const getLoadedBuffer = (url) => {
return bufferCache[url];
};
function resolveSpecialPaths(base) {
if (base.startsWith('bubo:')) {
const [_, repo] = base.split(':');
base = `github:Bubobubobubobubo/dough-${repo}`;
}
return base;
}
function githubPath(base, subpath = '') {
if (!base.startsWith('github:')) {
throw new Error('expected "github:" at the start of pseudoUrl');
}
let [_, path] = base.split('github:');
path = path.endsWith('/') ? path.slice(0, -1) : path;
if (path.split('/').length === 2) {
// assume main as default branch if none set
path += '/main';
}
return `https://raw.githubusercontent.com/${path}/${subpath}`;
}
export const processSampleMap = (sampleMap, fn, baseUrl = sampleMap._base || '') => {
return Object.entries(sampleMap).forEach(([key, value]) => {
if (typeof value === 'string') {
@@ -129,19 +108,15 @@ export const processSampleMap = (sampleMap, fn, baseUrl = sampleMap._base || '')
throw new Error('wrong sample map format for ' + key);
}
baseUrl = value._base || baseUrl;
baseUrl = resolveSpecialPaths(baseUrl);
if (baseUrl.startsWith('github:')) {
baseUrl = githubPath(baseUrl, '');
}
const fullUrl = (v) => baseUrl + v;
const replaceUrl = (v) => (baseUrl + v).replace('github:', 'https://raw.githubusercontent.com/');
if (Array.isArray(value)) {
//return [key, value.map(replaceUrl)];
value = value.map(fullUrl);
value = value.map(replaceUrl);
} else {
// must be object
value = Object.fromEntries(
Object.entries(value).map(([note, samples]) => {
return [note, (typeof samples === 'string' ? [samples] : samples).map(fullUrl)];
return [note, (typeof samples === 'string' ? [samples] : samples).map(replaceUrl)];
}),
);
}
@@ -167,7 +142,7 @@ function getSamplesPrefixHandler(url) {
/**
* Loads a collection of samples to use with `s`
* @example
* samples('github:tidalcycles/dirt-samples');
* samples('github:tidalcycles/Dirt-Samples/master');
* s("[bd ~]*2, [~ hh]*2, ~ sd")
* @example
* samples({
@@ -190,9 +165,18 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '', option
if (handler) {
return handler(sampleMap);
}
sampleMap = resolveSpecialPaths(sampleMap);
if (sampleMap.startsWith('bubo:')) {
const [_, repo] = sampleMap.split(':');
sampleMap = `github:Bubobubobubobubo/dough-${repo}`;
}
if (sampleMap.startsWith('github:')) {
sampleMap = githubPath(sampleMap, 'strudel.json');
let [_, path] = sampleMap.split('github:');
path = path.endsWith('/') ? path.slice(0, -1) : path;
if (path.split('/').length === 2) {
// assume main as default branch if none set
path += '/main';
}
sampleMap = `https://raw.githubusercontent.com/${path}/strudel.json`;
}
if (sampleMap.startsWith('shabda:')) {
let [_, path] = sampleMap.split('shabda:');
-5
View File
@@ -253,11 +253,6 @@ function effectSend(input, effect, wet) {
return send;
}
export function resetGlobalEffects() {
delays = {};
reverbs = {};
}
export const superdough = async (value, deadline, hapDuration) => {
const ac = getAudioContext();
if (typeof value !== 'object') {
+1 -1
View File
@@ -8,7 +8,7 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.cjs' })[ext],
},
rollupOptions: {
+3 -2
View File
@@ -1,10 +1,11 @@
{
"name": "@strudel/tonal",
"version": "1.0.1",
"version": "1.0.0",
"description": "Tonal functions for strudel",
"main": "index.mjs",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "@strudel/transpiler",
"version": "1.0.1",
"version": "1.0.0",
"description": "Transpiler for strudel user code. Converts syntactically correct but semantically meaningless JS into evaluatable strudel code.",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
@@ -23,9 +23,6 @@ describe('transpiler', () => {
it('supports top level await', () => {
expect(transpiler("await samples('xxx');", simple).output).toEqual("await samples('xxx');");
});
it('adds await to bare samples call', () => {
expect(transpiler("samples('xxx');", simple).output).toEqual("await samples('xxx');");
});
/* it('parses dynamic imports', () => {
expect(
transpiler("const { default: foo } = await import('https://bar.com/foo.js');", {
+3 -16
View File
@@ -1,7 +1,8 @@
import { getLeafLocations } from '@strudel/mini';
import { parse } from 'acorn';
import escodegen from 'escodegen';
import { parse } from 'acorn';
import { walk } from 'estree-walker';
import { isNoteWithOctave } from '@strudel/core';
import { getLeafLocations } from '@strudel/mini';
export function transpiler(input, options = {}) {
const { wrapAsync = false, addReturn = true, emitMiniLocations = true, emitWidgets = true } = options;
@@ -46,9 +47,6 @@ export function transpiler(input, options = {}) {
});
return this.replace(widgetWithLocation(node));
}
if (isBareSamplesCall(node, parent)) {
return this.replace(withAwait(node));
}
},
leave(node, parent, prop, index) {},
});
@@ -121,14 +119,3 @@ function widgetWithLocation(node) {
node.callee.name = 'sliderWithID';
return node;
}
function isBareSamplesCall(node, parent) {
return node.type === 'CallExpression' && node.callee.name === 'samples' && parent.type !== 'AwaitExpression';
}
function withAwait(node) {
return {
type: 'AwaitExpression',
argument: node,
};
}
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+1 -1
View File
@@ -43,7 +43,7 @@ By default, no external samples are loaded, but you can add them like this:
```js
initStrudel({
prebake: () => samples('github:tidalcycles/dirt-samples'),
prebake: () => samples('github:tidalcycles/Dirt-Samples/master'),
});
document.getElementById('play').addEventListener('click',
+3 -4
View File
@@ -1,8 +1,8 @@
{
"name": "@strudel/web",
"version": "1.0.3",
"version": "1.0.0",
"description": "Easy to setup, opiniated bundle of Strudel for the browser.",
"module": "web.mjs",
"main": "web.mjs",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/index.mjs"
@@ -37,8 +37,7 @@
"@strudel/mini": "workspace:*",
"@strudel/tonal": "workspace:*",
"@strudel/transpiler": "workspace:*",
"@strudel/webaudio": "workspace:*",
"@rollup/plugin-replace": "^5.0.5"
"@strudel/webaudio": "workspace:*"
},
"devDependencies": {
"vite": "^5.0.10"
+3 -11
View File
@@ -1,7 +1,6 @@
import { defineConfig } from 'vite';
import { dependencies } from './package.json';
import { resolve } from 'path';
import replace from '@rollup/plugin-replace';
// https://vitejs.dev/config/
export default defineConfig({
@@ -9,18 +8,11 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'web.mjs'),
name: 'strudel',
formats: ['es', 'iife'],
fileName: (ext) => ({ es: 'index.mjs', iife: 'index.js' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
// external: [...Object.keys(dependencies)],
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
preventAssignment: true,
}),
],
external: [...Object.keys(dependencies)],
},
target: 'esnext',
},
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@strudel/webaudio",
"version": "1.0.1",
"version": "1.0.0",
"description": "Web Audio helpers for Strudel",
"main": "index.mjs",
"type": "module",
@@ -8,7 +8,8 @@
"example": "examples"
},
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"example": "npx parcel examples/repl.html",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+3 -3
View File
@@ -1,11 +1,11 @@
{
"name": "@strudel/xen",
"version": "1.0.1",
"version": "1.0.0",
"description": "Xenharmonic API for strudel",
"main": "index.mjs",
"type": "module",
"publishConfig": {
"main": "dist/index.mjs"
"main": "dist/index.js",
"module": "dist/index.mjs"
},
"scripts": {
"build": "vite build",
+2 -2
View File
@@ -8,8 +8,8 @@ export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'index.mjs'),
formats: ['es'],
fileName: (ext) => ({ es: 'index.mjs' })[ext],
formats: ['es', 'cjs'],
fileName: (ext) => ({ es: 'index.mjs', cjs: 'index.js' })[ext],
},
rollupOptions: {
external: [...Object.keys(dependencies)],
+3 -3
View File
@@ -430,9 +430,6 @@ importers:
packages/web:
dependencies:
'@rollup/plugin-replace':
specifier: ^5.0.5
version: 5.0.5
'@strudel/core':
specifier: workspace:*
version: link:../core
@@ -3694,6 +3691,7 @@ packages:
dependencies:
'@rollup/pluginutils': 5.1.0
magic-string: 0.30.5
dev: true
/@rollup/pluginutils@3.1.0(rollup@2.79.1):
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
@@ -3719,6 +3717,7 @@ packages:
'@types/estree': 1.0.0
estree-walker: 2.0.2
picomatch: 2.3.1
dev: true
/@rollup/rollup-android-arm-eabi@4.9.2:
resolution: {integrity: sha512-RKzxFxBHq9ysZ83fn8Iduv3A283K7zPPYuhL/z9CQuyFrjwpErJx0h4aeb/bnJ+q29GRLgJpY66ceQ/Wcsn3wA==}
@@ -7119,6 +7118,7 @@ packages:
/estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
dev: true
/estree-walker@3.0.3:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
@@ -29,7 +29,7 @@ edit: the desktop app performance on linux is currently not that great.. the web
The desktop App has the same features as the webapp, with the additional ability to load samples from disk. It is currently not documented yet, but you can do something like
```js
samples('~/music/xxx');
await samples('~/music/xxx');
s('my_sound');
```
+2 -2
View File
@@ -1,6 +1,6 @@
export const examples = [
`// "coastline" @by eddyflux
samples('github:eddyflux/crate')
await samples('github:eddyflux/crate')
setcps(.75)
let chords = chord("<Bbm9 Fm9>/4").dict('ireal')
stack(
@@ -30,7 +30,7 @@ stack(
.late("[0 .01]*4").late("[0 .01]*2").size(4)`,
`// "broken cut 1" @by froos
samples('github:tidalcycles/dirt-samples')
await samples('github:tidalcycles/Dirt-Samples/master')
samples({
'slap': 'https://cdn.freesound.org/previews/495/495416_10350281-lq.mp3',
'whirl': 'https://cdn.freesound.org/previews/495/495313_10350281-lq.mp3',
+1 -1
View File
@@ -51,7 +51,7 @@ Alternatively, you can get a taste of what Strudel can do by clicking play on th
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
stack(
s("bd,[~ <sd!3 sd(3,4,2)>],hh*8") // drums
.speed(perlin.range(.7,.9)) // random sample speed variation
+10 -10
View File
@@ -143,7 +143,7 @@ Because GitHub is a popular place for uploading open source samples, it has its
bd: 'bd/BT0AADA.wav',
sd: 'sd/rytm-01-classic.wav',
hh: 'hh27/000_hh27closedhh.wav',
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
s("bd sd bd sd,hh*16")`}
/>
@@ -174,7 +174,7 @@ It is also possible, to declare multiple files for one sound, using the array no
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
s("bd:0 bd:1,~ <sd:0 sd:1> ~ sd:0,[hh:0 hh:1]*4")`}
/>
@@ -187,7 +187,7 @@ The sample number can also be set using `n`:
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav'],
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
s("bd bd,~ sd ~ sd,hh*8").n("<0 1>")`}
/>
@@ -231,7 +231,7 @@ For pitched sounds, you can use `note`, just like with synths:
client:idle
tune={`samples({
'gtr': 'gtr/0001_cleanC.wav',
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').gain(.5)`}
/>
@@ -242,7 +242,7 @@ If we want them to behave more like a synth, we can add `clip(1)`:
client:idle
tune={`samples({
'gtr': 'gtr/0001_cleanC.wav',
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s('gtr').clip(1)
.gain(.5)`}
/>
@@ -256,7 +256,7 @@ If we have 2 samples with different base pitches, we can make them in tune by sp
tune={`samples({
'gtr': 'gtr/0001_cleanC.wav',
'moog': { 'g3': 'moog/005_Mighty%20Moog%20G3.wav' },
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
note("g3 [bb3 c4] <g4 f4 eb4 f3>@2").s("gtr,moog").clip(1)
.gain(.5)`}
/>
@@ -272,7 +272,7 @@ We can also declare different samples for different regions of the keyboard:
'g2': 'moog/004_Mighty%20Moog%20G2.wav',
'g3': 'moog/005_Mighty%20Moog%20G3.wav',
'g4': 'moog/006_Mighty%20Moog%20G4.wav',
}}, 'github:tidalcycles/dirt-samples');
}}, 'github:tidalcycles/Dirt-Samples/master/');
note("g2!2 <bb2 c3>!2, <c4@3 [<eb4 bb3> g4 f4]>")
.s('moog').clip(1)
.gain(.5).cpm(60)`}
@@ -287,7 +287,7 @@ With it, you can enter any sample name(s) to query from [freesound.org](https://
<MiniRepl
client:idle
tune={`samples('shabda:bass:4,hihat:4,rimshot:2')
tune={`await samples('shabda:bass:4,hihat:4,rimshot:2')
stack(
n("0 1 2 3 0 1 2 3").s('bass'),
n("0 1*2 2 3*2").s('hihat'),
@@ -300,8 +300,8 @@ Note that the language code and the gender parameters are optional and default t
<MiniRepl
client:idle
tune={`samples('shabda/speech:the_drum,forever')
samples('shabda/speech/fr-FR/m:magnifique')
tune={`await samples('shabda/speech:the_drum,forever')
await samples('shabda/speech/fr-FR/m:magnifique')
stack(
s("the_drum*2").chop(16).speed(rand.range(0.85,1.1)),
s("forever magnifique").slow(4).late(0.125)
+10 -10
View File
@@ -60,7 +60,7 @@ A sample can be looped and chopped like this:
<MiniRepl
client:visible
tune={`samples('github:yaxu/clean-breaks')
tune={`await samples('github:yaxu/clean-breaks/main')
s("amen/4").fit().chop(32)`}
punchcard
/>
@@ -71,7 +71,7 @@ Let's add randmized doubling + reversing:
<MiniRepl
client:visible
tune={`samples('github:yaxu/clean-breaks')
tune={`await samples('github:yaxu/clean-breaks/main')
s("amen/4").fit().chop(16).cut(1)
.sometimesBy(.5, ply("2"))
.sometimesBy(.25, mul(speed("-1")))`}
@@ -82,7 +82,7 @@ If we want to specify the order of samples, we can replace `chop` with `slice`:
<MiniRepl
client:visible
tune={`samples('github:yaxu/clean-breaks')
tune={`await samples('github:yaxu/clean-breaks/main')
s("amen/4").fit()
.slice(8, "<0 1 2 3 4*2 5 6 [6 7]>*2")
.cut(1).rarely(ply("2"))`}
@@ -93,7 +93,7 @@ If we use `splice` instead of `slice`, the speed adjusts to the duration of the
<MiniRepl
client:visible
tune={`samples('github:yaxu/clean-breaks')
tune={`await samples('github:yaxu/clean-breaks/main')
s("amen")
.splice(8, "<0 1 2 3 4*2 5 6 [6 7]>*2")
.cut(1).rarely(ply("2"))`}
@@ -213,7 +213,7 @@ Using `run` with `n`, we can rush through a sample bank:
<MiniRepl
client:visible
tune={`samples('bubo:fox')
tune={`await samples('bubo:fox')
n(run(8)).s("ftabla")`}
punchcard
/>
@@ -224,7 +224,7 @@ In this case, I hear the beginning at the third sample, which can be accounted f
<MiniRepl
client:visible
tune={`samples('bubo:fox')
tune={`await samples('bubo:fox')
n(run(8)).s("ftabla").early(2/8)`}
/>
@@ -232,7 +232,7 @@ Let's add some randomness:
<MiniRepl
client:visible
tune={`samples('bubo:fox')
tune={`await samples('bubo:fox')
n(run(8)).s("ftabla").early(2/8)
.sometimes(mul(speed("1.5")))`}
/>
@@ -299,7 +299,7 @@ To simplify loading wavetables, any sample that starts with `wt_` will be looped
<MiniRepl
client:visible
tune={`samples('github:bubobubobubobubo/dough-waveforms')
tune={`await samples('github:bubobubobubobubo/dough-waveforms/main')
note("c eb g bb").s("wt_dbass").clip(2)`}
/>
@@ -307,7 +307,7 @@ Running through different wavetables can also give interesting variations:
<MiniRepl
client:visible
tune={`samples('github:bubobubobubobubo/dough-waveforms')
tune={`await samples('github:bubobubobubobubo/dough-waveforms/main')
note("c2*8").s("wt_dbass").n(run(8))`}
/>
@@ -315,7 +315,7 @@ note("c2*8").s("wt_dbass").n(run(8))`}
<MiniRepl
client:visible
tune={`samples('github:bubobubobubobubo/dough-waveforms')
tune={`await samples('github:bubobubobubobubo/dough-waveforms/main')
note("c2*8").s("wt_dbass").n(run(8))
.lpf(perlin.range(200,2000).slow(8))
.lpenv(-3).lpa(.1).room(.5)`}
+1 -1
View File
@@ -8,7 +8,7 @@ import { MiniRepl } from '../../docs/MiniRepl';
Note:
- this has been (partly) translated from https://tidalcycles.org/docs/patternlib/howtos/buildrhythms
- this only sounds good with `samples('github:tidalcycles/dirt-samples')` in prebake
- this only sounds good with `samples('github:tidalcycles/Dirt-Samples/master')` in prebake
# Build Rhythms
+1 -1
View File
@@ -139,7 +139,7 @@ The content of a sequence will be squished into what's called a cycle.
cpm = cycles per minute
By default, the tempo is 30 cycles per minute = 1 half cycle per second.
By default, the tempo is 60 cycles per minute = 1 cycle per second.
</Box>
-5
View File
@@ -64,8 +64,3 @@
#code .cm-focused {
outline: none;
}
#code .cm-matchingBracket {
text-decoration: underline 0.18rem;
text-underline-offset: 0.22rem;
}
+1 -9
View File
@@ -7,13 +7,7 @@ This program is free software: you can redistribute it and/or modify it under th
import { code2hash, getDrawContext, logger, silence } from '@strudel/core';
import cx from '@src/cx.mjs';
import { transpiler } from '@strudel/transpiler';
import {
getAudioContext,
initAudioOnFirstClick,
webaudioOutput,
resetGlobalEffects,
resetLoadedSounds,
} from '@strudel/webaudio';
import { getAudioContext, initAudioOnFirstClick, webaudioOutput } from '@strudel/webaudio';
import { defaultAudioDeviceName } from '../settings.mjs';
import { getAudioDevices, setAudioDevice } from './util.mjs';
import { StrudelMirror, defaultSettings } from '@strudel/codemirror';
@@ -163,7 +157,6 @@ export function Repl({ embedded = false }) {
};
const resetEditor = async () => {
resetGlobalEffects();
clearCanvas();
resetLoadedSounds();
editorRef.current.repl.setCps(0.5);
@@ -190,7 +183,6 @@ export function Repl({ embedded = false }) {
setViewingPatternData(patternData);
clearCanvas();
resetLoadedSounds();
resetGlobalEffects();
await prebake(); // declare default samples
editorRef.current.setCode(code);
editorRef.current.repl.evaluate(code);
-6
View File
@@ -77,7 +77,6 @@ export function SettingsTab({ started }) {
const {
theme,
keybindings,
isBracketMatchingEnabled,
isLineNumbersDisplayed,
isPatternHighlightingEnabled,
isActiveLineHighlighted,
@@ -138,11 +137,6 @@ export function SettingsTab({ started }) {
></ButtonGroup>
</FormItem>
<FormItem label="Code Settings">
<Checkbox
label="Enable bracket matching"
onChange={(cbEvent) => settingsMap.setKey('isBracketMatchingEnabled', cbEvent.target.checked)}
value={isBracketMatchingEnabled}
/>
<Checkbox
label="Display line numbers"
onChange={(cbEvent) => settingsMap.setKey('isLineNumbersDisplayed', cbEvent.target.checked)}
+2 -1
View File
@@ -115,12 +115,13 @@ export async function prebake() {
'numbers/8.wav',
],
},
'github:tidalcycles/dirt-samples',
'github:tidalcycles/Dirt-Samples/master/',
{
prebake: true,
},
),
]);
// await samples('github:tidalcycles/Dirt-Samples/master');
}
const maxPan = noteToMidi('C8');
+5 -5
View File
@@ -527,7 +527,7 @@ export const meltingsubmarine = `// "Melting submarine"
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
// @by Felix Roos
samples('github:tidalcycles/dirt-samples')
await samples('github:tidalcycles/Dirt-Samples/master/')
stack(
s("bd:5,[~ <sd:1!3 sd:1(3,4,3)>],hh27(3,4,1)") // drums
.speed(perlin.range(.7,.9)) // random sample speed variation
@@ -574,7 +574,7 @@ samples({
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
perc: ['perc/002_perc2.wav'],
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
chord("<C^7 Am7 Dm7 G7>*2").dict('lefthand').anchor("G4").voicing()
.stack(n("0@6 [<1 2> <2 0> 1]@2").scale('C5 major'))
@@ -608,7 +608,7 @@ samples({
bd: ['bd/BT0AADA.wav','bd/BT0AAD0.wav','bd/BT0A0DA.wav','bd/BT0A0D3.wav','bd/BT0A0D0.wav','bd/BT0A0A7.wav'],
sd: ['sd/rytm-01-classic.wav','sd/rytm-00-hard.wav'],
hh: ['hh27/000_hh27closedhh.wav','hh/000_hh3closedhh.wav'],
}, 'github:tidalcycles/dirt-samples');
}, 'github:tidalcycles/Dirt-Samples/master/');
note("<8(3,8) <7 7*2> [4 5@3] 8>".sub(1) // sub 1 -> 1-indexed
.layer(
@@ -797,7 +797,7 @@ export const amensister = `// "Amensister"
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
// @by Felix Roos
samples('github:tidalcycles/dirt-samples')
await samples('github:tidalcycles/Dirt-Samples/master')
stack(
// amen
@@ -906,7 +906,7 @@ export const arpoon = `// "Arpoon"
// @license CC BY-NC-SA 4.0 https://creativecommons.org/licenses/by-nc-sa/4.0/
// @by Felix Roos
samples('github:tidalcycles/dirt-samples')
await samples('github:tidalcycles/Dirt-Samples/master')
n("[0,3] 2 [1,3] 2".fast(3).lastOf(4, fast(2))).clip(2)
.offset("<<1 2> 2 1 1>")
-2
View File
@@ -7,7 +7,6 @@ export const defaultAudioDeviceName = 'System Standard';
export const defaultSettings = {
activeFooter: 'intro',
keybindings: 'codemirror',
isBracketMatchingEnabled: true,
isLineNumbersDisplayed: true,
isActiveLineHighlighted: true,
isAutoCompletionEnabled: false,
@@ -41,7 +40,6 @@ export function useSettings() {
return {
...state,
isZen: [true, 'true'].includes(state.isZen) ? true : false,
isBracketMatchingEnabled: [true, 'true'].includes(state.isBracketMatchingEnabled) ? true : false,
isLineNumbersDisplayed: [true, 'true'].includes(state.isLineNumbersDisplayed) ? true : false,
isActiveLineHighlighted: [true, 'true'].includes(state.isActiveLineHighlighted) ? true : false,
isAutoCompletionEnabled: [true, 'true'].includes(state.isAutoCompletionEnabled) ? true : false,