mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 21:58:37 +00:00
Merge pull request #148 from tidalcycles/webaudio-optimizations
Sampler optimizations and more
This commit is contained in:
commit
8a1cd32d50
152
package-lock.json
generated
152
package-lock.json
generated
@ -8504,6 +8504,31 @@
|
||||
"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": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
@ -9901,6 +9926,15 @@
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
@ -11339,7 +11373,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@strudel.cycles/core",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.2",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"bjork": "^0.0.1",
|
||||
@ -11351,15 +11385,15 @@
|
||||
},
|
||||
"packages/embed": {
|
||||
"name": "@strudel.cycles/embed",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"license": "AGPL-3.0-or-later"
|
||||
},
|
||||
"packages/eval": {
|
||||
"name": "@strudel.cycles/eval",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"estraverse": "^5.3.0",
|
||||
"shift-ast": "^6.1.0",
|
||||
"shift-codegen": "^7.0.3",
|
||||
@ -11383,27 +11417,30 @@
|
||||
},
|
||||
"packages/midi": {
|
||||
"name": "@strudel.cycles/midi",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/tone": "^0.1.1",
|
||||
"@strudel.cycles/tone": "^0.1.3",
|
||||
"tone": "^14.7.77",
|
||||
"webmidi": "^2.5.2"
|
||||
}
|
||||
},
|
||||
"packages/mini": {
|
||||
"name": "@strudel.cycles/mini",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/eval": "^0.1.1",
|
||||
"@strudel.cycles/tone": "^0.1.1"
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@strudel.cycles/eval": "^0.1.3",
|
||||
"@strudel.cycles/tone": "^0.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"peggy": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"packages/osc": {
|
||||
"name": "@strudel.cycles/osc",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"osc-js": "^2.3.2"
|
||||
@ -11411,14 +11448,14 @@
|
||||
},
|
||||
"packages/react": {
|
||||
"name": "@strudel.cycles/react",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.4",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@codemirror/lang-javascript": "^0.19.0",
|
||||
"@strudel.cycles/core": "*",
|
||||
"@strudel.cycles/eval": "^0.1.1",
|
||||
"@strudel.cycles/tone": "^0.1.1",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@strudel.cycles/eval": "^0.1.3",
|
||||
"@strudel.cycles/tone": "^0.1.3",
|
||||
"react-codemirror6": "^1.1.0",
|
||||
"react-hook-inview": "^4.5.0"
|
||||
},
|
||||
@ -11487,16 +11524,16 @@
|
||||
},
|
||||
"packages/serial": {
|
||||
"name": "@strudel.cycles/serial",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.3",
|
||||
"license": "AGPL-3.0-or-later"
|
||||
},
|
||||
"packages/soundfonts": {
|
||||
"name": "@strudel.cycles/soundfonts",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "*",
|
||||
"@strudel.cycles/webaudio": "*"
|
||||
"@strudel.cycles/webaudio": "^0.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"node-fetch": "^3.2.6"
|
||||
@ -11522,10 +11559,10 @@
|
||||
},
|
||||
"packages/tonal": {
|
||||
"name": "@strudel.cycles/tonal",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@tonaljs/tonal": "^4.6.5",
|
||||
"webmidi": "^3.0.15"
|
||||
}
|
||||
@ -11547,10 +11584,10 @@
|
||||
},
|
||||
"packages/tone": {
|
||||
"name": "@strudel.cycles/tone",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@tonejs/piano": "^0.2.1",
|
||||
"chord-voicings": "^0.0.1",
|
||||
"tone": "^14.7.77"
|
||||
@ -11558,27 +11595,27 @@
|
||||
},
|
||||
"packages/webaudio": {
|
||||
"name": "@strudel.cycles/webaudio",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.4",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.1.0"
|
||||
"@strudel.cycles/core": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"packages/webdirt": {
|
||||
"name": "@strudel.cycles/webdirt",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.2",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"WebDirt": "github:dktr0/WebDirt"
|
||||
}
|
||||
},
|
||||
"packages/xen": {
|
||||
"name": "@strudel.cycles/xen",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.3",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@strudel.cycles/core": "^0.1.0"
|
||||
"@strudel.cycles/core": "^0.1.2"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -13393,7 +13430,7 @@
|
||||
"@strudel.cycles/eval": {
|
||||
"version": "file:packages/eval",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"estraverse": "^5.3.0",
|
||||
"shift-ast": "^6.1.0",
|
||||
"shift-codegen": "^7.0.3",
|
||||
@ -13405,7 +13442,7 @@
|
||||
"@strudel.cycles/midi": {
|
||||
"version": "file:packages/midi",
|
||||
"requires": {
|
||||
"@strudel.cycles/tone": "^0.1.1",
|
||||
"@strudel.cycles/tone": "^0.1.3",
|
||||
"tone": "^14.7.77",
|
||||
"webmidi": "^2.5.2"
|
||||
}
|
||||
@ -13413,9 +13450,10 @@
|
||||
"@strudel.cycles/mini": {
|
||||
"version": "file:packages/mini",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/eval": "^0.1.1",
|
||||
"@strudel.cycles/tone": "^0.1.1"
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@strudel.cycles/eval": "^0.1.3",
|
||||
"@strudel.cycles/tone": "^0.1.3",
|
||||
"peggy": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"@strudel.cycles/osc": {
|
||||
@ -13428,9 +13466,9 @@
|
||||
"version": "file:packages/react",
|
||||
"requires": {
|
||||
"@codemirror/lang-javascript": "^0.19.0",
|
||||
"@strudel.cycles/core": "*",
|
||||
"@strudel.cycles/eval": "^0.1.1",
|
||||
"@strudel.cycles/tone": "^0.1.1",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@strudel.cycles/eval": "^0.1.3",
|
||||
"@strudel.cycles/tone": "^0.1.3",
|
||||
"@types/react": "^17.0.2",
|
||||
"@types/react-dom": "^17.0.2",
|
||||
"@vitejs/plugin-react": "^1.3.0",
|
||||
@ -13494,7 +13532,7 @@
|
||||
"version": "file:packages/soundfonts",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "*",
|
||||
"@strudel.cycles/webaudio": "*",
|
||||
"@strudel.cycles/webaudio": "^0.1.4",
|
||||
"node-fetch": "^3.2.6"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -13514,7 +13552,7 @@
|
||||
"@strudel.cycles/tonal": {
|
||||
"version": "file:packages/tonal",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@tonaljs/tonal": "^4.6.5",
|
||||
"webmidi": "^3.0.15"
|
||||
},
|
||||
@ -13534,7 +13572,7 @@
|
||||
"@strudel.cycles/tone": {
|
||||
"version": "file:packages/tone",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@tonejs/piano": "^0.2.1",
|
||||
"chord-voicings": "^0.0.1",
|
||||
"tone": "^14.7.77"
|
||||
@ -13543,20 +13581,20 @@
|
||||
"@strudel.cycles/webaudio": {
|
||||
"version": "file:packages/webaudio",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.1.0"
|
||||
"@strudel.cycles/core": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"@strudel.cycles/webdirt": {
|
||||
"version": "file:packages/webdirt",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.1.0",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"WebDirt": "github:dktr0/WebDirt"
|
||||
}
|
||||
},
|
||||
"@strudel.cycles/xen": {
|
||||
"version": "file:packages/xen",
|
||||
"requires": {
|
||||
"@strudel.cycles/core": "^0.1.0"
|
||||
"@strudel.cycles/core": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"@tonaljs/abc-notation": {
|
||||
@ -18292,6 +18330,24 @@
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"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": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
@ -18544,9 +18600,9 @@
|
||||
"version": "file:packages/react",
|
||||
"requires": {
|
||||
"@codemirror/lang-javascript": "^0.19.0",
|
||||
"@strudel.cycles/core": "*",
|
||||
"@strudel.cycles/eval": "^0.1.1",
|
||||
"@strudel.cycles/tone": "^0.1.1",
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@strudel.cycles/eval": "^0.1.3",
|
||||
"@strudel.cycles/tone": "^0.1.3",
|
||||
"@types/react": "^17.0.2",
|
||||
"@types/react-dom": "^17.0.2",
|
||||
"@vitejs/plugin-react": "^1.3.0",
|
||||
@ -19410,6 +19466,12 @@
|
||||
"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": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
|
||||
@ -744,6 +744,7 @@ const generic_params = [
|
||||
['f', 'uid', ''],
|
||||
['f', 'val', ''],
|
||||
['f', 'cps', ''],
|
||||
['f', 'clip', ''],
|
||||
];
|
||||
|
||||
// TODO: slice / splice https://www.youtube.com/watch?v=hKhPdO0RKDQ&list=PL2lW1zNIIwj3bDkh-Y3LUGDuRcoUigoDs&index=13
|
||||
|
||||
@ -16,4 +16,18 @@ export * from './timespan.mjs';
|
||||
export * from './util.mjs';
|
||||
export * from './speak.mjs';
|
||||
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;
|
||||
|
||||
@ -15,6 +15,7 @@ import drawLine from './drawLine.mjs';
|
||||
|
||||
/** @class Class representing a 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.
|
||||
*
|
||||
@ -1212,7 +1213,15 @@ export function pure(value) {
|
||||
|
||||
export function isPattern(thing) {
|
||||
// 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) {
|
||||
@ -1389,7 +1398,7 @@ export function pr(args) {
|
||||
}
|
||||
|
||||
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 chunkBack = curry((a, pat) => pat.chunkBack(a));
|
||||
export const div = curry((a, pat) => pat.div(a));
|
||||
|
||||
@ -10,7 +10,7 @@ export const tokenizeNote = (note) => {
|
||||
if (typeof note !== 'string') {
|
||||
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) {
|
||||
return [];
|
||||
}
|
||||
@ -24,7 +24,7 @@ export const toMidi = (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 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;
|
||||
};
|
||||
export const fromMidi = (n) => {
|
||||
|
||||
@ -1,10 +1,4 @@
|
||||
/*
|
||||
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.
|
||||
// Generated by Peggy 2.0.1.
|
||||
//
|
||||
// https://peggyjs.org/
|
||||
|
||||
@ -16,6 +10,7 @@ function peg$subclass(child, parent) {
|
||||
|
||||
function peg$SyntaxError(message, expected, found, location) {
|
||||
var self = Error.call(this, message);
|
||||
// istanbul ignore next Check is a necessary evil to support older environments
|
||||
if (Object.setPrototypeOf) {
|
||||
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;
|
||||
if (src) {
|
||||
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 last = s.line === e.line ? e.column : line.length + 1;
|
||||
var hatLen = (last - s.column) || 1;
|
||||
str += "\n --> " + loc + "\n"
|
||||
+ filler + " |\n"
|
||||
+ s.line + " | " + line + "\n"
|
||||
+ filler + " | " + peg$padEnd("", s.column - 1)
|
||||
+ peg$padEnd("", last - s.column, "^");
|
||||
+ filler + " | " + peg$padEnd("", s.column - 1, ' ')
|
||||
+ peg$padEnd("", hatLen, "^");
|
||||
} else {
|
||||
str += "\n at " + loc;
|
||||
}
|
||||
@ -79,7 +75,7 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
||||
: classEscape(part);
|
||||
});
|
||||
|
||||
return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
|
||||
return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
|
||||
},
|
||||
|
||||
any: function() {
|
||||
@ -185,31 +181,32 @@ function peg$parse(input, options) {
|
||||
var peg$c7 = "#";
|
||||
var peg$c8 = "^";
|
||||
var peg$c9 = "_";
|
||||
var peg$c10 = "[";
|
||||
var peg$c11 = "]";
|
||||
var peg$c12 = "<";
|
||||
var peg$c13 = ">";
|
||||
var peg$c14 = "@";
|
||||
var peg$c15 = "!";
|
||||
var peg$c16 = "(";
|
||||
var peg$c17 = ")";
|
||||
var peg$c18 = "/";
|
||||
var peg$c19 = "*";
|
||||
var peg$c20 = "%";
|
||||
var peg$c21 = "struct";
|
||||
var peg$c22 = "target";
|
||||
var peg$c23 = "euclid";
|
||||
var peg$c24 = "slow";
|
||||
var peg$c25 = "rotL";
|
||||
var peg$c26 = "rotR";
|
||||
var peg$c27 = "fast";
|
||||
var peg$c28 = "scale";
|
||||
var peg$c29 = "//";
|
||||
var peg$c30 = "cat";
|
||||
var peg$c31 = "$";
|
||||
var peg$c32 = "setcps";
|
||||
var peg$c33 = "setbpm";
|
||||
var peg$c34 = "hush";
|
||||
var peg$c10 = ":";
|
||||
var peg$c11 = "[";
|
||||
var peg$c12 = "]";
|
||||
var peg$c13 = "<";
|
||||
var peg$c14 = ">";
|
||||
var peg$c15 = "@";
|
||||
var peg$c16 = "!";
|
||||
var peg$c17 = "(";
|
||||
var peg$c18 = ")";
|
||||
var peg$c19 = "/";
|
||||
var peg$c20 = "*";
|
||||
var peg$c21 = "%";
|
||||
var peg$c22 = "struct";
|
||||
var peg$c23 = "target";
|
||||
var peg$c24 = "euclid";
|
||||
var peg$c25 = "slow";
|
||||
var peg$c26 = "rotL";
|
||||
var peg$c27 = "rotR";
|
||||
var peg$c28 = "fast";
|
||||
var peg$c29 = "scale";
|
||||
var peg$c30 = "//";
|
||||
var peg$c31 = "cat";
|
||||
var peg$c32 = "$";
|
||||
var peg$c33 = "setcps";
|
||||
var peg$c34 = "setbpm";
|
||||
var peg$c35 = "hush";
|
||||
|
||||
var peg$r0 = /^[1-9]/;
|
||||
var peg$r1 = /^[eE]/;
|
||||
@ -235,32 +232,33 @@ function peg$parse(input, options) {
|
||||
var peg$e14 = peg$literalExpectation("#", false);
|
||||
var peg$e15 = peg$literalExpectation("^", false);
|
||||
var peg$e16 = peg$literalExpectation("_", false);
|
||||
var peg$e17 = peg$literalExpectation("[", false);
|
||||
var peg$e18 = peg$literalExpectation("]", false);
|
||||
var peg$e19 = peg$literalExpectation("<", false);
|
||||
var peg$e20 = peg$literalExpectation(">", false);
|
||||
var peg$e21 = peg$literalExpectation("@", false);
|
||||
var peg$e22 = peg$literalExpectation("!", false);
|
||||
var peg$e23 = peg$literalExpectation("(", false);
|
||||
var peg$e24 = peg$literalExpectation(")", false);
|
||||
var peg$e25 = peg$literalExpectation("/", false);
|
||||
var peg$e26 = peg$literalExpectation("*", false);
|
||||
var peg$e27 = peg$literalExpectation("%", false);
|
||||
var peg$e28 = peg$literalExpectation("struct", false);
|
||||
var peg$e29 = peg$literalExpectation("target", false);
|
||||
var peg$e30 = peg$literalExpectation("euclid", false);
|
||||
var peg$e31 = peg$literalExpectation("slow", false);
|
||||
var peg$e32 = peg$literalExpectation("rotL", false);
|
||||
var peg$e33 = peg$literalExpectation("rotR", false);
|
||||
var peg$e34 = peg$literalExpectation("fast", false);
|
||||
var peg$e35 = peg$literalExpectation("scale", false);
|
||||
var peg$e36 = peg$literalExpectation("//", false);
|
||||
var peg$e37 = peg$classExpectation(["\n"], true, false);
|
||||
var peg$e38 = peg$literalExpectation("cat", false);
|
||||
var peg$e39 = peg$literalExpectation("$", false);
|
||||
var peg$e40 = peg$literalExpectation("setcps", false);
|
||||
var peg$e41 = peg$literalExpectation("setbpm", false);
|
||||
var peg$e42 = peg$literalExpectation("hush", false);
|
||||
var peg$e17 = peg$literalExpectation(":", false);
|
||||
var peg$e18 = peg$literalExpectation("[", false);
|
||||
var peg$e19 = peg$literalExpectation("]", false);
|
||||
var peg$e20 = peg$literalExpectation("<", false);
|
||||
var peg$e21 = peg$literalExpectation(">", false);
|
||||
var peg$e22 = peg$literalExpectation("@", false);
|
||||
var peg$e23 = peg$literalExpectation("!", false);
|
||||
var peg$e24 = peg$literalExpectation("(", false);
|
||||
var peg$e25 = peg$literalExpectation(")", false);
|
||||
var peg$e26 = peg$literalExpectation("/", false);
|
||||
var peg$e27 = peg$literalExpectation("*", false);
|
||||
var peg$e28 = peg$literalExpectation("%", false);
|
||||
var peg$e29 = peg$literalExpectation("struct", false);
|
||||
var peg$e30 = peg$literalExpectation("target", false);
|
||||
var peg$e31 = peg$literalExpectation("euclid", false);
|
||||
var peg$e32 = peg$literalExpectation("slow", false);
|
||||
var peg$e33 = peg$literalExpectation("rotL", false);
|
||||
var peg$e34 = peg$literalExpectation("rotR", false);
|
||||
var peg$e35 = peg$literalExpectation("fast", false);
|
||||
var peg$e36 = peg$literalExpectation("scale", false);
|
||||
var peg$e37 = peg$literalExpectation("//", false);
|
||||
var peg$e38 = peg$classExpectation(["\n"], true, false);
|
||||
var peg$e39 = peg$literalExpectation("cat", false);
|
||||
var peg$e40 = peg$literalExpectation("$", false);
|
||||
var peg$e41 = peg$literalExpectation("setcps", false);
|
||||
var peg$e42 = peg$literalExpectation("setbpm", false);
|
||||
var peg$e43 = peg$literalExpectation("hush", false);
|
||||
|
||||
var peg$f0 = function() { return parseFloat(text()); };
|
||||
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$f30 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})};
|
||||
var peg$f31 = function() { return new CommandStub("hush")};
|
||||
|
||||
var peg$currPos = 0;
|
||||
var peg$savedPos = 0;
|
||||
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
||||
@ -810,6 +807,15 @@ function peg$parse(input, options) {
|
||||
s0 = peg$FAILED;
|
||||
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;
|
||||
s1 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 91) {
|
||||
s2 = peg$c10;
|
||||
s2 = peg$c11;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s2 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e17); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parsews();
|
||||
@ -864,11 +870,11 @@ function peg$parse(input, options) {
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 93) {
|
||||
s6 = peg$c11;
|
||||
s6 = peg$c12;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s6 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
||||
}
|
||||
if (s6 !== peg$FAILED) {
|
||||
s7 = peg$parsews();
|
||||
@ -896,11 +902,11 @@ function peg$parse(input, options) {
|
||||
s0 = peg$currPos;
|
||||
s1 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 60) {
|
||||
s2 = peg$c12;
|
||||
s2 = peg$c13;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s2 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = peg$parsews();
|
||||
@ -908,11 +914,11 @@ function peg$parse(input, options) {
|
||||
if (s4 !== peg$FAILED) {
|
||||
s5 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 62) {
|
||||
s6 = peg$c13;
|
||||
s6 = peg$c14;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s6 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
||||
}
|
||||
if (s6 !== peg$FAILED) {
|
||||
s7 = peg$parsews();
|
||||
@ -976,11 +982,11 @@ function peg$parse(input, options) {
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 64) {
|
||||
s1 = peg$c14;
|
||||
s1 = peg$c15;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e22); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsenumber();
|
||||
@ -1004,11 +1010,11 @@ function peg$parse(input, options) {
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 33) {
|
||||
s1 = peg$c15;
|
||||
s1 = peg$c16;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e22); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e23); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsenumber();
|
||||
@ -1032,11 +1038,11 @@ function peg$parse(input, options) {
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 40) {
|
||||
s1 = peg$c16;
|
||||
s1 = peg$c17;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e23); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e24); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1060,11 +1066,11 @@ function peg$parse(input, options) {
|
||||
}
|
||||
s12 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 41) {
|
||||
s13 = peg$c17;
|
||||
s13 = peg$c18;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s13 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e24); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
||||
}
|
||||
if (s13 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
@ -1098,11 +1104,11 @@ function peg$parse(input, options) {
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 47) {
|
||||
s1 = peg$c18;
|
||||
s1 = peg$c19;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e26); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsenumber();
|
||||
@ -1126,11 +1132,11 @@ function peg$parse(input, options) {
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 42) {
|
||||
s1 = peg$c19;
|
||||
s1 = peg$c20;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e26); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsenumber();
|
||||
@ -1154,11 +1160,11 @@ function peg$parse(input, options) {
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.charCodeAt(peg$currPos) === 37) {
|
||||
s1 = peg$c20;
|
||||
s1 = peg$c21;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e28); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsenumber();
|
||||
@ -1332,12 +1338,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c21) {
|
||||
s1 = peg$c21;
|
||||
if (input.substr(peg$currPos, 6) === peg$c22) {
|
||||
s1 = peg$c22;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e28); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e29); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1361,12 +1367,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3, s4, s5;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c22) {
|
||||
s1 = peg$c22;
|
||||
if (input.substr(peg$currPos, 6) === peg$c23) {
|
||||
s1 = peg$c23;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e29); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1402,12 +1408,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3, s4, s5, s6, s7;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c23) {
|
||||
s1 = peg$c23;
|
||||
if (input.substr(peg$currPos, 6) === peg$c24) {
|
||||
s1 = peg$c24;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1443,12 +1449,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c24) {
|
||||
s1 = peg$c24;
|
||||
if (input.substr(peg$currPos, 4) === peg$c25) {
|
||||
s1 = peg$c25;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e32); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1472,12 +1478,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c25) {
|
||||
s1 = peg$c25;
|
||||
if (input.substr(peg$currPos, 4) === peg$c26) {
|
||||
s1 = peg$c26;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e32); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1501,12 +1507,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c26) {
|
||||
s1 = peg$c26;
|
||||
if (input.substr(peg$currPos, 4) === peg$c27) {
|
||||
s1 = peg$c27;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e34); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1530,12 +1536,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c27) {
|
||||
s1 = peg$c27;
|
||||
if (input.substr(peg$currPos, 4) === peg$c28) {
|
||||
s1 = peg$c28;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e34); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1559,12 +1565,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3, s4, s5;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 5) === peg$c28) {
|
||||
s1 = peg$c28;
|
||||
if (input.substr(peg$currPos, 5) === peg$c29) {
|
||||
s1 = peg$c29;
|
||||
peg$currPos += 5;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e36); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1609,12 +1615,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 2) === peg$c29) {
|
||||
s1 = peg$c29;
|
||||
if (input.substr(peg$currPos, 2) === peg$c30) {
|
||||
s1 = peg$c30;
|
||||
peg$currPos += 2;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e36); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e37); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = [];
|
||||
@ -1623,7 +1629,7 @@ function peg$parse(input, options) {
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e37); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e38); }
|
||||
}
|
||||
while (s3 !== peg$FAILED) {
|
||||
s2.push(s3);
|
||||
@ -1632,7 +1638,7 @@ function peg$parse(input, options) {
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e37); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e38); }
|
||||
}
|
||||
}
|
||||
s1 = [s1, s2];
|
||||
@ -1649,21 +1655,21 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 3) === peg$c30) {
|
||||
s1 = peg$c30;
|
||||
if (input.substr(peg$currPos, 3) === peg$c31) {
|
||||
s1 = peg$c31;
|
||||
peg$currPos += 3;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e38); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e39); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 91) {
|
||||
s3 = peg$c10;
|
||||
s3 = peg$c11;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e17); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parsews();
|
||||
@ -1705,11 +1711,11 @@ function peg$parse(input, options) {
|
||||
}
|
||||
s7 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 93) {
|
||||
s8 = peg$c11;
|
||||
s8 = peg$c12;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s8 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
||||
}
|
||||
if (s8 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
@ -1770,11 +1776,11 @@ function peg$parse(input, options) {
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
if (input.charCodeAt(peg$currPos) === 36) {
|
||||
s3 = peg$c31;
|
||||
s3 = peg$c32;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e39); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
s4 = peg$parsews();
|
||||
@ -1852,12 +1858,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c32) {
|
||||
s1 = peg$c32;
|
||||
if (input.substr(peg$currPos, 6) === peg$c33) {
|
||||
s1 = peg$c33;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1881,12 +1887,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1, s2, s3;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c33) {
|
||||
s1 = peg$c33;
|
||||
if (input.substr(peg$currPos, 6) === peg$c34) {
|
||||
s1 = peg$c34;
|
||||
peg$currPos += 6;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = peg$parsews();
|
||||
@ -1910,12 +1916,12 @@ function peg$parse(input, options) {
|
||||
var s0, s1;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 4) === peg$c34) {
|
||||
s1 = peg$c34;
|
||||
if (input.substr(peg$currPos, 4) === peg$c35) {
|
||||
s1 = peg$c35;
|
||||
peg$currPos += 4;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e43); }
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
@ -1938,35 +1944,34 @@ function peg$parse(input, options) {
|
||||
}
|
||||
|
||||
|
||||
var PatternStub = function(source, alignment)
|
||||
{
|
||||
this.type_ = "pattern";
|
||||
this.arguments_ = { alignment : alignment};
|
||||
this.source_ = source;
|
||||
}
|
||||
var PatternStub = function(source, alignment)
|
||||
{
|
||||
this.type_ = "pattern";
|
||||
this.arguments_ = { alignment : alignment};
|
||||
this.source_ = source;
|
||||
}
|
||||
|
||||
var OperatorStub = function(name, args, source)
|
||||
{
|
||||
this.type_ = name;
|
||||
this.arguments_ = args;
|
||||
this.source_ = source;
|
||||
}
|
||||
var OperatorStub = function(name, args, source)
|
||||
{
|
||||
this.type_ = name;
|
||||
this.arguments_ = args;
|
||||
this.source_ = source;
|
||||
}
|
||||
|
||||
var ElementStub = function(source, options)
|
||||
{
|
||||
this.type_ = "element";
|
||||
this.source_ = source;
|
||||
this.options_ = options;
|
||||
this.location_ = location();
|
||||
}
|
||||
|
||||
var CommandStub = function(name, options)
|
||||
{
|
||||
this.type_ = "command";
|
||||
this.name_ = name;
|
||||
this.options_ = options;
|
||||
}
|
||||
var ElementStub = function(source, options)
|
||||
{
|
||||
this.type_ = "element";
|
||||
this.source_ = source;
|
||||
this.options_ = options;
|
||||
this.location_ = location();
|
||||
}
|
||||
|
||||
var CommandStub = function(name, options)
|
||||
{
|
||||
this.type_ = "command";
|
||||
this.name_ = name;
|
||||
this.options_ = options;
|
||||
}
|
||||
|
||||
|
||||
peg$result = peg$startRuleFunction();
|
||||
@ -1990,5 +1995,6 @@ function peg$parse(input, options) {
|
||||
|
||||
export {
|
||||
peg$SyntaxError as SyntaxError,
|
||||
|
||||
peg$parse as parse
|
||||
};
|
||||
|
||||
@ -87,7 +87,7 @@ quote = '"' / "'"
|
||||
// ------------------ steps and cycles ---------------------------
|
||||
|
||||
// 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("") }
|
||||
|
||||
// define a sub cycle e.g. [1 2, 3 [4]]
|
||||
|
||||
1031
packages/mini/package-lock.json
generated
Normal file
1031
packages/mini/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,8 @@
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "mocha --colors"
|
||||
"test": "mocha --colors",
|
||||
"build:parser": "peggy -o krill-parser.js --format es ./krill.pegjs"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -28,5 +29,8 @@
|
||||
"@strudel.cycles/core": "^0.1.2",
|
||||
"@strudel.cycles/eval": "^0.1.3",
|
||||
"@strudel.cycles/tone": "^0.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"peggy": "^2.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,9 @@ async function loadFont(name) {
|
||||
}
|
||||
|
||||
export async function getFontBufferSource(name, pitch, ac) {
|
||||
if (typeof pitch === 'string') {
|
||||
pitch = toMidi(pitch);
|
||||
}
|
||||
const { buffer, zone } = await getFontPitch(name, pitch, ac);
|
||||
const src = ac.createBufferSource();
|
||||
src.buffer = buffer;
|
||||
|
||||
@ -8,7 +8,7 @@ import { Pattern } from '@strudel.cycles/core';
|
||||
|
||||
const scale = (normalized, min, max) => normalized * (max - min) + min;
|
||||
const getValue = (e) => {
|
||||
let value = typeof e.value === 'object' ? e.value.n : e.value;
|
||||
let value = typeof e.value === 'object' ? e.value.note ?? e.value.n : e.value;
|
||||
if (typeof value === 'string') {
|
||||
value = toMidi(value);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
...Object.fromEntries(
|
||||
Object.entries(sampleMap).map(([key, value]) => [
|
||||
key,
|
||||
(typeof value === 'string' ? [value] : value).map((v) =>
|
||||
(baseUrl + v).replace('github:', 'https://raw.githubusercontent.com/'),
|
||||
),
|
||||
]),
|
||||
Object.entries(sampleMap).map(([key, value]) => {
|
||||
if (typeof value === 'string') {
|
||||
value = [value];
|
||||
}
|
||||
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)];
|
||||
}),
|
||||
),
|
||||
];
|
||||
}),
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
@ -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 * as strudel from '@strudel.cycles/core';
|
||||
import { fromMidi } from '@strudel.cycles/core';
|
||||
import { fromMidi, toMidi } from '@strudel.cycles/core';
|
||||
import { loadBuffer } from './sampler.mjs';
|
||||
const { Pattern } = strudel;
|
||||
|
||||
@ -68,7 +68,11 @@ const getSoundfontKey = (s) => {
|
||||
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();
|
||||
// is sample from loaded samples(..)
|
||||
const samples = getLoadedSamples();
|
||||
@ -79,13 +83,47 @@ const getSampleBufferSource = async (s, n) => {
|
||||
if (!bank) {
|
||||
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 bufferSource = ac.createBufferSource();
|
||||
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;
|
||||
};
|
||||
|
||||
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 () {
|
||||
return this.onTrigger(async (t, hap, ct) => {
|
||||
const ac = getAudioContext();
|
||||
@ -96,7 +134,9 @@ Pattern.prototype.out = function () {
|
||||
freq,
|
||||
s,
|
||||
sf,
|
||||
clip = 0, // if 1, samples will be cut off when the hap ends
|
||||
n = 0,
|
||||
note,
|
||||
gain = 1,
|
||||
cutoff,
|
||||
resonance = 1,
|
||||
@ -106,19 +146,29 @@ Pattern.prototype.out = function () {
|
||||
bandq = 1,
|
||||
pan,
|
||||
attack = 0.001,
|
||||
decay = 0,
|
||||
sustain = 1,
|
||||
decay = 0.05,
|
||||
sustain = 0.5,
|
||||
release = 0.001,
|
||||
speed = 1, // sample playback speed
|
||||
begin = 0,
|
||||
end = 1,
|
||||
} = 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
|
||||
const chain = [];
|
||||
if (typeof n === 'string') {
|
||||
n = toMidi(n); // e.g. c3 => 48
|
||||
if (typeof s === 'string') {
|
||||
[s, n] = splitSN(s, n);
|
||||
}
|
||||
if (typeof note === 'string') {
|
||||
[note, n] = splitSN(note, n);
|
||||
}
|
||||
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
|
||||
if (!freq && typeof n === 'number') {
|
||||
freq = fromMidi(n); // + 48);
|
||||
@ -128,7 +178,7 @@ Pattern.prototype.out = function () {
|
||||
chain.push(o);
|
||||
// level down oscillators as they are really loud compared to samples i've tested
|
||||
const g = ac.createGain();
|
||||
g.gain.value = 0.5;
|
||||
g.gain.value = 0.3;
|
||||
chain.push(g);
|
||||
// TODO: make adsr work with samples without pops
|
||||
// envelope
|
||||
@ -150,10 +200,10 @@ Pattern.prototype.out = function () {
|
||||
try {
|
||||
if (soundfont) {
|
||||
// is soundfont
|
||||
bufferSource = await globalThis.getFontBufferSource(soundfont, n, ac);
|
||||
bufferSource = await globalThis.getFontBufferSource(soundfont, note || n, ac);
|
||||
} else {
|
||||
// is sample from loaded samples(..)
|
||||
bufferSource = await getSampleBufferSource(s, n);
|
||||
bufferSource = await getSampleBufferSource(s, n, note);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
@ -170,27 +220,34 @@ Pattern.prototype.out = function () {
|
||||
}
|
||||
bufferSource.playbackRate.value = Math.abs(speed) * bufferSource.playbackRate.value;
|
||||
// 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;
|
||||
const offset = begin * duration;
|
||||
duration = ((end - begin) * duration) / Math.abs(speed);
|
||||
if (soundfont) {
|
||||
if (soundfont || clip) {
|
||||
bufferSource.start(t, offset); // duration does not work here for some reason
|
||||
} else {
|
||||
bufferSource.start(t, offset, duration);
|
||||
}
|
||||
bufferSource.stop(t + duration);
|
||||
chain.push(bufferSource);
|
||||
if (soundfont) {
|
||||
if (soundfont || clip) {
|
||||
const env = ac.createGain();
|
||||
env.gain.value = 1;
|
||||
const fadeLength = 0.1;
|
||||
env.gain.value = 0.5;
|
||||
env.gain.setValueAtTime(0.5, t + duration - fadeLength);
|
||||
env.gain.linearRampToValueAtTime(0, t + duration);
|
||||
const releaseLength = 0.1;
|
||||
env.gain.value = 0.6;
|
||||
env.gain.setValueAtTime(env.gain.value, t + duration);
|
||||
env.gain.linearRampToValueAtTime(0, t + duration + releaseLength);
|
||||
// env.gain.linearRampToValueAtTime(0, t + duration + releaseLength);
|
||||
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
|
||||
cutoff !== undefined && chain.push(getFilter('lowpass', cutoff, resonance));
|
||||
hcutoff !== undefined && chain.push(getFilter('highpass', hcutoff, hresonance));
|
||||
@ -204,9 +261,9 @@ Pattern.prototype.out = function () {
|
||||
chain.push(panner);
|
||||
}
|
||||
// master out
|
||||
const master = ac.createGain();
|
||||
/* const master = ac.createGain();
|
||||
master.gain.value = 0.8 * gain;
|
||||
chain.push(master);
|
||||
chain.push(master); */
|
||||
chain.push(ac.destination);
|
||||
// connect chain elements together
|
||||
chain.slice(1).reduce((last, current) => last.connect(current), chain[0]);
|
||||
|
||||
BIN
repl/public/piano/A0v8.mp3
Normal file
BIN
repl/public/piano/A0v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/A1v8.mp3
Normal file
BIN
repl/public/piano/A1v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/A2v8.mp3
Normal file
BIN
repl/public/piano/A2v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/A3v8.mp3
Normal file
BIN
repl/public/piano/A3v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/A4v8.mp3
Normal file
BIN
repl/public/piano/A4v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/A5v8.mp3
Normal file
BIN
repl/public/piano/A5v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/A6v8.mp3
Normal file
BIN
repl/public/piano/A6v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/A7v8.mp3
Normal file
BIN
repl/public/piano/A7v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/C1v8.mp3
Normal file
BIN
repl/public/piano/C1v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/C2v8.mp3
Normal file
BIN
repl/public/piano/C2v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/C3v8.mp3
Normal file
BIN
repl/public/piano/C3v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/C4v8.mp3
Normal file
BIN
repl/public/piano/C4v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/C5v8.mp3
Normal file
BIN
repl/public/piano/C5v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/C6v8.mp3
Normal file
BIN
repl/public/piano/C6v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/C7v8.mp3
Normal file
BIN
repl/public/piano/C7v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/C8v8.mp3
Normal file
BIN
repl/public/piano/C8v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Ds1v8.mp3
Normal file
BIN
repl/public/piano/Ds1v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Ds2v8.mp3
Normal file
BIN
repl/public/piano/Ds2v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Ds3v8.mp3
Normal file
BIN
repl/public/piano/Ds3v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Ds4v8.mp3
Normal file
BIN
repl/public/piano/Ds4v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Ds5v8.mp3
Normal file
BIN
repl/public/piano/Ds5v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Ds6v8.mp3
Normal file
BIN
repl/public/piano/Ds6v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Ds7v8.mp3
Normal file
BIN
repl/public/piano/Ds7v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Fs1v8.mp3
Normal file
BIN
repl/public/piano/Fs1v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Fs2v8.mp3
Normal file
BIN
repl/public/piano/Fs2v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Fs3v8.mp3
Normal file
BIN
repl/public/piano/Fs3v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Fs4v8.mp3
Normal file
BIN
repl/public/piano/Fs4v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Fs5v8.mp3
Normal file
BIN
repl/public/piano/Fs5v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Fs6v8.mp3
Normal file
BIN
repl/public/piano/Fs6v8.mp3
Normal file
Binary file not shown.
BIN
repl/public/piano/Fs7v8.mp3
Normal file
BIN
repl/public/piano/Fs7v8.mp3
Normal file
Binary file not shown.
@ -12,6 +12,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from
|
||||
import './App.css';
|
||||
import logo from './logo.svg';
|
||||
import * as tunes from './tunes.mjs';
|
||||
import { prebake } from './prebake.mjs';
|
||||
import * as WebDirt from 'WebDirt';
|
||||
import { loadWebDirt } from '@strudel.cycles/webdirt';
|
||||
import { resetLoadedSamples, getAudioContext } from '@strudel.cycles/webaudio';
|
||||
@ -46,6 +47,8 @@ loadWebDirt({
|
||||
sampleFolder: 'EmuSP12',
|
||||
});
|
||||
|
||||
prebake();
|
||||
|
||||
async function initCode() {
|
||||
// load code from url hash (either short hash from database or decode long hash)
|
||||
try {
|
||||
@ -218,6 +221,7 @@ function App() {
|
||||
cleanupDraw();
|
||||
cleanupUi();
|
||||
resetLoadedSamples();
|
||||
prebake();
|
||||
const parsed = await evaluate(_code);
|
||||
setPattern(parsed.pattern);
|
||||
setActiveCode(_code);
|
||||
|
||||
57
repl/src/prebake.mjs
Normal file
57
repl/src/prebake.mjs
Normal 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 };
|
||||
});
|
||||
};
|
||||
@ -31,6 +31,8 @@ import '@strudel.cycles/xen/xen.mjs';
|
||||
// import '@strudel.cycles/serial/serial.mjs';
|
||||
// import controls from '@strudel.cycles/core/controls.mjs';
|
||||
|
||||
import { prebake } from './prebake.mjs';
|
||||
|
||||
class MockedNode {
|
||||
chain() {
|
||||
return this;
|
||||
@ -121,6 +123,7 @@ const uiHelpersMocked = {
|
||||
backgroundImage: id,
|
||||
};
|
||||
|
||||
prebake();
|
||||
|
||||
// TODO: refactor to evalScope
|
||||
extend(
|
||||
|
||||
@ -444,7 +444,7 @@ export const barryHarris = `backgroundImage(
|
||||
.scale('C bebop major')
|
||||
.transpose("<0 1 2 1>/8")
|
||||
.slow(2)
|
||||
.tone((await piano()).toDestination())
|
||||
.note().piano().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(5)
|
||||
.fast(2 / 3)
|
||||
.tone((await piano()).toDestination())`;
|
||||
.note().piano().out()`;
|
||||
|
||||
export const festivalOfFingers = `const chords = "<Cm7 Fm7 G7 F#7>";
|
||||
stack(
|
||||
@ -563,7 +563,7 @@ stack(
|
||||
.scaleTranspose("0 4 0 6".early(".125 .5")).layer(scaleTranspose("0,<2 [4,6] [5,7]>/4"))
|
||||
).slow(2)
|
||||
.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 >";
|
||||
const scales = cat('C minor','F dorian','G dorian','F# mixolydian')
|
||||
@ -577,36 +577,35 @@ stack(
|
||||
).slow(2).transpose(-1)
|
||||
.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))
|
||||
.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' })
|
||||
|
||||
const drums = await players({
|
||||
bd: 'bd/BT0A0D0.wav',
|
||||
sn: 'sn/ST0T0S3.wav',
|
||||
hh: 'hh/000_hh3closedhh.wav',
|
||||
cp: 'cp/HANDCLP0.wav',
|
||||
samples({ bd: 'bd/BT0A0D0.wav', sn: 'sn/ST0T0S3.wav', hh: 'hh/000_hh3closedhh.wav', cp: 'cp/HANDCLP0.wav',
|
||||
}, '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(
|
||||
"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)
|
||||
.legato(.5)
|
||||
.stut(3, .5, 1/8)
|
||||
).transpose(-1).tone((await piano()).chain(out())),
|
||||
"mad".slow(2).tone(breaks)
|
||||
).cpm(78).slow(4).pianoroll()
|
||||
).transpose(-1).note().piano(),
|
||||
s("mad").slow(2)
|
||||
).cpm(78).slow(4)
|
||||
.out()
|
||||
.pianoroll()
|
||||
`;
|
||||
|
||||
export const goodTimes = `const scale = cat('C3 dorian','Bb2 major').slow(4);
|
||||
@ -637,10 +638,9 @@ stack(
|
||||
.legato("2")
|
||||
.scale(scale)
|
||||
.scaleTranspose("<0>".slow(4))
|
||||
.tone((await piano()).chain(out()))
|
||||
//.midi()
|
||||
.velocity(.8)
|
||||
.transpose(5)
|
||||
.note().piano().out()
|
||||
.velocity(.8)
|
||||
.slow(2)
|
||||
.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'))
|
||||
.legato(.5)
|
||||
.echo(4, 1/8, .5)
|
||||
.tone((await piano()).chain(out()))
|
||||
.note().piano().out()
|
||||
.pianoroll()`;
|
||||
|
||||
export const sml1 = `
|
||||
@ -687,7 +687,7 @@ stack(
|
||||
f3!2 e3!2 ab3!2 ~!2
|
||||
>\`
|
||||
.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',
|
||||
{ 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'))
|
||||
.legato(1)
|
||||
.slow(2)
|
||||
.tone((await piano()).toDestination())
|
||||
.note().piano().out()
|
||||
//.pianoroll({maxMidi:160})`;
|
||||
|
||||
export const bossa = `
|
||||
@ -835,7 +835,7 @@ const scales = sequence('C minor', ['D locrian', 'G phrygian'], 'Bb2 minor', ['C
|
||||
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(),
|
||||
"[~ [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(
|
||||
freq("55 [110,165] 110 [220,275]".mul("<1 <3/4 2/3>>").struct("x(3,8)").layer(x=>x.mul("1.006,.995"))),
|
||||
@ -994,3 +994,28 @@ export const outroMusic = `samples({
|
||||
).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
Loading…
x
Reference in New Issue
Block a user