Compare commits

...

31 Commits

Author SHA1 Message Date
Felix Roos 5cf9f9fef4 built in webaudio prebake ? 2022-07-01 10:45:43 +02:00
Felix Roos e44313f631 basic static sample server 2022-07-01 10:45:25 +02:00
Felix Roos 8a1cd32d50 Merge pull request #148 from tidalcycles/webaudio-optimizations
Sampler optimizations and more
2022-06-28 21:54:34 +02:00
Felix Roos 2a18b27114 rerun snapshots 2022-06-28 21:51:11 +02:00
Felix Roos 55f91143d9 rename choke -> clip 2022-06-28 21:50:08 +02:00
Felix Roos cf564a7d06 fix tests 2022-06-27 23:52:02 +02:00
Felix Roos b55067ad60 load piano samples locally 2022-06-27 23:32:45 +02:00
Felix Roos a437c698eb style version log + check if already loaded 2022-06-27 23:17:46 +02:00
Felix Roos f8ada70fe7 add tune 2022-06-27 22:40:59 +02:00
Felix Roos 196d9db3fa log core version + add warning to isPattern 2022-06-27 22:40:50 +02:00
Felix Roos e29eaf3785 fix splitSN 2022-06-27 00:57:27 +02:00
Felix Roos 7048ea473f migrate tone piano to own piano 2022-06-27 00:50:24 +02:00
Felix Roos 720b1eeb27 fix soundfonts + samples without base 2022-06-27 00:49:58 +02:00
Felix Roos 4e282dac5b migrate underground plumber 2022-06-27 00:26:29 +02:00
Felix Roos 42343254b1 fix single sampels 2022-06-27 00:26:21 +02:00
Felix Roos e98829c96b tame oscillator gain 2022-06-27 00:26:11 +02:00
Felix Roos 5791f12a28 add prebake script with piano 2022-06-27 00:04:33 +02:00
Felix Roos fe9a6e8fdd draw note property if set 2022-06-27 00:03:26 +02:00
Felix Roos dd3f4e4751 support "s" as "#" alternative inside note names 2022-06-27 00:03:06 +02:00
Felix Roos a89fa766ea support colon sign as normal char 2022-06-27 00:02:33 +02:00
Felix Roos 39c2cf6c72 add build:parser script once more.. 2022-06-27 00:01:59 +02:00
Felix Roos c1ce72469c webaudio optimizations
- samples with obejct format for pitch declaration
- support note to repitch samples
- support choke to fit samples to hap duration
- support "legacy" context.velocity in .out
- support ":" inside s or note to set n
- fix sample fadeout for soundfonts and choke
- move gain before filters
2022-06-27 00:01:28 +02:00
Felix Roos eca76dd7c4 refactor share for build without top level await 2022-06-26 13:05:36 +02:00
Felix Roos 621b2d8fc9 Merge pull request #146 from tidalcycles/share-link
can now generate short link for sharing
2022-06-26 12:58:53 +02:00
Felix Roos 4039b962b4 can now generate short link for sharing 2022-06-26 12:49:29 +02:00
Felix Roos 3d314324e0 Merge pull request #144 from tidalcycles/flash-effect
flash effect on ctrl enter
2022-06-24 22:16:03 +02:00
Felix Roos b9829bb696 flash effect on ctrl enter 2022-06-24 21:13:17 +02:00
Felix Roos 85f03fb1d0 Merge pull request #142 from tidalcycles/pianoroll-object-support
Pianoroll Object Support
2022-06-22 20:18:17 +02:00
Felix Roos 69810303e5 remove old code 2022-06-22 20:17:12 +02:00
Felix Roos 5b0e31acf3 add tune 2022-06-22 20:13:41 +02:00
Felix Roos 64f717f81b object support for pianoroll 2022-06-21 22:38:05 +02:00
61 changed files with 3235 additions and 3961 deletions
+107 -45
View File
@@ -8504,6 +8504,31 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/peggy": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/peggy/-/peggy-2.0.1.tgz",
"integrity": "sha512-mBqfmdUAOVn7RILpXTbcRBhLfTR4Go0SresSnivGDdRylBOyVFJncFiVyCNNpPWq8HmgeRleXHs/Go4o8kQVXA==",
"dev": true,
"dependencies": {
"commander": "^9.3.0",
"source-map-generator": "0.8.0"
},
"bin": {
"peggy": "bin/peggy.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/peggy/node_modules/commander": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
"integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
"dev": true,
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/performance-now": { "node_modules/performance-now": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -9901,6 +9926,15 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/source-map-generator": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/source-map-generator/-/source-map-generator-0.8.0.tgz",
"integrity": "sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA==",
"dev": true,
"engines": {
"node": ">= 10"
}
},
"node_modules/source-map-js": { "node_modules/source-map-js": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
@@ -11339,7 +11373,7 @@
}, },
"packages/core": { "packages/core": {
"name": "@strudel.cycles/core", "name": "@strudel.cycles/core",
"version": "0.1.0", "version": "0.1.2",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"bjork": "^0.0.1", "bjork": "^0.0.1",
@@ -11351,15 +11385,15 @@
}, },
"packages/embed": { "packages/embed": {
"name": "@strudel.cycles/embed", "name": "@strudel.cycles/embed",
"version": "0.1.0", "version": "0.1.1",
"license": "AGPL-3.0-or-later" "license": "AGPL-3.0-or-later"
}, },
"packages/eval": { "packages/eval": {
"name": "@strudel.cycles/eval", "name": "@strudel.cycles/eval",
"version": "0.1.1", "version": "0.1.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"estraverse": "^5.3.0", "estraverse": "^5.3.0",
"shift-ast": "^6.1.0", "shift-ast": "^6.1.0",
"shift-codegen": "^7.0.3", "shift-codegen": "^7.0.3",
@@ -11383,27 +11417,30 @@
}, },
"packages/midi": { "packages/midi": {
"name": "@strudel.cycles/midi", "name": "@strudel.cycles/midi",
"version": "0.1.1", "version": "0.1.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/tone": "^0.1.1", "@strudel.cycles/tone": "^0.1.3",
"tone": "^14.7.77", "tone": "^14.7.77",
"webmidi": "^2.5.2" "webmidi": "^2.5.2"
} }
}, },
"packages/mini": { "packages/mini": {
"name": "@strudel.cycles/mini", "name": "@strudel.cycles/mini",
"version": "0.1.1", "version": "0.1.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"@strudel.cycles/eval": "^0.1.1", "@strudel.cycles/eval": "^0.1.3",
"@strudel.cycles/tone": "^0.1.1" "@strudel.cycles/tone": "^0.1.3"
},
"devDependencies": {
"peggy": "^2.0.1"
} }
}, },
"packages/osc": { "packages/osc": {
"name": "@strudel.cycles/osc", "name": "@strudel.cycles/osc",
"version": "0.1.0", "version": "0.1.1",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"osc-js": "^2.3.2" "osc-js": "^2.3.2"
@@ -11411,14 +11448,14 @@
}, },
"packages/react": { "packages/react": {
"name": "@strudel.cycles/react", "name": "@strudel.cycles/react",
"version": "0.1.2", "version": "0.1.4",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@codemirror/lang-javascript": "^0.19.0", "@codemirror/lang-javascript": "^0.19.0",
"@strudel.cycles/core": "*", "@strudel.cycles/core": "^0.1.2",
"@strudel.cycles/eval": "^0.1.1", "@strudel.cycles/eval": "^0.1.3",
"@strudel.cycles/tone": "^0.1.1", "@strudel.cycles/tone": "^0.1.3",
"react-codemirror6": "^1.1.0", "react-codemirror6": "^1.1.0",
"react-hook-inview": "^4.5.0" "react-hook-inview": "^4.5.0"
}, },
@@ -11487,16 +11524,16 @@
}, },
"packages/serial": { "packages/serial": {
"name": "@strudel.cycles/serial", "name": "@strudel.cycles/serial",
"version": "0.1.0", "version": "0.1.3",
"license": "AGPL-3.0-or-later" "license": "AGPL-3.0-or-later"
}, },
"packages/soundfonts": { "packages/soundfonts": {
"name": "@strudel.cycles/soundfonts", "name": "@strudel.cycles/soundfonts",
"version": "0.1.0", "version": "0.1.1",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "*", "@strudel.cycles/core": "*",
"@strudel.cycles/webaudio": "*" "@strudel.cycles/webaudio": "^0.1.4"
}, },
"devDependencies": { "devDependencies": {
"node-fetch": "^3.2.6" "node-fetch": "^3.2.6"
@@ -11522,10 +11559,10 @@
}, },
"packages/tonal": { "packages/tonal": {
"name": "@strudel.cycles/tonal", "name": "@strudel.cycles/tonal",
"version": "0.1.1", "version": "0.1.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"@tonaljs/tonal": "^4.6.5", "@tonaljs/tonal": "^4.6.5",
"webmidi": "^3.0.15" "webmidi": "^3.0.15"
} }
@@ -11547,10 +11584,10 @@
}, },
"packages/tone": { "packages/tone": {
"name": "@strudel.cycles/tone", "name": "@strudel.cycles/tone",
"version": "0.1.1", "version": "0.1.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"@tonejs/piano": "^0.2.1", "@tonejs/piano": "^0.2.1",
"chord-voicings": "^0.0.1", "chord-voicings": "^0.0.1",
"tone": "^14.7.77" "tone": "^14.7.77"
@@ -11558,27 +11595,27 @@
}, },
"packages/webaudio": { "packages/webaudio": {
"name": "@strudel.cycles/webaudio", "name": "@strudel.cycles/webaudio",
"version": "0.1.1", "version": "0.1.4",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "^0.1.0" "@strudel.cycles/core": "^0.1.2"
} }
}, },
"packages/webdirt": { "packages/webdirt": {
"name": "@strudel.cycles/webdirt", "name": "@strudel.cycles/webdirt",
"version": "0.1.0", "version": "0.1.2",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"WebDirt": "github:dktr0/WebDirt" "WebDirt": "github:dktr0/WebDirt"
} }
}, },
"packages/xen": { "packages/xen": {
"name": "@strudel.cycles/xen", "name": "@strudel.cycles/xen",
"version": "0.1.1", "version": "0.1.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "^0.1.0" "@strudel.cycles/core": "^0.1.2"
} }
} }
}, },
@@ -13393,7 +13430,7 @@
"@strudel.cycles/eval": { "@strudel.cycles/eval": {
"version": "file:packages/eval", "version": "file:packages/eval",
"requires": { "requires": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"estraverse": "^5.3.0", "estraverse": "^5.3.0",
"shift-ast": "^6.1.0", "shift-ast": "^6.1.0",
"shift-codegen": "^7.0.3", "shift-codegen": "^7.0.3",
@@ -13405,7 +13442,7 @@
"@strudel.cycles/midi": { "@strudel.cycles/midi": {
"version": "file:packages/midi", "version": "file:packages/midi",
"requires": { "requires": {
"@strudel.cycles/tone": "^0.1.1", "@strudel.cycles/tone": "^0.1.3",
"tone": "^14.7.77", "tone": "^14.7.77",
"webmidi": "^2.5.2" "webmidi": "^2.5.2"
} }
@@ -13413,9 +13450,10 @@
"@strudel.cycles/mini": { "@strudel.cycles/mini": {
"version": "file:packages/mini", "version": "file:packages/mini",
"requires": { "requires": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"@strudel.cycles/eval": "^0.1.1", "@strudel.cycles/eval": "^0.1.3",
"@strudel.cycles/tone": "^0.1.1" "@strudel.cycles/tone": "^0.1.3",
"peggy": "^2.0.1"
} }
}, },
"@strudel.cycles/osc": { "@strudel.cycles/osc": {
@@ -13428,9 +13466,9 @@
"version": "file:packages/react", "version": "file:packages/react",
"requires": { "requires": {
"@codemirror/lang-javascript": "^0.19.0", "@codemirror/lang-javascript": "^0.19.0",
"@strudel.cycles/core": "*", "@strudel.cycles/core": "^0.1.2",
"@strudel.cycles/eval": "^0.1.1", "@strudel.cycles/eval": "^0.1.3",
"@strudel.cycles/tone": "^0.1.1", "@strudel.cycles/tone": "^0.1.3",
"@types/react": "^17.0.2", "@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2", "@types/react-dom": "^17.0.2",
"@vitejs/plugin-react": "^1.3.0", "@vitejs/plugin-react": "^1.3.0",
@@ -13494,7 +13532,7 @@
"version": "file:packages/soundfonts", "version": "file:packages/soundfonts",
"requires": { "requires": {
"@strudel.cycles/core": "*", "@strudel.cycles/core": "*",
"@strudel.cycles/webaudio": "*", "@strudel.cycles/webaudio": "^0.1.4",
"node-fetch": "^3.2.6" "node-fetch": "^3.2.6"
}, },
"dependencies": { "dependencies": {
@@ -13514,7 +13552,7 @@
"@strudel.cycles/tonal": { "@strudel.cycles/tonal": {
"version": "file:packages/tonal", "version": "file:packages/tonal",
"requires": { "requires": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"@tonaljs/tonal": "^4.6.5", "@tonaljs/tonal": "^4.6.5",
"webmidi": "^3.0.15" "webmidi": "^3.0.15"
}, },
@@ -13534,7 +13572,7 @@
"@strudel.cycles/tone": { "@strudel.cycles/tone": {
"version": "file:packages/tone", "version": "file:packages/tone",
"requires": { "requires": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"@tonejs/piano": "^0.2.1", "@tonejs/piano": "^0.2.1",
"chord-voicings": "^0.0.1", "chord-voicings": "^0.0.1",
"tone": "^14.7.77" "tone": "^14.7.77"
@@ -13543,20 +13581,20 @@
"@strudel.cycles/webaudio": { "@strudel.cycles/webaudio": {
"version": "file:packages/webaudio", "version": "file:packages/webaudio",
"requires": { "requires": {
"@strudel.cycles/core": "^0.1.0" "@strudel.cycles/core": "^0.1.2"
} }
}, },
"@strudel.cycles/webdirt": { "@strudel.cycles/webdirt": {
"version": "file:packages/webdirt", "version": "file:packages/webdirt",
"requires": { "requires": {
"@strudel.cycles/core": "^0.1.0", "@strudel.cycles/core": "^0.1.2",
"WebDirt": "github:dktr0/WebDirt" "WebDirt": "github:dktr0/WebDirt"
} }
}, },
"@strudel.cycles/xen": { "@strudel.cycles/xen": {
"version": "file:packages/xen", "version": "file:packages/xen",
"requires": { "requires": {
"@strudel.cycles/core": "^0.1.0" "@strudel.cycles/core": "^0.1.2"
} }
}, },
"@tonaljs/abc-notation": { "@tonaljs/abc-notation": {
@@ -18292,6 +18330,24 @@
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true "dev": true
}, },
"peggy": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/peggy/-/peggy-2.0.1.tgz",
"integrity": "sha512-mBqfmdUAOVn7RILpXTbcRBhLfTR4Go0SresSnivGDdRylBOyVFJncFiVyCNNpPWq8HmgeRleXHs/Go4o8kQVXA==",
"dev": true,
"requires": {
"commander": "^9.3.0",
"source-map-generator": "0.8.0"
},
"dependencies": {
"commander": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz",
"integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
"dev": true
}
}
},
"performance-now": { "performance-now": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -18544,9 +18600,9 @@
"version": "file:packages/react", "version": "file:packages/react",
"requires": { "requires": {
"@codemirror/lang-javascript": "^0.19.0", "@codemirror/lang-javascript": "^0.19.0",
"@strudel.cycles/core": "*", "@strudel.cycles/core": "^0.1.2",
"@strudel.cycles/eval": "^0.1.1", "@strudel.cycles/eval": "^0.1.3",
"@strudel.cycles/tone": "^0.1.1", "@strudel.cycles/tone": "^0.1.3",
"@types/react": "^17.0.2", "@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2", "@types/react-dom": "^17.0.2",
"@vitejs/plugin-react": "^1.3.0", "@vitejs/plugin-react": "^1.3.0",
@@ -19410,6 +19466,12 @@
"is-plain-obj": "^2.0.0" "is-plain-obj": "^2.0.0"
} }
}, },
"source-map-generator": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/source-map-generator/-/source-map-generator-0.8.0.tgz",
"integrity": "sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA==",
"dev": true
},
"source-map-js": { "source-map-js": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+1
View File
@@ -10,6 +10,7 @@
"snapshot": "cd repl && npm run snapshot", "snapshot": "cd repl && npm run snapshot",
"repl": "cd repl && npm run dev", "repl": "cd repl && npm run dev",
"osc": "cd packages/osc && npm run server", "osc": "cd packages/osc && npm run server",
"sampler": "cd ./repl/public/samples && node ../../packages/webaudio/sample-server.js",
"build": "rm -rf out && cd repl && npm run build && cd ../tutorial && npm run build", "build": "rm -rf out && cd repl && npm run build && cd ../tutorial && npm run build",
"preview": "npx serve ./out", "preview": "npx serve ./out",
"deploy": "gh-pages -d out", "deploy": "gh-pages -d out",
+1
View File
@@ -744,6 +744,7 @@ const generic_params = [
['f', 'uid', ''], ['f', 'uid', ''],
['f', 'val', ''], ['f', 'val', ''],
['f', 'cps', ''], ['f', 'cps', ''],
['f', 'clip', ''],
]; ];
// TODO: slice / splice https://www.youtube.com/watch?v=hKhPdO0RKDQ&list=PL2lW1zNIIwj3bDkh-Y3LUGDuRcoUigoDs&index=13 // TODO: slice / splice https://www.youtube.com/watch?v=hKhPdO0RKDQ&list=PL2lW1zNIIwj3bDkh-Y3LUGDuRcoUigoDs&index=13
+15 -1
View File
@@ -16,4 +16,18 @@ export * from './timespan.mjs';
export * from './util.mjs'; export * from './util.mjs';
export * from './speak.mjs'; export * from './speak.mjs';
export { default as gist } from './gist.js'; export { default as gist } from './gist.js';
// export * from './value.mjs'; // below won't work with runtime.mjs (json import fails)
/* import * as p from './package.json';
export const version = p.version; */
console.log(
'%c // 🌀 @strudel.cycles/core loaded 🌀', // keep "//" for runnable snapshot source..
'background-color: black;color:white;padding:4px;border-radius:15px',
);
if (globalThis._strudelLoaded) {
console.warn(
`@strudel.cycles/core was loaded more than once...
This might happen when you have multiple versions of strudel installed.
Please check with "npm ls @strudel.cycles/core".`,
);
}
globalThis._strudelLoaded = true;
+11 -2
View File
@@ -15,6 +15,7 @@ import drawLine from './drawLine.mjs';
/** @class Class representing a pattern. */ /** @class Class representing a pattern. */
export class Pattern { export class Pattern {
_Pattern = true; // this property is used to detect if a pattern that fails instanceof Pattern is an instance of another Pattern
/** /**
* Create a pattern. As an end user, you will most likely not create a Pattern directly. * Create a pattern. As an end user, you will most likely not create a Pattern directly.
* *
@@ -1212,7 +1213,15 @@ export function pure(value) {
export function isPattern(thing) { export function isPattern(thing) {
// thing?.constructor?.name !== 'Pattern' // <- this will fail when code is mangled // thing?.constructor?.name !== 'Pattern' // <- this will fail when code is mangled
return thing instanceof Pattern; const is = thing instanceof Pattern || thing._Pattern;
if (!thing instanceof Pattern) {
console.warn(
`Found Pattern that fails "instanceof Pattern" check.
This may happen if you are using multiple versions of @strudel.cycles/core.
Please check by running "npm ls @strudel.cycles/core".`,
);
}
return is;
} }
export function reify(thing) { export function reify(thing) {
@@ -1389,7 +1398,7 @@ export function pr(args) {
} }
export const add = curry((a, pat) => pat.add(a)); export const add = curry((a, pat) => pat.add(a));
export const chop = curry((a, pat) => pat.chop(a)) export const chop = curry((a, pat) => pat.chop(a));
export const chunk = curry((a, pat) => pat.chunk(a)); export const chunk = curry((a, pat) => pat.chunk(a));
export const chunkBack = curry((a, pat) => pat.chunkBack(a)); export const chunkBack = curry((a, pat) => pat.chunkBack(a));
export const div = curry((a, pat) => pat.div(a)); export const div = curry((a, pat) => pat.div(a));
+2 -2
View File
@@ -10,7 +10,7 @@ export const tokenizeNote = (note) => {
if (typeof note !== 'string') { if (typeof note !== 'string') {
return []; return [];
} }
const [pc, acc = '', oct] = note.match(/^([a-gA-G])([#b]*)([0-9])?$/)?.slice(1) || []; const [pc, acc = '', oct] = note.match(/^([a-gA-G])([#bs]*)([0-9])?$/)?.slice(1) || [];
if (!pc) { if (!pc) {
return []; return [];
} }
@@ -24,7 +24,7 @@ export const toMidi = (note) => {
throw new Error('not a note: "' + note + '"'); throw new Error('not a note: "' + note + '"');
} }
const chroma = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 }[pc.toLowerCase()]; const chroma = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 }[pc.toLowerCase()];
const offset = acc?.split('').reduce((o, char) => o + { '#': 1, b: -1 }[char], 0) || 0; const offset = acc?.split('').reduce((o, char) => o + { '#': 1, b: -1, s: 1 }[char], 0) || 0;
return (Number(oct) + 1) * 12 + chroma + offset; return (Number(oct) + 1) * 12 + chroma + offset;
}; };
export const fromMidi = (n) => { export const fromMidi = (n) => {
+164 -158
View File
@@ -1,10 +1,4 @@
/* // Generated by Peggy 2.0.1.
krill-parser.js - <short description TODO>
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/mini/krill-parser.js>
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/>.
*/
// Generated by Peggy 1.2.0.
// //
// https://peggyjs.org/ // https://peggyjs.org/
@@ -16,6 +10,7 @@ function peg$subclass(child, parent) {
function peg$SyntaxError(message, expected, found, location) { function peg$SyntaxError(message, expected, found, location) {
var self = Error.call(this, message); var self = Error.call(this, message);
// istanbul ignore next Check is a necessary evil to support older environments
if (Object.setPrototypeOf) { if (Object.setPrototypeOf) {
Object.setPrototypeOf(self, peg$SyntaxError.prototype); Object.setPrototypeOf(self, peg$SyntaxError.prototype);
} }
@@ -51,14 +46,15 @@ peg$SyntaxError.prototype.format = function(sources) {
var loc = this.location.source + ":" + s.line + ":" + s.column; var loc = this.location.source + ":" + s.line + ":" + s.column;
if (src) { if (src) {
var e = this.location.end; var e = this.location.end;
var filler = peg$padEnd("", s.line.toString().length); var filler = peg$padEnd("", s.line.toString().length, ' ');
var line = src[s.line - 1]; var line = src[s.line - 1];
var last = s.line === e.line ? e.column : line.length + 1; var last = s.line === e.line ? e.column : line.length + 1;
var hatLen = (last - s.column) || 1;
str += "\n --> " + loc + "\n" str += "\n --> " + loc + "\n"
+ filler + " |\n" + filler + " |\n"
+ s.line + " | " + line + "\n" + s.line + " | " + line + "\n"
+ filler + " | " + peg$padEnd("", s.column - 1) + filler + " | " + peg$padEnd("", s.column - 1, ' ')
+ peg$padEnd("", last - s.column, "^"); + peg$padEnd("", hatLen, "^");
} else { } else {
str += "\n at " + loc; str += "\n at " + loc;
} }
@@ -79,7 +75,7 @@ peg$SyntaxError.buildMessage = function(expected, found) {
: classEscape(part); : classEscape(part);
}); });
return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
}, },
any: function() { any: function() {
@@ -185,31 +181,32 @@ function peg$parse(input, options) {
var peg$c7 = "#"; var peg$c7 = "#";
var peg$c8 = "^"; var peg$c8 = "^";
var peg$c9 = "_"; var peg$c9 = "_";
var peg$c10 = "["; var peg$c10 = ":";
var peg$c11 = "]"; var peg$c11 = "[";
var peg$c12 = "<"; var peg$c12 = "]";
var peg$c13 = ">"; var peg$c13 = "<";
var peg$c14 = "@"; var peg$c14 = ">";
var peg$c15 = "!"; var peg$c15 = "@";
var peg$c16 = "("; var peg$c16 = "!";
var peg$c17 = ")"; var peg$c17 = "(";
var peg$c18 = "/"; var peg$c18 = ")";
var peg$c19 = "*"; var peg$c19 = "/";
var peg$c20 = "%"; var peg$c20 = "*";
var peg$c21 = "struct"; var peg$c21 = "%";
var peg$c22 = "target"; var peg$c22 = "struct";
var peg$c23 = "euclid"; var peg$c23 = "target";
var peg$c24 = "slow"; var peg$c24 = "euclid";
var peg$c25 = "rotL"; var peg$c25 = "slow";
var peg$c26 = "rotR"; var peg$c26 = "rotL";
var peg$c27 = "fast"; var peg$c27 = "rotR";
var peg$c28 = "scale"; var peg$c28 = "fast";
var peg$c29 = "//"; var peg$c29 = "scale";
var peg$c30 = "cat"; var peg$c30 = "//";
var peg$c31 = "$"; var peg$c31 = "cat";
var peg$c32 = "setcps"; var peg$c32 = "$";
var peg$c33 = "setbpm"; var peg$c33 = "setcps";
var peg$c34 = "hush"; var peg$c34 = "setbpm";
var peg$c35 = "hush";
var peg$r0 = /^[1-9]/; var peg$r0 = /^[1-9]/;
var peg$r1 = /^[eE]/; var peg$r1 = /^[eE]/;
@@ -235,32 +232,33 @@ function peg$parse(input, options) {
var peg$e14 = peg$literalExpectation("#", false); var peg$e14 = peg$literalExpectation("#", false);
var peg$e15 = peg$literalExpectation("^", false); var peg$e15 = peg$literalExpectation("^", false);
var peg$e16 = peg$literalExpectation("_", false); var peg$e16 = peg$literalExpectation("_", false);
var peg$e17 = peg$literalExpectation("[", false); var peg$e17 = peg$literalExpectation(":", false);
var peg$e18 = peg$literalExpectation("]", false); var peg$e18 = peg$literalExpectation("[", false);
var peg$e19 = peg$literalExpectation("<", false); var peg$e19 = peg$literalExpectation("]", false);
var peg$e20 = peg$literalExpectation(">", false); var peg$e20 = peg$literalExpectation("<", false);
var peg$e21 = peg$literalExpectation("@", false); var peg$e21 = peg$literalExpectation(">", false);
var peg$e22 = peg$literalExpectation("!", false); var peg$e22 = peg$literalExpectation("@", false);
var peg$e23 = peg$literalExpectation("(", false); var peg$e23 = peg$literalExpectation("!", false);
var peg$e24 = peg$literalExpectation(")", false); var peg$e24 = peg$literalExpectation("(", false);
var peg$e25 = peg$literalExpectation("/", false); var peg$e25 = peg$literalExpectation(")", false);
var peg$e26 = peg$literalExpectation("*", false); var peg$e26 = peg$literalExpectation("/", false);
var peg$e27 = peg$literalExpectation("%", false); var peg$e27 = peg$literalExpectation("*", false);
var peg$e28 = peg$literalExpectation("struct", false); var peg$e28 = peg$literalExpectation("%", false);
var peg$e29 = peg$literalExpectation("target", false); var peg$e29 = peg$literalExpectation("struct", false);
var peg$e30 = peg$literalExpectation("euclid", false); var peg$e30 = peg$literalExpectation("target", false);
var peg$e31 = peg$literalExpectation("slow", false); var peg$e31 = peg$literalExpectation("euclid", false);
var peg$e32 = peg$literalExpectation("rotL", false); var peg$e32 = peg$literalExpectation("slow", false);
var peg$e33 = peg$literalExpectation("rotR", false); var peg$e33 = peg$literalExpectation("rotL", false);
var peg$e34 = peg$literalExpectation("fast", false); var peg$e34 = peg$literalExpectation("rotR", false);
var peg$e35 = peg$literalExpectation("scale", false); var peg$e35 = peg$literalExpectation("fast", false);
var peg$e36 = peg$literalExpectation("//", false); var peg$e36 = peg$literalExpectation("scale", false);
var peg$e37 = peg$classExpectation(["\n"], true, false); var peg$e37 = peg$literalExpectation("//", false);
var peg$e38 = peg$literalExpectation("cat", false); var peg$e38 = peg$classExpectation(["\n"], true, false);
var peg$e39 = peg$literalExpectation("$", false); var peg$e39 = peg$literalExpectation("cat", false);
var peg$e40 = peg$literalExpectation("setcps", false); var peg$e40 = peg$literalExpectation("$", false);
var peg$e41 = peg$literalExpectation("setbpm", false); var peg$e41 = peg$literalExpectation("setcps", false);
var peg$e42 = peg$literalExpectation("hush", false); var peg$e42 = peg$literalExpectation("setbpm", false);
var peg$e43 = peg$literalExpectation("hush", false);
var peg$f0 = function() { return parseFloat(text()); }; var peg$f0 = function() { return parseFloat(text()); };
var peg$f1 = function(chars) { return chars.join("") }; var peg$f1 = function(chars) { return chars.join("") };
@@ -294,7 +292,6 @@ function peg$parse(input, options) {
var peg$f29 = function(v) { return new CommandStub("setcps", { value: v})}; var peg$f29 = function(v) { return new CommandStub("setcps", { value: v})};
var peg$f30 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})}; var peg$f30 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})};
var peg$f31 = function() { return new CommandStub("hush")}; var peg$f31 = function() { return new CommandStub("hush")};
var peg$currPos = 0; var peg$currPos = 0;
var peg$savedPos = 0; var peg$savedPos = 0;
var peg$posDetailsCache = [{ line: 1, column: 1 }]; var peg$posDetailsCache = [{ line: 1, column: 1 }];
@@ -810,6 +807,15 @@ function peg$parse(input, options) {
s0 = peg$FAILED; s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e16); } if (peg$silentFails === 0) { peg$fail(peg$e16); }
} }
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 58) {
s0 = peg$c10;
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e17); }
}
}
} }
} }
} }
@@ -852,11 +858,11 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
s1 = peg$parsews(); s1 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 91) { if (input.charCodeAt(peg$currPos) === 91) {
s2 = peg$c10; s2 = peg$c11;
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e17); } if (peg$silentFails === 0) { peg$fail(peg$e18); }
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s3 = peg$parsews(); s3 = peg$parsews();
@@ -864,11 +870,11 @@ function peg$parse(input, options) {
if (s4 !== peg$FAILED) { if (s4 !== peg$FAILED) {
s5 = peg$parsews(); s5 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 93) { if (input.charCodeAt(peg$currPos) === 93) {
s6 = peg$c11; s6 = peg$c12;
peg$currPos++; peg$currPos++;
} else { } else {
s6 = peg$FAILED; s6 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e18); } if (peg$silentFails === 0) { peg$fail(peg$e19); }
} }
if (s6 !== peg$FAILED) { if (s6 !== peg$FAILED) {
s7 = peg$parsews(); s7 = peg$parsews();
@@ -896,11 +902,11 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
s1 = peg$parsews(); s1 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 60) { if (input.charCodeAt(peg$currPos) === 60) {
s2 = peg$c12; s2 = peg$c13;
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e19); } if (peg$silentFails === 0) { peg$fail(peg$e20); }
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s3 = peg$parsews(); s3 = peg$parsews();
@@ -908,11 +914,11 @@ function peg$parse(input, options) {
if (s4 !== peg$FAILED) { if (s4 !== peg$FAILED) {
s5 = peg$parsews(); s5 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 62) { if (input.charCodeAt(peg$currPos) === 62) {
s6 = peg$c13; s6 = peg$c14;
peg$currPos++; peg$currPos++;
} else { } else {
s6 = peg$FAILED; s6 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e20); } if (peg$silentFails === 0) { peg$fail(peg$e21); }
} }
if (s6 !== peg$FAILED) { if (s6 !== peg$FAILED) {
s7 = peg$parsews(); s7 = peg$parsews();
@@ -976,11 +982,11 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 64) { if (input.charCodeAt(peg$currPos) === 64) {
s1 = peg$c14; s1 = peg$c15;
peg$currPos++; peg$currPos++;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e21); } if (peg$silentFails === 0) { peg$fail(peg$e22); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsenumber(); s2 = peg$parsenumber();
@@ -1004,11 +1010,11 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 33) { if (input.charCodeAt(peg$currPos) === 33) {
s1 = peg$c15; s1 = peg$c16;
peg$currPos++; peg$currPos++;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e22); } if (peg$silentFails === 0) { peg$fail(peg$e23); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsenumber(); s2 = peg$parsenumber();
@@ -1032,11 +1038,11 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 40) { if (input.charCodeAt(peg$currPos) === 40) {
s1 = peg$c16; s1 = peg$c17;
peg$currPos++; peg$currPos++;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e23); } if (peg$silentFails === 0) { peg$fail(peg$e24); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1060,11 +1066,11 @@ function peg$parse(input, options) {
} }
s12 = peg$parsews(); s12 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 41) { if (input.charCodeAt(peg$currPos) === 41) {
s13 = peg$c17; s13 = peg$c18;
peg$currPos++; peg$currPos++;
} else { } else {
s13 = peg$FAILED; s13 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e24); } if (peg$silentFails === 0) { peg$fail(peg$e25); }
} }
if (s13 !== peg$FAILED) { if (s13 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
@@ -1098,11 +1104,11 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 47) { if (input.charCodeAt(peg$currPos) === 47) {
s1 = peg$c18; s1 = peg$c19;
peg$currPos++; peg$currPos++;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e25); } if (peg$silentFails === 0) { peg$fail(peg$e26); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsenumber(); s2 = peg$parsenumber();
@@ -1126,11 +1132,11 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 42) { if (input.charCodeAt(peg$currPos) === 42) {
s1 = peg$c19; s1 = peg$c20;
peg$currPos++; peg$currPos++;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e26); } if (peg$silentFails === 0) { peg$fail(peg$e27); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsenumber(); s2 = peg$parsenumber();
@@ -1154,11 +1160,11 @@ function peg$parse(input, options) {
s0 = peg$currPos; s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 37) { if (input.charCodeAt(peg$currPos) === 37) {
s1 = peg$c20; s1 = peg$c21;
peg$currPos++; peg$currPos++;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e27); } if (peg$silentFails === 0) { peg$fail(peg$e28); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsenumber(); s2 = peg$parsenumber();
@@ -1332,12 +1338,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 6) === peg$c21) { if (input.substr(peg$currPos, 6) === peg$c22) {
s1 = peg$c21; s1 = peg$c22;
peg$currPos += 6; peg$currPos += 6;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e28); } if (peg$silentFails === 0) { peg$fail(peg$e29); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1361,12 +1367,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3, s4, s5; var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 6) === peg$c22) { if (input.substr(peg$currPos, 6) === peg$c23) {
s1 = peg$c22; s1 = peg$c23;
peg$currPos += 6; peg$currPos += 6;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e29); } if (peg$silentFails === 0) { peg$fail(peg$e30); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1402,12 +1408,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3, s4, s5, s6, s7; var s0, s1, s2, s3, s4, s5, s6, s7;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 6) === peg$c23) { if (input.substr(peg$currPos, 6) === peg$c24) {
s1 = peg$c23; s1 = peg$c24;
peg$currPos += 6; peg$currPos += 6;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e30); } if (peg$silentFails === 0) { peg$fail(peg$e31); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1443,12 +1449,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 4) === peg$c24) { if (input.substr(peg$currPos, 4) === peg$c25) {
s1 = peg$c24; s1 = peg$c25;
peg$currPos += 4; peg$currPos += 4;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e31); } if (peg$silentFails === 0) { peg$fail(peg$e32); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1472,12 +1478,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 4) === peg$c25) { if (input.substr(peg$currPos, 4) === peg$c26) {
s1 = peg$c25; s1 = peg$c26;
peg$currPos += 4; peg$currPos += 4;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e32); } if (peg$silentFails === 0) { peg$fail(peg$e33); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1501,12 +1507,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 4) === peg$c26) { if (input.substr(peg$currPos, 4) === peg$c27) {
s1 = peg$c26; s1 = peg$c27;
peg$currPos += 4; peg$currPos += 4;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e33); } if (peg$silentFails === 0) { peg$fail(peg$e34); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1530,12 +1536,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 4) === peg$c27) { if (input.substr(peg$currPos, 4) === peg$c28) {
s1 = peg$c27; s1 = peg$c28;
peg$currPos += 4; peg$currPos += 4;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e34); } if (peg$silentFails === 0) { peg$fail(peg$e35); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1559,12 +1565,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3, s4, s5; var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 5) === peg$c28) { if (input.substr(peg$currPos, 5) === peg$c29) {
s1 = peg$c28; s1 = peg$c29;
peg$currPos += 5; peg$currPos += 5;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e35); } if (peg$silentFails === 0) { peg$fail(peg$e36); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1609,12 +1615,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 2) === peg$c29) { if (input.substr(peg$currPos, 2) === peg$c30) {
s1 = peg$c29; s1 = peg$c30;
peg$currPos += 2; peg$currPos += 2;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e36); } if (peg$silentFails === 0) { peg$fail(peg$e37); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = []; s2 = [];
@@ -1623,7 +1629,7 @@ function peg$parse(input, options) {
peg$currPos++; peg$currPos++;
} else { } else {
s3 = peg$FAILED; s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e37); } if (peg$silentFails === 0) { peg$fail(peg$e38); }
} }
while (s3 !== peg$FAILED) { while (s3 !== peg$FAILED) {
s2.push(s3); s2.push(s3);
@@ -1632,7 +1638,7 @@ function peg$parse(input, options) {
peg$currPos++; peg$currPos++;
} else { } else {
s3 = peg$FAILED; s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e37); } if (peg$silentFails === 0) { peg$fail(peg$e38); }
} }
} }
s1 = [s1, s2]; s1 = [s1, s2];
@@ -1649,21 +1655,21 @@ function peg$parse(input, options) {
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 3) === peg$c30) { if (input.substr(peg$currPos, 3) === peg$c31) {
s1 = peg$c30; s1 = peg$c31;
peg$currPos += 3; peg$currPos += 3;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e38); } if (peg$silentFails === 0) { peg$fail(peg$e39); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 91) { if (input.charCodeAt(peg$currPos) === 91) {
s3 = peg$c10; s3 = peg$c11;
peg$currPos++; peg$currPos++;
} else { } else {
s3 = peg$FAILED; s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e17); } if (peg$silentFails === 0) { peg$fail(peg$e18); }
} }
if (s3 !== peg$FAILED) { if (s3 !== peg$FAILED) {
s4 = peg$parsews(); s4 = peg$parsews();
@@ -1705,11 +1711,11 @@ function peg$parse(input, options) {
} }
s7 = peg$parsews(); s7 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 93) { if (input.charCodeAt(peg$currPos) === 93) {
s8 = peg$c11; s8 = peg$c12;
peg$currPos++; peg$currPos++;
} else { } else {
s8 = peg$FAILED; s8 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e18); } if (peg$silentFails === 0) { peg$fail(peg$e19); }
} }
if (s8 !== peg$FAILED) { if (s8 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
@@ -1770,11 +1776,11 @@ function peg$parse(input, options) {
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 36) { if (input.charCodeAt(peg$currPos) === 36) {
s3 = peg$c31; s3 = peg$c32;
peg$currPos++; peg$currPos++;
} else { } else {
s3 = peg$FAILED; s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e39); } if (peg$silentFails === 0) { peg$fail(peg$e40); }
} }
if (s3 !== peg$FAILED) { if (s3 !== peg$FAILED) {
s4 = peg$parsews(); s4 = peg$parsews();
@@ -1852,12 +1858,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 6) === peg$c32) { if (input.substr(peg$currPos, 6) === peg$c33) {
s1 = peg$c32; s1 = peg$c33;
peg$currPos += 6; peg$currPos += 6;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e40); } if (peg$silentFails === 0) { peg$fail(peg$e41); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1881,12 +1887,12 @@ function peg$parse(input, options) {
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 6) === peg$c33) { if (input.substr(peg$currPos, 6) === peg$c34) {
s1 = peg$c33; s1 = peg$c34;
peg$currPos += 6; peg$currPos += 6;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e41); } if (peg$silentFails === 0) { peg$fail(peg$e42); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@@ -1910,12 +1916,12 @@ function peg$parse(input, options) {
var s0, s1; var s0, s1;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 4) === peg$c34) { if (input.substr(peg$currPos, 4) === peg$c35) {
s1 = peg$c34; s1 = peg$c35;
peg$currPos += 4; peg$currPos += 4;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e42); } if (peg$silentFails === 0) { peg$fail(peg$e43); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
@@ -1938,35 +1944,34 @@ function peg$parse(input, options) {
} }
var PatternStub = function(source, alignment) var PatternStub = function(source, alignment)
{ {
this.type_ = "pattern"; this.type_ = "pattern";
this.arguments_ = { alignment : alignment}; this.arguments_ = { alignment : alignment};
this.source_ = source; this.source_ = source;
} }
var OperatorStub = function(name, args, source) var OperatorStub = function(name, args, source)
{ {
this.type_ = name; this.type_ = name;
this.arguments_ = args; this.arguments_ = args;
this.source_ = source; this.source_ = source;
} }
var ElementStub = function(source, options) var ElementStub = function(source, options)
{ {
this.type_ = "element"; this.type_ = "element";
this.source_ = source; this.source_ = source;
this.options_ = options; this.options_ = options;
this.location_ = location(); this.location_ = location();
} }
var CommandStub = function(name, options)
{
this.type_ = "command";
this.name_ = name;
this.options_ = options;
}
var CommandStub = function(name, options)
{
this.type_ = "command";
this.name_ = name;
this.options_ = options;
}
peg$result = peg$startRuleFunction(); peg$result = peg$startRuleFunction();
@@ -1990,5 +1995,6 @@ function peg$parse(input, options) {
export { export {
peg$SyntaxError as SyntaxError, peg$SyntaxError as SyntaxError,
peg$parse as parse peg$parse as parse
}; };
+1 -1
View File
@@ -87,7 +87,7 @@ quote = '"' / "'"
// ------------------ steps and cycles --------------------------- // ------------------ steps and cycles ---------------------------
// single step definition (e.g bd) // single step definition (e.g bd)
step_char = [0-9a-zA-Z~] / "-" / "#" / "." / "^" / "_" step_char = [0-9a-zA-Z~] / "-" / "#" / "." / "^" / "_" / ":"
step = ws chars:step_char+ ws { return chars.join("") } step = ws chars:step_char+ ws { return chars.join("") }
// define a sub cycle e.g. [1 2, 3 [4]] // define a sub cycle e.g. [1 2, 3 [4]]
+1031
View File
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -5,7 +5,8 @@
"main": "index.mjs", "main": "index.mjs",
"type": "module", "type": "module",
"scripts": { "scripts": {
"test": "mocha --colors" "test": "mocha --colors",
"build:parser": "peggy -o krill-parser.js --format es ./krill.pegjs"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -28,5 +29,8 @@
"@strudel.cycles/core": "^0.1.2", "@strudel.cycles/core": "^0.1.2",
"@strudel.cycles/eval": "^0.1.3", "@strudel.cycles/eval": "^0.1.3",
"@strudel.cycles/tone": "^0.1.3" "@strudel.cycles/tone": "^0.1.3"
},
"devDependencies": {
"peggy": "^2.0.1"
} }
} }
+2 -2
View File
File diff suppressed because one or more lines are too long
+35 -10
View File
@@ -145,6 +145,37 @@ const materialPalenightHighlightStyle = HighlightStyle.define([
// : Extension // : Extension
const materialPalenight = [materialPalenightTheme, materialPalenightHighlightStyle]; const materialPalenight = [materialPalenightTheme, materialPalenightHighlightStyle];
const setFlash = StateEffect.define();
const flashField = StateField.define({
create() {
return Decoration.none;
},
update(flash2, tr) {
try {
for (let e of tr.effects) {
if (e.is(setFlash)) {
if (e.value) {
const mark = Decoration.mark({ attributes: { style: `background-color: #FFCA2880` } });
flash2 = Decoration.set([mark.range(0, tr.newDoc.length)]);
} else {
flash2 = Decoration.set([]);
}
}
}
return flash2;
} catch (err) {
console.warn("flash error", err);
return flash2;
}
},
provide: (f) => EditorView.decorations.from(f)
});
const flash = (view) => {
view.dispatch({ effects: setFlash.of(true) });
setTimeout(() => {
view.dispatch({ effects: setFlash.of(false) });
}, 200);
};
const setHighlights = StateEffect.define(); const setHighlights = StateEffect.define();
const highlightField = StateField.define({ const highlightField = StateField.define({
create() { create() {
@@ -187,7 +218,8 @@ function CodeMirror({ value, onChange, onViewChanged, onCursor, options, editorD
extensions: [ extensions: [
javascript(), javascript(),
materialPalenight, materialPalenight,
highlightField highlightField,
flashField
] ]
})); }));
} }
@@ -340,14 +372,7 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawP
/* console.warn('no instrument chosen', event); /* console.warn('no instrument chosen', event);
throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */ throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */
} else { } else {
onTrigger( onTrigger(time, event, currentTime, 1 /* cps */);
time,
event,
currentTime,
1 /* cps */,
event.wholeOrPart().begin.valueOf(),
event.duration.valueOf(),
);
} }
} catch (err) { } catch (err) {
console.warn(err); console.warn(err);
@@ -623,4 +648,4 @@ function useWebMidi(props) {
return { loading, outputs, outputByName }; return { loading, outputs, outputByName };
} }
export { CodeMirror, MiniRepl, cx, useCycle, useHighlighting, usePostMessage, useRepl, useWebMidi }; export { CodeMirror, MiniRepl, cx, flash, useCycle, useHighlighting, usePostMessage, useRepl, useWebMidi };
@@ -7,6 +7,39 @@ import { javascript } from '@codemirror/lang-javascript';
// import { materialPalenight } from 'codemirror6-themes'; // import { materialPalenight } from 'codemirror6-themes';
import { materialPalenight } from '../themes/material-palenight'; import { materialPalenight } from '../themes/material-palenight';
export const setFlash = StateEffect.define();
const flashField = StateField.define({
create() {
return Decoration.none;
},
update(flash, tr) {
try {
for (let e of tr.effects) {
if (e.is(setFlash)) {
if (e.value) {
const mark = Decoration.mark({ attributes: { style: `background-color: #FFCA2880` } });
flash = Decoration.set([mark.range(0, tr.newDoc.length)]);
} else {
flash = Decoration.set([]);
}
}
}
return flash;
} catch (err) {
console.warn('flash error', err);
return flash;
}
},
provide: (f) => EditorView.decorations.from(f),
});
export const flash = (view) => {
view.dispatch({ effects: setFlash.of(true) });
setTimeout(() => {
view.dispatch({ effects: setFlash.of(false) });
}, 200);
};
export const setHighlights = StateEffect.define(); export const setHighlights = StateEffect.define();
const highlightField = StateField.define({ const highlightField = StateField.define({
create() { create() {
@@ -61,6 +94,7 @@ export default function CodeMirror({ value, onChange, onViewChanged, onCursor, o
javascript(), javascript(),
materialPalenight, materialPalenight,
highlightField, highlightField,
flashField,
// theme, language, ... // theme, language, ...
]} ]}
/> />
+1 -1
View File
@@ -1,6 +1,6 @@
// import 'tailwindcss/tailwind.css'; // import 'tailwindcss/tailwind.css';
export { default as CodeMirror } from './components/CodeMirror6'; export { default as CodeMirror, flash } from './components/CodeMirror6';
export * from './components/MiniRepl'; export * from './components/MiniRepl';
export { default as useCycle } from './hooks/useCycle'; export { default as useCycle } from './hooks/useCycle';
export { default as useHighlighting } from './hooks/useHighlighting'; export { default as useHighlighting } from './hooks/useHighlighting';
+3
View File
@@ -16,6 +16,9 @@ async function loadFont(name) {
} }
export async function getFontBufferSource(name, pitch, ac) { export async function getFontBufferSource(name, pitch, ac) {
if (typeof pitch === 'string') {
pitch = toMidi(pitch);
}
const { buffer, zone } = await getFontPitch(name, pitch, ac); const { buffer, zone } = await getFontPitch(name, pitch, ac);
const src = ac.createBufferSource(); const src = ac.createBufferSource();
src.buffer = buffer; src.buffer = buffer;
+1 -2
View File
@@ -36,8 +36,7 @@ Pattern.prototype.draw = function (callback, { from, to, onQuery }) {
const begin = currentCycle + from; const begin = currentCycle + from;
const end = currentCycle + to; const end = currentCycle + to;
setTimeout(() => { setTimeout(() => {
events = this._asNumber(true) // true = silent error events = this.query(new State(new TimeSpan(begin, end)))
.query(new State(new TimeSpan(begin, end)))
.filter(Boolean) .filter(Boolean)
.filter((event) => event.part.begin.equals(event.whole.begin)); .filter((event) => event.part.begin.equals(event.whole.begin));
onQuery?.(events); onQuery?.(events);
+9 -3
View File
@@ -7,6 +7,13 @@ This program is free software: you can redistribute it and/or modify it under th
import { Pattern } from '@strudel.cycles/core'; import { Pattern } from '@strudel.cycles/core';
const scale = (normalized, min, max) => normalized * (max - min) + min; const scale = (normalized, min, max) => normalized * (max - min) + min;
const getValue = (e) => {
let value = typeof e.value === 'object' ? e.value.note ?? e.value.n : e.value;
if (typeof value === 'string') {
value = toMidi(value);
}
return value;
};
Pattern.prototype.pianoroll = function ({ Pattern.prototype.pianoroll = function ({
cycles = 4, cycles = 4,
@@ -75,9 +82,9 @@ Pattern.prototype.pianoroll = function ({
ctx.stroke(); ctx.stroke();
const timePx = scale((event.whole.begin - (flipTime ? to : from)) / timeExtent, ...timeRange); const timePx = scale((event.whole.begin - (flipTime ? to : from)) / timeExtent, ...timeRange);
let durationPx = scale(event.duration / timeExtent, 0, timeAxis); let durationPx = scale(event.duration / timeExtent, 0, timeAxis);
const value = getValue(event);
const valuePx = scale( const valuePx = scale(
fold ? foldValues.indexOf(event.value) / foldValues.length : (Number(event.value) - minMidi) / valueExtent, fold ? foldValues.indexOf(value) / foldValues.length : (Number(value) - minMidi) / valueExtent,
...valueRange, ...valueRange,
); );
let margin = 0; let margin = 0;
@@ -105,7 +112,6 @@ Pattern.prototype.pianoroll = function ({
from: from - overscan, from: from - overscan,
to: to + overscan, to: to + overscan,
onQuery: (events) => { onQuery: (events) => {
const getValue = (e) => Number(e.value);
const { min, max, values } = events.reduce( const { min, max, values } = events.reduce(
({ min, max, values }, e) => { ({ min, max, values }, e) => {
const v = getValue(e); const v = getValue(e);
+1
View File
@@ -8,3 +8,4 @@ export * from './clockworker.mjs';
export * from './scheduler.mjs'; export * from './scheduler.mjs';
export * from './webaudio.mjs'; export * from './webaudio.mjs';
export * from './sampler.mjs'; export * from './sampler.mjs';
export * from './prebake.mjs';
+834 -3636
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -29,5 +29,10 @@
"homepage": "https://github.com/tidalcycles/strudel#readme", "homepage": "https://github.com/tidalcycles/strudel#readme",
"dependencies": { "dependencies": {
"@strudel.cycles/core": "^0.1.2" "@strudel.cycles/core": "^0.1.2"
},
"devDependencies": {
"koa": "^2.13.4",
"koa-static": "^5.0.0",
"@koa/cors": "^3.3.0"
} }
} }
+83
View File
@@ -0,0 +1,83 @@
import { Pattern, toMidi } from '@strudel.cycles/core';
import { samples } from '.';
let baking;
export function prebake(props) {
if (baking) {
return baking;
}
baking = prebaker(props);
return baking;
}
async function prebaker(props = {}) {
const { baseURL = './samples' } = props; // http://localhost:1234
try {
samples(
{
piano: {
A0: 'A0v8.mp3',
C1: 'C1v8.mp3',
Ds1: 'Ds1v8.mp3',
Fs1: 'Fs1v8.mp3',
A1: 'A1v8.mp3',
C2: 'C2v8.mp3',
Ds2: 'Ds2v8.mp3',
Fs2: 'Fs2v8.mp3',
A2: 'A2v8.mp3',
C3: 'C3v8.mp3',
Ds3: 'Ds3v8.mp3',
Fs3: 'Fs3v8.mp3',
A3: 'A3v8.mp3',
C4: 'C4v8.mp3',
Ds4: 'Ds4v8.mp3',
Fs4: 'Fs4v8.mp3',
A4: 'A4v8.mp3',
C5: 'C5v8.mp3',
Ds4: 'Ds4v8.mp3',
Fs5: 'Fs5v8.mp3',
A5: 'A5v8.mp3',
C6: 'C6v8.mp3',
Ds6: 'Ds6v8.mp3',
Fs6: 'Fs6v8.mp3',
A6: 'A6v8.mp3',
C7: 'C7v8.mp3',
Ds7: 'Ds7v8.mp3',
Fs7: 'Fs7v8.mp3',
A7: 'A7v8.mp3',
C8: 'C8v8.mp3',
},
},
// https://archive.org/details/SalamanderGrandPianoV3
// License: CC-by http://creativecommons.org/licenses/by/3.0/ Author: Alexander Holm
baseURL + '/piano/',
);
const maxPan = toMidi('C8');
const panwidth = (pan, width) => pan * width + (1 - width) / 2;
Pattern.prototype.piano = function () {
return this.clip(1)
.s('piano')
.fmap((value) => {
// pan by pitch
const pan = panwidth(Math.min(toMidi(value.note) / maxPan, 1), 0.5);
return { ...value, pan: (value.pan || 1) * pan };
});
};
// ping sample server
/* await fetch(samplerURL)
.then(() => {
console.log(`prebake: Using samples from "${baseURL}"`);
})
.catch(() => {
throw new Error(
`sample server not running at "${samplerURL}"... run "npm run sampler" from the strudel project root.`,
);
}); */
} catch (e) {
console.warn('prebake error', e);
}
}
+34
View File
@@ -0,0 +1,34 @@
// "sampler": "cd ./repl/public/samples && node ../../../packages/webaudio/sample-server.js",
// "sampler": "http-server ./repl/public",
import fs from 'fs';
import path from 'path';
import Koa from 'koa'; // CJS: require('koa');
import cors from '@koa/cors';
import serve from 'koa-static'; // CJS: require('koa-static')
const cwd = process.cwd();
const yellow = '\x1b[33m%s\x1b[0m';
// get array of all folders in cwd:
const banks = fs.readdirSync(cwd).filter((f) => fs.statSync(path.join(cwd, f)).isDirectory());
const app = new Koa();
app.use(cors());
app.use(serve(cwd));
app.use((ctx, next) => {
return next().then(() => {
if (ctx.path === '/') {
ctx.body = 'banks: ' + banks.join(', ');
}
});
});
const port = 1234;
app.listen(port);
console.log(yellow, `strudel sampler running at http://localhost:${port}`);
// node: get current working directory
console.log(yellow, 'cwd: ' + cwd);
console.log('found banks:');
banks.map((c) => console.log(yellow, c));
+23 -7
View File
@@ -93,16 +93,32 @@ export const loadGithubSamples = async (path, nameFn) => {
* *
*/ */
export const samples = (sampleMap, baseUrl = sampleMap._base) => { export const samples = (sampleMap, baseUrl = sampleMap._base || '') => {
sampleCache.current = { sampleCache.current = {
...sampleCache.current, ...sampleCache.current,
...Object.fromEntries( ...Object.fromEntries(
Object.entries(sampleMap).map(([key, value]) => [ Object.entries(sampleMap).map(([key, value]) => {
key, if (typeof value === 'string') {
(typeof value === 'string' ? [value] : value).map((v) => value = [value];
(baseUrl + v).replace('github:', 'https://raw.githubusercontent.com/'), }
), if (typeof value !== 'object') {
]), throw new Error('wrong sample map format for ' + key);
}
baseUrl = value._base || baseUrl;
const replaceUrl = (v) => (baseUrl + v).replace('github:', 'https://raw.githubusercontent.com/');
if (Array.isArray(value)) {
return [key, value.map(replaceUrl)];
}
// must be object
return [
key,
Object.fromEntries(
Object.entries(value).map(([note, samples]) => {
return [note, (typeof samples === 'string' ? [samples] : samples).map(replaceUrl)];
}),
),
];
}),
), ),
}; };
}; };
+78 -21
View File
@@ -6,7 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th
// import { Pattern, getFrequency, patternify2 } from '@strudel.cycles/core'; // import { Pattern, getFrequency, patternify2 } from '@strudel.cycles/core';
import * as strudel from '@strudel.cycles/core'; import * as strudel from '@strudel.cycles/core';
import { fromMidi } from '@strudel.cycles/core'; import { fromMidi, toMidi } from '@strudel.cycles/core';
import { loadBuffer } from './sampler.mjs'; import { loadBuffer } from './sampler.mjs';
const { Pattern } = strudel; const { Pattern } = strudel;
@@ -68,7 +68,11 @@ const getSoundfontKey = (s) => {
return; return;
}; };
const getSampleBufferSource = async (s, n) => { const getSampleBufferSource = async (s, n, note) => {
let transpose = 0;
if (note) {
transpose = toMidi(note) - 36; // C3 is middle C
}
const ac = getAudioContext(); const ac = getAudioContext();
// is sample from loaded samples(..) // is sample from loaded samples(..)
const samples = getLoadedSamples(); const samples = getLoadedSamples();
@@ -79,13 +83,47 @@ const getSampleBufferSource = async (s, n) => {
if (!bank) { if (!bank) {
throw new Error('sample not found:', s, 'try one of ' + Object.keys(samples)); throw new Error('sample not found:', s, 'try one of ' + Object.keys(samples));
} }
const sampleUrl = bank[n % bank.length]; if (typeof bank !== 'object') {
throw new Error('wrong format for sample bank:', s);
}
let sampleUrl;
if (Array.isArray(bank)) {
sampleUrl = bank[n % bank.length];
} else {
if (!note) {
throw new Error('no note(...) set for sound', s);
}
const midiDiff = (noteA) => toMidi(noteA) - toMidi(note);
// object format will expect keys as notes
const closest = Object.keys(bank)
.filter((k) => !k.startsWith('_'))
.reduce(
(closest, key, j) => (!closest || Math.abs(midiDiff(key)) < Math.abs(midiDiff(closest)) ? key : closest),
null,
);
transpose = -midiDiff(closest); // semitones to repitch
sampleUrl = bank[closest][n % bank[closest].length];
}
const buffer = await loadBuffer(sampleUrl, ac); const buffer = await loadBuffer(sampleUrl, ac);
const bufferSource = ac.createBufferSource(); const bufferSource = ac.createBufferSource();
bufferSource.buffer = buffer; bufferSource.buffer = buffer;
const playbackRate = 1.0 * Math.pow(2, transpose / 12);
// bufferSource.playbackRate.value = Math.pow(2, transpose / 12);
bufferSource.playbackRate.value = playbackRate;
return bufferSource; return bufferSource;
}; };
const splitSN = (s, n) => {
if (!s.includes(':')) {
return [s, n];
}
let [s2, n2] = s.split(':');
if (isNaN(Number(n2))) {
return [s, n];
}
return [s2, n2];
};
Pattern.prototype.out = function () { Pattern.prototype.out = function () {
return this.onTrigger(async (t, hap, ct) => { return this.onTrigger(async (t, hap, ct) => {
const ac = getAudioContext(); const ac = getAudioContext();
@@ -96,7 +134,9 @@ Pattern.prototype.out = function () {
freq, freq,
s, s,
sf, sf,
clip = 0, // if 1, samples will be cut off when the hap ends
n = 0, n = 0,
note,
gain = 1, gain = 1,
cutoff, cutoff,
resonance = 1, resonance = 1,
@@ -106,19 +146,29 @@ Pattern.prototype.out = function () {
bandq = 1, bandq = 1,
pan, pan,
attack = 0.001, attack = 0.001,
decay = 0, decay = 0.05,
sustain = 1, sustain = 0.5,
release = 0.001, release = 0.001,
speed = 1, // sample playback speed speed = 1, // sample playback speed
begin = 0, begin = 0,
end = 1, end = 1,
} = hap.value; } = hap.value;
const { velocity = 1 } = hap.context;
gain *= velocity; // legacy fix for velocity
// the chain will hold all audio nodes that connect to each other // the chain will hold all audio nodes that connect to each other
const chain = []; const chain = [];
if (typeof n === 'string') { if (typeof s === 'string') {
n = toMidi(n); // e.g. c3 => 48 [s, n] = splitSN(s, n);
}
if (typeof note === 'string') {
[note, n] = splitSN(note, n);
} }
if (!s || ['sine', 'square', 'triangle', 'sawtooth'].includes(s)) { if (!s || ['sine', 'square', 'triangle', 'sawtooth'].includes(s)) {
// with synths, n and note are the same thing
n = note || n;
if (typeof n === 'string') {
n = toMidi(n); // e.g. c3 => 48
}
// get frequency // get frequency
if (!freq && typeof n === 'number') { if (!freq && typeof n === 'number') {
freq = fromMidi(n); // + 48); freq = fromMidi(n); // + 48);
@@ -128,7 +178,7 @@ Pattern.prototype.out = function () {
chain.push(o); chain.push(o);
// level down oscillators as they are really loud compared to samples i've tested // level down oscillators as they are really loud compared to samples i've tested
const g = ac.createGain(); const g = ac.createGain();
g.gain.value = 0.5; g.gain.value = 0.3;
chain.push(g); chain.push(g);
// TODO: make adsr work with samples without pops // TODO: make adsr work with samples without pops
// envelope // envelope
@@ -150,10 +200,10 @@ Pattern.prototype.out = function () {
try { try {
if (soundfont) { if (soundfont) {
// is soundfont // is soundfont
bufferSource = await globalThis.getFontBufferSource(soundfont, n, ac); bufferSource = await globalThis.getFontBufferSource(soundfont, note || n, ac);
} else { } else {
// is sample from loaded samples(..) // is sample from loaded samples(..)
bufferSource = await getSampleBufferSource(s, n); bufferSource = await getSampleBufferSource(s, n, note);
} }
} catch (err) { } catch (err) {
console.warn(err); console.warn(err);
@@ -170,27 +220,34 @@ Pattern.prototype.out = function () {
} }
bufferSource.playbackRate.value = Math.abs(speed) * bufferSource.playbackRate.value; bufferSource.playbackRate.value = Math.abs(speed) * bufferSource.playbackRate.value;
// TODO: nudge, unit, cut, loop // TODO: nudge, unit, cut, loop
let duration = soundfont ? hap.duration : bufferSource.buffer.duration; let duration = soundfont || clip ? hap.duration : bufferSource.buffer.duration;
// let duration = bufferSource.buffer.duration; // let duration = bufferSource.buffer.duration;
const offset = begin * duration; const offset = begin * duration;
duration = ((end - begin) * duration) / Math.abs(speed); duration = ((end - begin) * duration) / Math.abs(speed);
if (soundfont) { if (soundfont || clip) {
bufferSource.start(t, offset); // duration does not work here for some reason bufferSource.start(t, offset); // duration does not work here for some reason
} else { } else {
bufferSource.start(t, offset, duration); bufferSource.start(t, offset, duration);
} }
bufferSource.stop(t + duration);
chain.push(bufferSource); chain.push(bufferSource);
if (soundfont) { if (soundfont || clip) {
const env = ac.createGain(); const env = ac.createGain();
env.gain.value = 1; const releaseLength = 0.1;
const fadeLength = 0.1; env.gain.value = 0.6;
env.gain.value = 0.5; env.gain.setValueAtTime(env.gain.value, t + duration);
env.gain.setValueAtTime(0.5, t + duration - fadeLength); env.gain.linearRampToValueAtTime(0, t + duration + releaseLength);
env.gain.linearRampToValueAtTime(0, t + duration); // env.gain.linearRampToValueAtTime(0, t + duration + releaseLength);
chain.push(env); chain.push(env);
bufferSource.stop(t + duration + releaseLength);
} else {
bufferSource.stop(t + duration);
} }
} }
// master out
const master = ac.createGain();
master.gain.value = gain;
chain.push(master);
// filters // filters
cutoff !== undefined && chain.push(getFilter('lowpass', cutoff, resonance)); cutoff !== undefined && chain.push(getFilter('lowpass', cutoff, resonance));
hcutoff !== undefined && chain.push(getFilter('highpass', hcutoff, hresonance)); hcutoff !== undefined && chain.push(getFilter('highpass', hcutoff, hresonance));
@@ -204,9 +261,9 @@ Pattern.prototype.out = function () {
chain.push(panner); chain.push(panner);
} }
// master out // master out
const master = ac.createGain(); /* const master = ac.createGain();
master.gain.value = 0.8 * gain; master.gain.value = 0.8 * gain;
chain.push(master); chain.push(master); */
chain.push(ac.destination); chain.push(ac.destination);
// connect chain elements together // connect chain elements together
chain.slice(1).reduce((last, current) => last.connect(current), chain[0]); chain.slice(1).reduce((last, current) => last.connect(current), chain[0]);
+506 -10
View File
@@ -8,6 +8,8 @@
"name": "@strudel.cycles/repl", "name": "@strudel.cycles/repl",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@supabase/supabase-js": "^1.35.3",
"nanoid": "^4.0.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2" "react-dom": "^17.0.2"
}, },
@@ -509,6 +511,59 @@
"node": ">= 8.0.0" "node": ">= 8.0.0"
} }
}, },
"node_modules/@supabase/functions-js": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-1.3.3.tgz",
"integrity": "sha512-35vO9niHRtzGe1QSvXKdOfvGPiX2KC44dGpWU6y0/gZCfTIgog/soU9HqABzQC/maVowO3hGLWfez5aN0MKfow==",
"dependencies": {
"cross-fetch": "^3.1.5"
}
},
"node_modules/@supabase/gotrue-js": {
"version": "1.22.16",
"resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-1.22.16.tgz",
"integrity": "sha512-t/tR87anihvyc9ePk53NF2CG8yzTDiWOt0ReZpr7sRKV91sHNLbghVMsMDwPONWnVQ9V2/qfKutuAvPGTB/Dew==",
"dependencies": {
"cross-fetch": "^3.0.6"
}
},
"node_modules/@supabase/postgrest-js": {
"version": "0.37.3",
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-0.37.3.tgz",
"integrity": "sha512-Iqwv9D80YGkCi60Zl2lsV04WxOmjFqxpFmxoZ5xUqsVZHvIoAbJ9tMM3+0F7VkZZbsjnaYHrpJ58xLxU7cgy2w==",
"dependencies": {
"cross-fetch": "^3.1.5"
}
},
"node_modules/@supabase/realtime-js": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-1.7.2.tgz",
"integrity": "sha512-DMUaFIKj7KszGtWTTQbhMmUzZf7UnwYqySsmY+G8HgYxvY3ZaVa+DZD0I6ofgr4OLNr0po/ODM2a4lf5m5GNBg==",
"dependencies": {
"@types/phoenix": "^1.5.4",
"websocket": "^1.0.34"
}
},
"node_modules/@supabase/storage-js": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-1.7.1.tgz",
"integrity": "sha512-0ZlKlGgB3Qzhu07fts5pr2Y+c4xW58d7sDOB9m6nSfltS6SSfBPmqtdhU0zV9vy3vAjC74XeqUcpMhHP5E+aoA==",
"dependencies": {
"cross-fetch": "^3.1.0"
}
},
"node_modules/@supabase/supabase-js": {
"version": "1.35.3",
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-1.35.3.tgz",
"integrity": "sha512-uwO8OVdMFsGZNZ1xQhFz22+PSW0EWYZ5xVq+jQeGz8nhabEu+Q9Uyep/bcNzOpyPJRzbGfxSPRzgAdAxfJgFhw==",
"dependencies": {
"@supabase/functions-js": "^1.3.3",
"@supabase/gotrue-js": "^1.22.14",
"@supabase/postgrest-js": "^0.37.2",
"@supabase/realtime-js": "^1.7.2",
"@supabase/storage-js": "^1.7.0"
}
},
"node_modules/@tailwindcss/typography": { "node_modules/@tailwindcss/typography": {
"version": "0.5.2", "version": "0.5.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz",
@@ -523,6 +578,11 @@
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || insiders" "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || insiders"
} }
}, },
"node_modules/@types/phoenix": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.5.4.tgz",
"integrity": "sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ=="
},
"node_modules/@vitejs/plugin-react": { "node_modules/@vitejs/plugin-react": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-1.3.2.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-1.3.2.tgz",
@@ -688,6 +748,18 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
} }
}, },
"node_modules/bufferutil": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz",
"integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==",
"hasInstallScript": true,
"dependencies": {
"node-gyp-build": "^4.3.0"
},
"engines": {
"node": ">=6.14.2"
}
},
"node_modules/camelcase-css": { "node_modules/camelcase-css": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
@@ -790,6 +862,14 @@
"safe-buffer": "~5.1.1" "safe-buffer": "~5.1.1"
} }
}, },
"node_modules/cross-fetch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
"dependencies": {
"node-fetch": "2.6.7"
}
},
"node_modules/cssesc": { "node_modules/cssesc": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -802,6 +882,15 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"dependencies": {
"es5-ext": "^0.10.50",
"type": "^1.0.1"
}
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -860,6 +949,39 @@
"integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==",
"dev": true "dev": true
}, },
"node_modules/es5-ext": {
"version": "0.10.61",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz",
"integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==",
"hasInstallScript": true,
"dependencies": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"next-tick": "^1.1.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
"dependencies": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
"node_modules/es6-symbol": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
"dependencies": {
"d": "^1.0.1",
"ext": "^1.1.2"
}
},
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.14.39", "version": "0.14.39",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz",
@@ -1239,6 +1361,19 @@
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true "dev": true
}, },
"node_modules/ext": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
"integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
"dependencies": {
"type": "^2.5.0"
}
},
"node_modules/ext/node_modules/type": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
"integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ=="
},
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.11", "version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
@@ -1426,6 +1561,11 @@
"node": ">=0.12.0" "node": ">=0.12.0"
} }
}, },
"node_modules/is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -1528,15 +1668,48 @@
"dev": true "dev": true
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.4", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "integrity": "sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==",
"dev": true,
"bin": { "bin": {
"nanoid": "bin/nanoid.cjs" "nanoid": "bin/nanoid.js"
}, },
"engines": { "engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" "node": "^14 || ^16 || >=18"
}
},
"node_modules/next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
},
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-gyp-build": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz",
"integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==",
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
} }
}, },
"node_modules/node-releases": { "node_modules/node-releases": {
@@ -1714,6 +1887,18 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true "dev": true
}, },
"node_modules/postcss/node_modules/nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
"dev": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -1980,6 +2165,36 @@
"node": ">=8.0" "node": ">=8.0"
} }
}, },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"node_modules/typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"dependencies": {
"is-typedarray": "^1.0.0"
}
},
"node_modules/utf-8-validate": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz",
"integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==",
"hasInstallScript": true,
"dependencies": {
"node-gyp-build": "^4.3.0"
},
"engines": {
"node": ">=6.14.2"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -2023,6 +2238,49 @@
} }
} }
}, },
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/websocket": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz",
"integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==",
"dependencies": {
"bufferutil": "^4.0.1",
"debug": "^2.2.0",
"es5-ext": "^0.10.50",
"typedarray-to-buffer": "^3.1.5",
"utf-8-validate": "^5.0.2",
"yaeti": "^0.0.6"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/websocket/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/websocket/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/xtend": { "node_modules/xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -2032,6 +2290,14 @@
"node": ">=0.4" "node": ">=0.4"
} }
}, },
"node_modules/yaeti": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
"integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==",
"engines": {
"node": ">=0.10.32"
}
},
"node_modules/yaml": { "node_modules/yaml": {
"version": "1.10.2", "version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
@@ -2402,6 +2668,59 @@
"picomatch": "^2.2.2" "picomatch": "^2.2.2"
} }
}, },
"@supabase/functions-js": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-1.3.3.tgz",
"integrity": "sha512-35vO9niHRtzGe1QSvXKdOfvGPiX2KC44dGpWU6y0/gZCfTIgog/soU9HqABzQC/maVowO3hGLWfez5aN0MKfow==",
"requires": {
"cross-fetch": "^3.1.5"
}
},
"@supabase/gotrue-js": {
"version": "1.22.16",
"resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-1.22.16.tgz",
"integrity": "sha512-t/tR87anihvyc9ePk53NF2CG8yzTDiWOt0ReZpr7sRKV91sHNLbghVMsMDwPONWnVQ9V2/qfKutuAvPGTB/Dew==",
"requires": {
"cross-fetch": "^3.0.6"
}
},
"@supabase/postgrest-js": {
"version": "0.37.3",
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-0.37.3.tgz",
"integrity": "sha512-Iqwv9D80YGkCi60Zl2lsV04WxOmjFqxpFmxoZ5xUqsVZHvIoAbJ9tMM3+0F7VkZZbsjnaYHrpJ58xLxU7cgy2w==",
"requires": {
"cross-fetch": "^3.1.5"
}
},
"@supabase/realtime-js": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-1.7.2.tgz",
"integrity": "sha512-DMUaFIKj7KszGtWTTQbhMmUzZf7UnwYqySsmY+G8HgYxvY3ZaVa+DZD0I6ofgr4OLNr0po/ODM2a4lf5m5GNBg==",
"requires": {
"@types/phoenix": "^1.5.4",
"websocket": "^1.0.34"
}
},
"@supabase/storage-js": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-1.7.1.tgz",
"integrity": "sha512-0ZlKlGgB3Qzhu07fts5pr2Y+c4xW58d7sDOB9m6nSfltS6SSfBPmqtdhU0zV9vy3vAjC74XeqUcpMhHP5E+aoA==",
"requires": {
"cross-fetch": "^3.1.0"
}
},
"@supabase/supabase-js": {
"version": "1.35.3",
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-1.35.3.tgz",
"integrity": "sha512-uwO8OVdMFsGZNZ1xQhFz22+PSW0EWYZ5xVq+jQeGz8nhabEu+Q9Uyep/bcNzOpyPJRzbGfxSPRzgAdAxfJgFhw==",
"requires": {
"@supabase/functions-js": "^1.3.3",
"@supabase/gotrue-js": "^1.22.14",
"@supabase/postgrest-js": "^0.37.2",
"@supabase/realtime-js": "^1.7.2",
"@supabase/storage-js": "^1.7.0"
}
},
"@tailwindcss/typography": { "@tailwindcss/typography": {
"version": "0.5.2", "version": "0.5.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz",
@@ -2413,6 +2732,11 @@
"lodash.merge": "^4.6.2" "lodash.merge": "^4.6.2"
} }
}, },
"@types/phoenix": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.5.4.tgz",
"integrity": "sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ=="
},
"@vitejs/plugin-react": { "@vitejs/plugin-react": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-1.3.2.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-1.3.2.tgz",
@@ -2519,6 +2843,14 @@
"picocolors": "^1.0.0" "picocolors": "^1.0.0"
} }
}, },
"bufferutil": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz",
"integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==",
"requires": {
"node-gyp-build": "^4.3.0"
}
},
"camelcase-css": { "camelcase-css": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
@@ -2593,12 +2925,29 @@
"safe-buffer": "~5.1.1" "safe-buffer": "~5.1.1"
} }
}, },
"cross-fetch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
"requires": {
"node-fetch": "2.6.7"
}
},
"cssesc": { "cssesc": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true "dev": true
}, },
"d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"requires": {
"es5-ext": "^0.10.50",
"type": "^1.0.1"
}
},
"debug": { "debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -2643,6 +2992,35 @@
"integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==",
"dev": true "dev": true
}, },
"es5-ext": {
"version": "0.10.61",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz",
"integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==",
"requires": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"next-tick": "^1.1.0"
}
},
"es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
"requires": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
"es6-symbol": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
"requires": {
"d": "^1.0.1",
"ext": "^1.1.2"
}
},
"esbuild": { "esbuild": {
"version": "0.14.39", "version": "0.14.39",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz",
@@ -2829,6 +3207,21 @@
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true "dev": true
}, },
"ext": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
"integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
"requires": {
"type": "^2.5.0"
},
"dependencies": {
"type": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
"integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ=="
}
}
},
"fast-glob": { "fast-glob": {
"version": "3.2.11", "version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
@@ -2965,6 +3358,11 @@
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true "dev": true
}, },
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
"js-tokens": { "js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -3043,10 +3441,27 @@
"dev": true "dev": true
}, },
"nanoid": { "nanoid": {
"version": "3.3.4", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "integrity": "sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg=="
"dev": true },
"next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
},
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"node-gyp-build": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz",
"integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ=="
}, },
"node-releases": { "node-releases": {
"version": "2.0.4", "version": "2.0.4",
@@ -3104,6 +3519,14 @@
"nanoid": "^3.3.3", "nanoid": "^3.3.3",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"source-map-js": "^1.0.2" "source-map-js": "^1.0.2"
},
"dependencies": {
"nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
"dev": true
}
} }
}, },
"postcss-js": { "postcss-js": {
@@ -3325,6 +3748,32 @@
"is-number": "^7.0.0" "is-number": "^7.0.0"
} }
}, },
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"requires": {
"is-typedarray": "^1.0.0"
}
},
"utf-8-validate": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz",
"integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==",
"requires": {
"node-gyp-build": "^4.3.0"
}
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -3344,12 +3793,59 @@
"rollup": "^2.59.0" "rollup": "^2.59.0"
} }
}, },
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"websocket": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz",
"integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==",
"requires": {
"bufferutil": "^4.0.1",
"debug": "^2.2.0",
"es5-ext": "^0.10.50",
"typedarray-to-buffer": "^3.1.5",
"utf-8-validate": "^5.0.2",
"yaeti": "^0.0.6"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
}
}
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"dev": true "dev": true
}, },
"yaeti": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz",
"integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug=="
},
"yaml": { "yaml": {
"version": "1.10.2", "version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+2
View File
@@ -15,6 +15,8 @@
"static": "npx serve ../docs" "static": "npx serve ../docs"
}, },
"dependencies": { "dependencies": {
"@supabase/supabase-js": "^1.35.3",
"nanoid": "^4.0.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2" "react-dom": "^17.0.2"
}, },
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+83 -11
View File
@@ -6,15 +6,25 @@ This program is free software: you can redistribute it and/or modify it under th
import controls from '@strudel.cycles/core/controls.mjs'; import controls from '@strudel.cycles/core/controls.mjs';
import { evalScope, evaluate } from '@strudel.cycles/eval'; import { evalScope, evaluate } from '@strudel.cycles/eval';
import { CodeMirror, cx, useHighlighting, useRepl, useWebMidi } from '@strudel.cycles/react'; import { CodeMirror, cx, flash, useHighlighting, useRepl, useWebMidi } from '@strudel.cycles/react';
import { getDefaultSynth, cleanupDraw, cleanupUi, Tone } from '@strudel.cycles/tone'; import { getDefaultSynth, cleanupDraw, cleanupUi, Tone } from '@strudel.cycles/tone';
import React, { useCallback, useLayoutEffect, useRef, useState } from 'react'; import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import './App.css'; import './App.css';
import logo from './logo.svg'; import logo from './logo.svg';
import * as tunes from './tunes.mjs'; import * as tunes from './tunes.mjs';
import { prebake } from './prebake.mjs';
import * as WebDirt from 'WebDirt'; import * as WebDirt from 'WebDirt';
import { loadWebDirt } from '@strudel.cycles/webdirt'; import { loadWebDirt } from '@strudel.cycles/webdirt';
import { resetLoadedSamples, getAudioContext } from '@strudel.cycles/webaudio'; import { resetLoadedSamples, getAudioContext } from '@strudel.cycles/webaudio';
import { createClient } from '@supabase/supabase-js';
import { nanoid } from 'nanoid';
// Create a single supabase client for interacting with your database
const supabase = createClient(
'https://pidxdsxphlhzjnzmifth.supabase.co',
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBpZHhkc3hwaGxoempuem1pZnRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTYyMzA1NTYsImV4cCI6MTk3MTgwNjU1Nn0.bqlw7802fsWRnqU5BLYtmXk_k-D1VFmbkHMywWc15NM',
);
evalScope( evalScope(
Tone, Tone,
controls, controls,
@@ -37,13 +47,37 @@ loadWebDirt({
sampleFolder: 'EmuSP12', sampleFolder: 'EmuSP12',
}); });
const initialUrl = window.location.href; prebake();
const codeParam = window.location.href.split('#')[1];
let decoded; async function initCode() {
try { // load code from url hash (either short hash from database or decode long hash)
decoded = atob(decodeURIComponent(codeParam || '')); try {
} catch (err) { const initialUrl = window.location.href;
console.warn('failed to decode', err); const hash = initialUrl.split('?')[1]?.split('#')?.[0];
const codeParam = window.location.href.split('#')[1];
// looking like https://strudel.tidalcycles.org/?J01s5i1J0200 (fixed hash length)
if (codeParam) {
console.log('decode hash from url');
// looking like https://strudel.tidalcycles.org/#ImMzIGUzIg%3D%3D (hash length depends on code length)
return atob(decodeURIComponent(codeParam || ''));
} else if (hash) {
return supabase
.from('code')
.select('code')
.eq('hash', hash)
.then(({ data, error }) => {
if (error) {
console.warn('failed to load hash', err);
}
if (data.length) {
console.log('load hash from database', hash);
return data[0].code;
}
});
}
} catch (err) {
console.warn('failed to decode', err);
}
} }
function getRandomTune() { function getRandomTune() {
@@ -58,6 +92,7 @@ const isEmbedded = window.location !== window.parent.location;
function App() { function App() {
// const [editor, setEditor] = useState(); // const [editor, setEditor] = useState();
const [view, setView] = useState(); const [view, setView] = useState();
const [lastShared, setLastShared] = useState();
const { const {
setCode, setCode,
setPattern, setPattern,
@@ -74,9 +109,12 @@ function App() {
pushLog, pushLog,
pending, pending,
} = useRepl({ } = useRepl({
tune: decoded || randomTune, tune: '// LOADING...',
defaultSynth, defaultSynth,
}); });
useEffect(() => {
initCode().then((decoded) => setCode(decoded || randomTune));
}, []);
const logBox = useRef(); const logBox = useRef();
// scroll log box to bottom when log changes // scroll log box to bottom when log changes
useLayoutEffect(() => { useLayoutEffect(() => {
@@ -92,6 +130,7 @@ function App() {
if (e.ctrlKey || e.altKey) { if (e.ctrlKey || e.altKey) {
if (e.code === 'Enter') { if (e.code === 'Enter') {
e.preventDefault(); e.preventDefault();
flash(view);
await activateCode(); await activateCode();
} else if (e.code === 'Period') { } else if (e.code === 'Period') {
cycle.stop(); cycle.stop();
@@ -101,7 +140,7 @@ function App() {
}; };
window.addEventListener('keydown', handleKeyPress, true); window.addEventListener('keydown', handleKeyPress, true);
return () => window.removeEventListener('keydown', handleKeyPress, true); return () => window.removeEventListener('keydown', handleKeyPress, true);
}, [pattern, code, activateCode, cycle]); }, [pattern, code, activateCode, cycle, view]);
useHighlighting({ view, pattern, active: cycle.started && !activeCode?.includes('strudel disable-highlighting') }); useHighlighting({ view, pattern, active: cycle.started && !activeCode?.includes('strudel disable-highlighting') });
@@ -182,6 +221,7 @@ function App() {
cleanupDraw(); cleanupDraw();
cleanupUi(); cleanupUi();
resetLoadedSamples(); resetLoadedSamples();
prebake();
const parsed = await evaluate(_code); const parsed = await evaluate(_code);
setPattern(parsed.pattern); setPattern(parsed.pattern);
setActiveCode(_code); setActiveCode(_code);
@@ -195,6 +235,38 @@ function App() {
<a href="./tutorial">📚 tutorial</a> <a href="./tutorial">📚 tutorial</a>
</button> </button>
)} )}
{!isEmbedded && (
<button
className={cx('cursor-pointer hover:bg-gray-300', !isEmbedded ? 'p-2' : 'px-2')}
onClick={async () => {
const codeToShare = activeCode || code;
if (lastShared === codeToShare) {
// alert('Link already generated!');
pushLog(`Link already generated!`);
return;
}
// generate uuid in the browser
const hash = nanoid(12);
const { data, error } = await supabase.from('code').insert([{ code: codeToShare, hash }]);
if (!error) {
setLastShared(activeCode || code);
const shareUrl = window.location.origin + '?' + hash;
// copy shareUrl to clipboard
navigator.clipboard.writeText(shareUrl);
const message = `Link copied to clipboard: ${shareUrl}`;
// alert(message);
pushLog(message);
} else {
console.log('error', error);
const message = `Error: ${error.message}`;
// alert(message);
pushLog(message);
}
}}
>
📣 share{lastShared && lastShared === (activeCode || code) ? 'd!' : ''}
</button>
)}
{isEmbedded && ( {isEmbedded && (
<button className={cx('hover:bg-gray-300 px-2')}> <button className={cx('hover:bg-gray-300 px-2')}>
<a href={window.location.href} target="_blank" rel="noopener noreferrer" title="Open in REPL"> <a href={window.location.href} target="_blank" rel="noopener noreferrer" title="Open in REPL">
+57
View File
@@ -0,0 +1,57 @@
import { Pattern, toMidi } from '@strudel.cycles/core';
import { samples } from '@strudel.cycles/webaudio';
export function prebake() {
samples(
{
piano: {
A0: 'A0v8.mp3',
C1: 'C1v8.mp3',
Ds1: 'Ds1v8.mp3',
Fs1: 'Fs1v8.mp3',
A1: 'A1v8.mp3',
C2: 'C2v8.mp3',
Ds2: 'Ds2v8.mp3',
Fs2: 'Fs2v8.mp3',
A2: 'A2v8.mp3',
C3: 'C3v8.mp3',
Ds3: 'Ds3v8.mp3',
Fs3: 'Fs3v8.mp3',
A3: 'A3v8.mp3',
C4: 'C4v8.mp3',
Ds4: 'Ds4v8.mp3',
Fs4: 'Fs4v8.mp3',
A4: 'A4v8.mp3',
C5: 'C5v8.mp3',
Ds4: 'Ds4v8.mp3',
Fs5: 'Fs5v8.mp3',
A5: 'A5v8.mp3',
C6: 'C6v8.mp3',
Ds6: 'Ds6v8.mp3',
Fs6: 'Fs6v8.mp3',
A6: 'A6v8.mp3',
C7: 'C7v8.mp3',
Ds7: 'Ds7v8.mp3',
Fs7: 'Fs7v8.mp3',
A7: 'A7v8.mp3',
C8: 'C8v8.mp3',
},
},
// https://archive.org/details/SalamanderGrandPianoV3
// License: CC-by http://creativecommons.org/licenses/by/3.0/ Author: Alexander Holm
'./piano/',
);
}
const maxPan = toMidi('C8');
const panwidth = (pan, width) => pan * width + (1 - width) / 2;
Pattern.prototype.piano = function () {
return this.clip(1)
.s('piano')
.fmap((value) => {
// pan by pitch
const pan = panwidth(Math.min(toMidi(value.note) / maxPan, 1), 0.5);
return { ...value, pan: (value.pan || 1) * pan };
});
};
+3
View File
@@ -31,6 +31,8 @@ import '@strudel.cycles/xen/xen.mjs';
// import '@strudel.cycles/serial/serial.mjs'; // import '@strudel.cycles/serial/serial.mjs';
// import controls from '@strudel.cycles/core/controls.mjs'; // import controls from '@strudel.cycles/core/controls.mjs';
import { prebake } from './prebake.mjs';
class MockedNode { class MockedNode {
chain() { chain() {
return this; return this;
@@ -121,6 +123,7 @@ const uiHelpersMocked = {
backgroundImage: id, backgroundImage: id,
}; };
prebake();
// TODO: refactor to evalScope // TODO: refactor to evalScope
extend( extend(
+90 -38
View File
@@ -444,7 +444,7 @@ export const barryHarris = `backgroundImage(
.scale('C bebop major') .scale('C bebop major')
.transpose("<0 1 2 1>/8") .transpose("<0 1 2 1>/8")
.slow(2) .slow(2)
.tone((await piano()).toDestination()) .note().piano().out()
`; `;
export const blippyRhodes = `const delay = new FeedbackDelay(1/12, .4).chain(vol(0.3), out()); export const blippyRhodes = `const delay = new FeedbackDelay(1/12, .4).chain(vol(0.3), out());
@@ -551,7 +551,7 @@ export const risingEnemy = `stack(
.transpose("<0 1 2 1>/2".early(0.5)) .transpose("<0 1 2 1>/2".early(0.5))
.transpose(5) .transpose(5)
.fast(2 / 3) .fast(2 / 3)
.tone((await piano()).toDestination())`; .note().piano().out()`;
export const festivalOfFingers = `const chords = "<Cm7 Fm7 G7 F#7>"; export const festivalOfFingers = `const chords = "<Cm7 Fm7 G7 F#7>";
stack( stack(
@@ -563,7 +563,7 @@ stack(
.scaleTranspose("0 4 0 6".early(".125 .5")).layer(scaleTranspose("0,<2 [4,6] [5,7]>/4")) .scaleTranspose("0 4 0 6".early(".125 .5")).layer(scaleTranspose("0,<2 [4,6] [5,7]>/4"))
).slow(2) ).slow(2)
.velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8)) .velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8))
.tone((await piano()).chain(out()))`; .note().piano().out()`;
export const festivalOfFingers2 = `const chords = "<Cm7 Fm7 G7 F#7 >"; export const festivalOfFingers2 = `const chords = "<Cm7 Fm7 G7 F#7 >";
const scales = cat('C minor','F dorian','G dorian','F# mixolydian') const scales = cat('C minor','F dorian','G dorian','F# mixolydian')
@@ -577,36 +577,35 @@ stack(
).slow(2).transpose(-1) ).slow(2).transpose(-1)
.legato(cosine.struct("x*8").add(4/5).mul(4/5).fast(8)) .legato(cosine.struct("x*8").add(4/5).mul(4/5).fast(8))
.velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8)) .velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8))
.tone((await piano()).chain(out())).fast(3/4)`; .note().piano().out().fast(3/4)`;
// iter, stut, stutWith // iter, echo, echoWith
export const undergroundPlumber = `backgroundImage('https://images.nintendolife.com/news/2016/08/video_exploring_the_funky_inspiration_for_the_super_mario_bros_underground_theme/large.jpg',{ className:'darken' }) export const undergroundPlumber = `backgroundImage('https://images.nintendolife.com/news/2016/08/video_exploring_the_funky_inspiration_for_the_super_mario_bros_underground_theme/large.jpg',{ className:'darken' })
const drums = await players({ samples({ bd: 'bd/BT0A0D0.wav', sn: 'sn/ST0T0S3.wav', hh: 'hh/000_hh3closedhh.wav', cp: 'cp/HANDCLP0.wav',
bd: 'bd/BT0A0D0.wav',
sn: 'sn/ST0T0S3.wav',
hh: 'hh/000_hh3closedhh.wav',
cp: 'cp/HANDCLP0.wav',
}, 'https://loophole-letters.vercel.app/samples/tidal/') }, 'https://loophole-letters.vercel.app/samples/tidal/')
stack(
"<<bd*2 bd> sn> hh".fast(4).slow(2).tone(drums.chain(vol(.5),out())),
stack(
"[c2 a1 bb1 ~] ~"
.stut(2, .6, 1/16)
.legato(.4)
.slow(2)
.tone(synth({...osc('sawtooth7'),...adsr(0,.3,0)}).chain(out())),
"[g2,[c3 eb3]]".iter(4)
.stutWith(4, 1/8, (x,n)=>x.transpose(n*12).velocity(Math.pow(.4,n)))
.legato(.1)
)
.transpose("<0@2 5 0 7 5 0 -5>/2")
)
.fast(2/3)
.pianoroll({minMidi:21,maxMidi:180, background:'transparent',inactive:'#3F8F90',active:'#DE3123'})`;
export const bridgeIsOver = `const breaks = (await players({mad:'https://freesound.org/data/previews/22/22274_109943-lq.mp3'})).chain(out()) const h = x=>x.transpose("<0@2 5 0 7 5 0 -5>/2")
stack(
s("<<bd*2 bd> sn> hh").fast(2).gain(.7),
"[c2 a1 bb1 ~] ~"
.echo(2, 1/16, 1)
.legato(.4)
.slow(2)
.layer(h)
.note().s('square')
.cutoff(400).decay(.12).sustain(0)
,
"[g2,[c3 eb3]]".iter(4)
.echoWith(4, 1/8, (x,n)=>x.transpose(n*12).velocity(Math.pow(.4,n)))
.legato(.1)
.layer(h).note()
).out()
.fast(2/3)
.pianoroll({})`;
export const bridgeIsOver = `samples({mad:'https://freesound.org/data/previews/22/22274_109943-lq.mp3'})
stack( stack(
stack( stack(
"c3*2 [[c3@1.4 bb2] ab2] gb2*2 <[[gb2@1.4 ab2] bb2] gb2>".legato(".5 1".fast(2)).velocity(.8), "c3*2 [[c3@1.4 bb2] ab2] gb2*2 <[[gb2@1.4 ab2] bb2] gb2>".legato(".5 1".fast(2)).velocity(.8),
@@ -618,9 +617,11 @@ stack(
.velocity(.7) .velocity(.7)
.legato(.5) .legato(.5)
.stut(3, .5, 1/8) .stut(3, .5, 1/8)
).transpose(-1).tone((await piano()).chain(out())), ).transpose(-1).note().piano(),
"mad".slow(2).tone(breaks) s("mad").slow(2)
).cpm(78).slow(4).pianoroll() ).cpm(78).slow(4)
.out()
.pianoroll()
`; `;
export const goodTimes = `const scale = cat('C3 dorian','Bb2 major').slow(4); export const goodTimes = `const scale = cat('C3 dorian','Bb2 major').slow(4);
@@ -637,10 +638,9 @@ stack(
.legato("2") .legato("2")
.scale(scale) .scale(scale)
.scaleTranspose("<0>".slow(4)) .scaleTranspose("<0>".slow(4))
.tone((await piano()).chain(out()))
//.midi()
.velocity(.8)
.transpose(5) .transpose(5)
.note().piano().out()
.velocity(.8)
.slow(2) .slow(2)
.pianoroll({maxMidi:100,minMidi:20})`; .pianoroll({maxMidi:100,minMidi:20})`;
@@ -651,7 +651,7 @@ export const echoPiano = `"<0 2 [4 6](3,4,1) 3*2>"
.off(1/2, x=>x.scaleTranspose(6).color('steelblue')) .off(1/2, x=>x.scaleTranspose(6).color('steelblue'))
.legato(.5) .legato(.5)
.echo(4, 1/8, .5) .echo(4, 1/8, .5)
.tone((await piano()).chain(out())) .note().piano().out()
.pianoroll()`; .pianoroll()`;
export const sml1 = ` export const sml1 = `
@@ -687,7 +687,7 @@ stack(
f3!2 e3!2 ab3!2 ~!2 f3!2 e3!2 ab3!2 ~!2
>\` >\`
.legato(.5) .legato(.5)
).fast(2) //.tone((await piano()).chain(out()))`; ).fast(2) // .note().piano().out()`;
export const speakerman = `backgroundImage('https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi.ytimg.com%2Fvi%2FXR0rKqW3VwY%2Fmaxresdefault.jpg&f=1&nofb=1', export const speakerman = `backgroundImage('https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi.ytimg.com%2Fvi%2FXR0rKqW3VwY%2Fmaxresdefault.jpg&f=1&nofb=1',
{ className:'darken', style:'background-size:cover'}) { className:'darken', style:'background-size:cover'})
@@ -827,7 +827,7 @@ export const festivalOfFingers3 = `"[-7*3],0,2,6,[8 7]"
.scale(cat('D dorian','G mixolydian','C dorian','F mixolydian')) .scale(cat('D dorian','G mixolydian','C dorian','F mixolydian'))
.legato(1) .legato(1)
.slow(2) .slow(2)
.tone((await piano()).toDestination()) .note().piano().out()
//.pianoroll({maxMidi:160})`; //.pianoroll({maxMidi:160})`;
export const bossa = ` export const bossa = `
@@ -835,7 +835,7 @@ const scales = sequence('C minor', ['D locrian', 'G phrygian'], 'Bb2 minor', ['C
stack( stack(
"<Cm7 [Dm7b5 G7b9] Bbm7 [Cm7b5 F7b9]>".fast(2).struct("x ~ x@3 x ~ x ~ ~ ~ x ~ x@3".late(1/8)).early(1/8).slow(2).voicings(), "<Cm7 [Dm7b5 G7b9] Bbm7 [Cm7b5 F7b9]>".fast(2).struct("x ~ x@3 x ~ x ~ ~ ~ x ~ x@3".late(1/8)).early(1/8).slow(2).voicings(),
"[~ [0 ~]] 0 [~ [4 ~]] 4".sub(7).restart(scales).scale(scales).early(.25) "[~ [0 ~]] 0 [~ [4 ~]] 4".sub(7).restart(scales).scale(scales).early(.25)
).tone((await piano()).toDestination()).slow(2)`; ).note().piano().out().slow(2)`;
export const customTrigger = `stack( export const customTrigger = `stack(
freq("55 [110,165] 110 [220,275]".mul("<1 <3/4 2/3>>").struct("x(3,8)").layer(x=>x.mul("1.006,.995"))), freq("55 [110,165] 110 [220,275]".mul("<1 <3/4 2/3>>").struct("x(3,8)").layer(x=>x.mul("1.006,.995"))),
@@ -967,3 +967,55 @@ export const swimmingWithSoundfonts = `stack(
).s('Acoustic Bass: Bass') ).s('Acoustic Bass: Bass')
).slow(51) ).slow(51)
.out()`; .out()`;
export const outroMusic = `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'],
perc: ['perc/002_perc2.wav'],
}, 'github:tidalcycles/Dirt-Samples/master/');
"C^7 Am7 Dm7 G7".slow(2).voicings()
.stack("0@6 [<1 2> <2 0> 1]@2".scale('C5 major'))
.n().slow(4)
.s('0040_FluidR3_GM_sf2_file')
.color('steelblue')
.stack(
"<-7 ~@2 [~@2 -7] -9 ~@2 [~@2 -9] -10!2 ~ [~@2 -10] -5 ~ [-3 -2 -10]@2>*2".scale('C3 major')
.n().s('sawtooth').color('brown')
)
.attack(0.05).decay(.1).sustain(.7)
.cutoff(perlin.range(800,2000))
.gain(.3)
.stack(
s("<bd!3 [bd ~ bd]> sd,hh*3,~@5 <perc perc*3>")
.speed(perlin.range(.9,1.1))
.n(3).color('gray')
).slow(3/2)
//.pianoroll({autorange:1,vertical:1,fold:0})
.out()`;
export const bassFuge = `samples({ flbass: ['00_c2_finger_long_neck.wav','01_c2_finger_short_neck.wav','02_c2_finger_long_bridge.wav','03_c2_finger_short_bridge.wav','04_c2_pick_long.wav','05_c2_pick_short.wav','06_c2_palm_mute.wav'] },
'github:cleary/samples-flbass/main/')
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/master/');
note("<8(3,8) <7 7*2> [4 5@3] 8>".sub(1) // sub 1 -> 1-indexed
.layer(
x=>x,
x=>x.add(7).color('steelblue')
.off(1/8,x=>x.add("2,4").off(1/8,x=>x.add(5).echo(4,.125,.5)))
.slow(2),
).scale('A1 minor'))
.s("flbass").n(0)
.gain(.3)
.cutoff(sine.slow(7).range(200,4000))
.resonance(10)
//.hcutoff(400)
.clip(1)
.stack(s("bd:1*2,~ sd:0,[~ hh:0]*2"))
.out()
.pianoroll({vertical:1})`;
File diff suppressed because one or more lines are too long