This commit is contained in:
Felix Roos 2022-02-16 20:13:40 +01:00
parent b8d3fe6f1a
commit f97837d15a
10 changed files with 526 additions and 295 deletions

View File

@ -178,30 +178,32 @@ function peg$parse(input, options) {
var peg$c6 = "'"; var peg$c6 = "'";
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 = "struct"; var peg$c19 = "*";
var peg$c20 = "target"; var peg$c20 = "%";
var peg$c21 = "euclid"; var peg$c21 = "struct";
var peg$c22 = "slow"; var peg$c22 = "target";
var peg$c23 = "rotL"; var peg$c23 = "euclid";
var peg$c24 = "rotR"; var peg$c24 = "slow";
var peg$c25 = "fast"; var peg$c25 = "rotL";
var peg$c26 = "scale"; var peg$c26 = "rotR";
var peg$c27 = "//"; var peg$c27 = "fast";
var peg$c28 = "cat"; var peg$c28 = "scale";
var peg$c29 = "$"; var peg$c29 = "//";
var peg$c30 = "setcps"; var peg$c30 = "cat";
var peg$c31 = "setbpm"; var peg$c31 = "$";
var peg$c32 = "hush"; var peg$c32 = "setcps";
var peg$c33 = "setbpm";
var peg$c34 = "hush";
var peg$r0 = /^[1-9]/; var peg$r0 = /^[1-9]/;
var peg$r1 = /^[eE]/; var peg$r1 = /^[eE]/;
@ -226,63 +228,66 @@ function peg$parse(input, options) {
var peg$e13 = peg$classExpectation([["0", "9"], ["a", "z"], ["A", "Z"], "~"], false, false); var peg$e13 = peg$classExpectation([["0", "9"], ["a", "z"], ["A", "Z"], "~"], false, false);
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("struct", false); var peg$e26 = peg$literalExpectation("*", false);
var peg$e27 = peg$literalExpectation("target", false); var peg$e27 = peg$literalExpectation("%", false);
var peg$e28 = peg$literalExpectation("euclid", false); var peg$e28 = peg$literalExpectation("struct", false);
var peg$e29 = peg$literalExpectation("slow", false); var peg$e29 = peg$literalExpectation("target", false);
var peg$e30 = peg$literalExpectation("rotL", false); var peg$e30 = peg$literalExpectation("euclid", false);
var peg$e31 = peg$literalExpectation("rotR", false); var peg$e31 = peg$literalExpectation("slow", false);
var peg$e32 = peg$literalExpectation("fast", false); var peg$e32 = peg$literalExpectation("rotL", false);
var peg$e33 = peg$literalExpectation("scale", false); var peg$e33 = peg$literalExpectation("rotR", false);
var peg$e34 = peg$literalExpectation("//", false); var peg$e34 = peg$literalExpectation("fast", false);
var peg$e35 = peg$classExpectation(["\n"], true, false); var peg$e35 = peg$literalExpectation("scale", false);
var peg$e36 = peg$literalExpectation("cat", false); var peg$e36 = peg$literalExpectation("//", false);
var peg$e37 = peg$literalExpectation("$", false); var peg$e37 = peg$classExpectation(["\n"], true, false);
var peg$e38 = peg$literalExpectation("setcps", false); var peg$e38 = peg$literalExpectation("cat", false);
var peg$e39 = peg$literalExpectation("setbpm", false); var peg$e39 = peg$literalExpectation("$", false);
var peg$e40 = peg$literalExpectation("hush", false); var peg$e40 = peg$literalExpectation("setcps", false);
var peg$e41 = peg$literalExpectation("setbpm", false);
var peg$e42 = 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("") };
var peg$f2 = function(s) { return s}; var peg$f2 = function(s) { return s};
var peg$f3 = function(sc) { sc.arguments_.alignment = "t"; return sc;}; var peg$f3 = function(sc) { sc.arguments_.alignment = "t"; return sc;};
var peg$f4 = function(a) { return { weight: a} }; var peg$f4 = function(a) { return { weight: a} };
var peg$f5 = function(p, s) { return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s } } } }; var peg$f5 = function(a) { return { replicate: a } };
var peg$f6 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:a } } } }; var peg$f6 = function(p, s) { return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s } } } };
var peg$f7 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:"1/"+a } } } }; var peg$f7 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:a } } } };
var peg$f8 = function(a) { return { operator : { type_: "fixed-step", arguments_ :{ amount:a } } } }; var peg$f8 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:"1/"+a } } } };
var peg$f9 = function(s, o) { return new ElementStub(s, o);}; var peg$f9 = function(a) { return { operator : { type_: "fixed-step", arguments_ :{ amount:a } } } };
var peg$f10 = function(s) { return new PatternStub(s,"h"); }; var peg$f10 = function(s, o) { return new ElementStub(s, o);};
var peg$f11 = function(c, v) { return v}; var peg$f11 = function(s) { return new PatternStub(s,"h"); };
var peg$f12 = function(c, cs) { if (cs.length == 0 && c instanceof Object) { return c;} else { cs.unshift(c); return new PatternStub(cs,"v");} }; var peg$f12 = function(c, v) { return v};
var peg$f13 = function(s) { return s; }; var peg$f13 = function(c, cs) { if (cs.length == 0 && c instanceof Object) { return c;} else { cs.unshift(c); return new PatternStub(cs,"v");} };
var peg$f14 = function(s) { return { name: "struct", args: { sequence:s }}}; var peg$f14 = function(s) { return s; };
var peg$f15 = function(s) { return { name: "target", args : { name:s}}}; var peg$f15 = function(s) { return { name: "struct", args: { sequence:s }}};
var peg$f16 = function(p, s) { return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}}; var peg$f16 = function(s) { return { name: "target", args : { name:s}}};
var peg$f17 = function(a) { return { name: "stretch", args :{ amount: a}}}; var peg$f17 = function(p, s) { return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}};
var peg$f18 = function(a) { return { name: "shift", args :{ amount: "-"+a}}}; var peg$f18 = function(a) { return { name: "stretch", args :{ amount: a}}};
var peg$f19 = function(a) { return { name: "shift", args :{ amount: a}}}; var peg$f19 = function(a) { return { name: "shift", args :{ amount: "-"+a}}};
var peg$f20 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}}; var peg$f20 = function(a) { return { name: "shift", args :{ amount: a}}};
var peg$f21 = function(s) { return { name: "scale", args :{ scale: s.join("")}}}; var peg$f21 = function(a) { return { name: "stretch", args :{ amount: "1/"+a}}};
var peg$f22 = function(s, v) { return v}; var peg$f22 = function(s) { return { name: "scale", args :{ scale: s.join("")}}};
var peg$f23 = function(s, ss) { ss.unshift(s); return new PatternStub(ss,"t"); }; var peg$f23 = function(s, v) { return v};
var peg$f24 = function(sg) {return sg}; var peg$f24 = function(s, ss) { ss.unshift(s); return new PatternStub(ss,"t"); };
var peg$f25 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)}; var peg$f25 = function(sg) {return sg};
var peg$f26 = function(sc) { return sc }; var peg$f26 = function(o, soc) { return new OperatorStub(o.name,o.args,soc)};
var peg$f27 = function(c) { return c }; var peg$f27 = function(sc) { return sc };
var peg$f28 = function(v) { return new CommandStub("setcps", { value: v})}; var peg$f28 = function(c) { return c };
var peg$f29 = function(v) { return new CommandStub("setcps", { value: (v/120/2)})}; var peg$f29 = function(v) { return new CommandStub("setcps", { value: v})};
var peg$f30 = function() { return new CommandStub("hush")}; 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$currPos = 0;
var peg$savedPos = 0; var peg$savedPos = 0;
@ -791,6 +796,15 @@ function peg$parse(input, options) {
s0 = peg$FAILED; s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e15); } if (peg$silentFails === 0) { peg$fail(peg$e15); }
} }
if (s0 === peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 95) {
s0 = peg$c9;
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e16); }
}
}
} }
} }
} }
@ -832,11 +846,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$c9; s2 = peg$c10;
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e16); } if (peg$silentFails === 0) { peg$fail(peg$e17); }
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s3 = peg$parsews(); s3 = peg$parsews();
@ -844,11 +858,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$c10; s6 = peg$c11;
peg$currPos++; peg$currPos++;
} else { } else {
s6 = peg$FAILED; s6 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e17); } if (peg$silentFails === 0) { peg$fail(peg$e18); }
} }
if (s6 !== peg$FAILED) { if (s6 !== peg$FAILED) {
s7 = peg$parsews(); s7 = peg$parsews();
@ -876,11 +890,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$c11; s2 = peg$c12;
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e18); } if (peg$silentFails === 0) { peg$fail(peg$e19); }
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s3 = peg$parsews(); s3 = peg$parsews();
@ -888,11 +902,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$c12; s6 = peg$c13;
peg$currPos++; peg$currPos++;
} else { } else {
s6 = peg$FAILED; s6 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e19); } if (peg$silentFails === 0) { peg$fail(peg$e20); }
} }
if (s6 !== peg$FAILED) { if (s6 !== peg$FAILED) {
s7 = peg$parsews(); s7 = peg$parsews();
@ -940,6 +954,9 @@ function peg$parse(input, options) {
s0 = peg$parseslice_fast(); s0 = peg$parseslice_fast();
if (s0 === peg$FAILED) { if (s0 === peg$FAILED) {
s0 = peg$parseslice_fixed_step(); s0 = peg$parseslice_fixed_step();
if (s0 === peg$FAILED) {
s0 = peg$parseslice_replicate();
}
} }
} }
} }
@ -953,11 +970,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$c13; s1 = peg$c14;
peg$currPos++; peg$currPos++;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e20); } if (peg$silentFails === 0) { peg$fail(peg$e21); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsenumber(); s2 = peg$parsenumber();
@ -976,16 +993,44 @@ function peg$parse(input, options) {
return s0; return s0;
} }
function peg$parseslice_replicate() {
var s0, s1, s2;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 33) {
s1 = peg$c15;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e22); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsenumber();
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f5(s2);
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parseslice_bjorklund() { function peg$parseslice_bjorklund() {
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.charCodeAt(peg$currPos) === 40) { if (input.charCodeAt(peg$currPos) === 40) {
s1 = peg$c14; s1 = peg$c16;
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$e23); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@ -999,15 +1044,15 @@ function peg$parse(input, options) {
if (s7 !== peg$FAILED) { if (s7 !== peg$FAILED) {
s8 = peg$parsews(); s8 = peg$parsews();
if (input.charCodeAt(peg$currPos) === 41) { if (input.charCodeAt(peg$currPos) === 41) {
s9 = peg$c15; s9 = peg$c17;
peg$currPos++; peg$currPos++;
} else { } else {
s9 = peg$FAILED; s9 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e22); } if (peg$silentFails === 0) { peg$fail(peg$e24); }
} }
if (s9 !== peg$FAILED) { if (s9 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f5(s3, s7); s0 = peg$f6(s3, s7);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1037,39 +1082,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$c16; s1 = peg$c18;
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$e25); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsenumber();
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f6(s2);
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parseslice_fast() {
var s0, s1, s2;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 42) {
s1 = peg$c17;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e24); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsenumber(); s2 = peg$parsenumber();
@ -1088,16 +1105,16 @@ function peg$parse(input, options) {
return s0; return s0;
} }
function peg$parseslice_fixed_step() { function peg$parseslice_fast() {
var s0, s1, s2; var s0, s1, s2;
s0 = peg$currPos; s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 37) { if (input.charCodeAt(peg$currPos) === 42) {
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();
@ -1116,6 +1133,34 @@ function peg$parse(input, options) {
return s0; return s0;
} }
function peg$parseslice_fixed_step() {
var s0, s1, s2;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 37) {
s1 = peg$c20;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e27); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsenumber();
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f9(s2);
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parseslice_with_modifier() { function peg$parseslice_with_modifier() {
var s0, s1, s2; var s0, s1, s2;
@ -1127,7 +1172,7 @@ function peg$parse(input, options) {
s2 = null; s2 = null;
} }
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f9(s1, s2); s0 = peg$f10(s1, s2);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1152,7 +1197,7 @@ function peg$parse(input, options) {
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s1 = peg$f10(s1); s1 = peg$f11(s1);
} }
s0 = s1; s0 = s1;
@ -1172,7 +1217,7 @@ function peg$parse(input, options) {
s5 = peg$parsesingle_cycle(); s5 = peg$parsesingle_cycle();
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
peg$savedPos = s3; peg$savedPos = s3;
s3 = peg$f11(s1, s5); s3 = peg$f12(s1, s5);
} else { } else {
peg$currPos = s3; peg$currPos = s3;
s3 = peg$FAILED; s3 = peg$FAILED;
@ -1189,7 +1234,7 @@ function peg$parse(input, options) {
s5 = peg$parsesingle_cycle(); s5 = peg$parsesingle_cycle();
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
peg$savedPos = s3; peg$savedPos = s3;
s3 = peg$f11(s1, s5); s3 = peg$f12(s1, s5);
} else { } else {
peg$currPos = s3; peg$currPos = s3;
s3 = peg$FAILED; s3 = peg$FAILED;
@ -1200,7 +1245,7 @@ function peg$parse(input, options) {
} }
} }
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f12(s1, s2); s0 = peg$f13(s1, s2);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1221,7 +1266,7 @@ function peg$parse(input, options) {
s4 = peg$parsequote(); s4 = peg$parsequote();
if (s4 !== peg$FAILED) { if (s4 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f13(s3); s0 = peg$f14(s3);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1271,19 +1316,19 @@ 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$c19) { if (input.substr(peg$currPos, 6) === peg$c21) {
s1 = peg$c19; s1 = peg$c21;
peg$currPos += 6; peg$currPos += 6;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e26); } if (peg$silentFails === 0) { peg$fail(peg$e28); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
s3 = peg$parsesequence_or_operator(); s3 = peg$parsesequence_or_operator();
if (s3 !== peg$FAILED) { if (s3 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f14(s3); s0 = peg$f15(s3);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1300,12 +1345,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$c20) { if (input.substr(peg$currPos, 6) === peg$c22) {
s1 = peg$c20; s1 = peg$c22;
peg$currPos += 6; peg$currPos += 6;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e27); } if (peg$silentFails === 0) { peg$fail(peg$e29); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@ -1316,7 +1361,7 @@ function peg$parse(input, options) {
s5 = peg$parsequote(); s5 = peg$parsequote();
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f15(s4); s0 = peg$f16(s4);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1341,12 +1386,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$c21) { if (input.substr(peg$currPos, 6) === peg$c23) {
s1 = peg$c21; s1 = peg$c23;
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$e30); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@ -1356,7 +1401,7 @@ function peg$parse(input, options) {
s5 = peg$parseint(); s5 = peg$parseint();
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f16(s3, s5); s0 = peg$f17(s3, s5);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1377,41 +1422,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$c22) { if (input.substr(peg$currPos, 4) === peg$c24) {
s1 = peg$c22; s1 = peg$c24;
peg$currPos += 4; peg$currPos += 4;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e29); } if (peg$silentFails === 0) { peg$fail(peg$e31); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsews();
s3 = peg$parsenumber();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f17(s3);
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parserotL() {
var s0, s1, s2, s3;
s0 = peg$currPos;
if (input.substr(peg$currPos, 4) === peg$c23) {
s1 = peg$c23;
peg$currPos += 4;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e30); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@ -1431,16 +1447,16 @@ function peg$parse(input, options) {
return s0; return s0;
} }
function peg$parserotR() { function peg$parserotL() {
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();
@ -1460,16 +1476,16 @@ function peg$parse(input, options) {
return s0; return s0;
} }
function peg$parsefast() { function peg$parserotR() {
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();
@ -1489,16 +1505,45 @@ function peg$parse(input, options) {
return s0; return s0;
} }
function peg$parsefast() {
var s0, s1, s2, s3;
s0 = peg$currPos;
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$e34); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsews();
s3 = peg$parsenumber();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f21(s3);
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parsescale() { function peg$parsescale() {
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$c26) { if (input.substr(peg$currPos, 5) === peg$c28) {
s1 = peg$c26; s1 = peg$c28;
peg$currPos += 5; peg$currPos += 5;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e33); } if (peg$silentFails === 0) { peg$fail(peg$e35); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@ -1518,7 +1563,7 @@ function peg$parse(input, options) {
s5 = peg$parsequote(); s5 = peg$parsequote();
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f21(s4); s0 = peg$f22(s4);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1543,12 +1588,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$c27) { if (input.substr(peg$currPos, 2) === peg$c29) {
s1 = peg$c27; s1 = peg$c29;
peg$currPos += 2; peg$currPos += 2;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e34); } if (peg$silentFails === 0) { peg$fail(peg$e36); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = []; s2 = [];
@ -1557,7 +1602,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$e35); } if (peg$silentFails === 0) { peg$fail(peg$e37); }
} }
while (s3 !== peg$FAILED) { while (s3 !== peg$FAILED) {
s2.push(s3); s2.push(s3);
@ -1566,7 +1611,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$e35); } if (peg$silentFails === 0) { peg$fail(peg$e37); }
} }
} }
s1 = [s1, s2]; s1 = [s1, s2];
@ -1583,21 +1628,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$c28) { if (input.substr(peg$currPos, 3) === peg$c30) {
s1 = peg$c28; s1 = peg$c30;
peg$currPos += 3; peg$currPos += 3;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e36); } if (peg$silentFails === 0) { peg$fail(peg$e38); }
} }
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$c9; s3 = peg$c10;
peg$currPos++; peg$currPos++;
} else { } else {
s3 = peg$FAILED; s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e16); } if (peg$silentFails === 0) { peg$fail(peg$e17); }
} }
if (s3 !== peg$FAILED) { if (s3 !== peg$FAILED) {
s4 = peg$parsews(); s4 = peg$parsews();
@ -1610,7 +1655,7 @@ function peg$parse(input, options) {
s9 = peg$parsesequence_or_operator(); s9 = peg$parsesequence_or_operator();
if (s9 !== peg$FAILED) { if (s9 !== peg$FAILED) {
peg$savedPos = s7; peg$savedPos = s7;
s7 = peg$f22(s5, s9); s7 = peg$f23(s5, s9);
} else { } else {
peg$currPos = s7; peg$currPos = s7;
s7 = peg$FAILED; s7 = peg$FAILED;
@ -1627,7 +1672,7 @@ function peg$parse(input, options) {
s9 = peg$parsesequence_or_operator(); s9 = peg$parsesequence_or_operator();
if (s9 !== peg$FAILED) { if (s9 !== peg$FAILED) {
peg$savedPos = s7; peg$savedPos = s7;
s7 = peg$f22(s5, s9); s7 = peg$f23(s5, s9);
} else { } else {
peg$currPos = s7; peg$currPos = s7;
s7 = peg$FAILED; s7 = peg$FAILED;
@ -1639,15 +1684,15 @@ 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$c10; s8 = peg$c11;
peg$currPos++; peg$currPos++;
} else { } else {
s8 = peg$FAILED; s8 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e17); } if (peg$silentFails === 0) { peg$fail(peg$e18); }
} }
if (s8 !== peg$FAILED) { if (s8 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f23(s5, s6); s0 = peg$f24(s5, s6);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1693,7 +1738,7 @@ function peg$parse(input, options) {
s4 = peg$parsecomment(); s4 = peg$parsecomment();
} }
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f24(s1); s0 = peg$f25(s1);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1704,18 +1749,18 @@ 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$c29; s3 = peg$c31;
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$e39); }
} }
if (s3 !== peg$FAILED) { if (s3 !== peg$FAILED) {
s4 = peg$parsews(); s4 = peg$parsews();
s5 = peg$parsesequence_or_operator(); s5 = peg$parsesequence_or_operator();
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f25(s1, s5); s0 = peg$f26(s1, s5);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1740,7 +1785,7 @@ function peg$parse(input, options) {
s1 = peg$parsesequence_or_operator(); s1 = peg$parsesequence_or_operator();
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s1 = peg$f26(s1); s1 = peg$f27(s1);
} }
s0 = s1; s0 = s1;
if (s0 === peg$FAILED) { if (s0 === peg$FAILED) {
@ -1773,7 +1818,7 @@ function peg$parse(input, options) {
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s3 = peg$parsews(); s3 = peg$parsews();
peg$savedPos = s0; peg$savedPos = s0;
s0 = peg$f27(s2); s0 = peg$f28(s2);
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
@ -1786,41 +1831,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$c30) { if (input.substr(peg$currPos, 6) === peg$c32) {
s1 = peg$c30; s1 = peg$c32;
peg$currPos += 6; peg$currPos += 6;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e38); } if (peg$silentFails === 0) { peg$fail(peg$e40); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsews();
s3 = peg$parsenumber();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f28(s3);
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parsesetbpm() {
var s0, s1, s2, s3;
s0 = peg$currPos;
if (input.substr(peg$currPos, 6) === peg$c31) {
s1 = peg$c31;
peg$currPos += 6;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e39); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = peg$parsews(); s2 = peg$parsews();
@ -1840,20 +1856,49 @@ function peg$parse(input, options) {
return s0; return s0;
} }
function peg$parsesetbpm() {
var s0, s1, s2, s3;
s0 = peg$currPos;
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$e41); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parsews();
s3 = peg$parsenumber();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
s0 = peg$f30(s3);
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
return s0;
}
function peg$parsehush() { function peg$parsehush() {
var s0, s1; var s0, s1;
s0 = peg$currPos; s0 = peg$currPos;
if (input.substr(peg$currPos, 4) === peg$c32) { if (input.substr(peg$currPos, 4) === peg$c34) {
s1 = peg$c32; s1 = peg$c34;
peg$currPos += 4; peg$currPos += 4;
} else { } else {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e40); } if (peg$silentFails === 0) { peg$fail(peg$e42); }
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s1 = peg$f30(); s1 = peg$f31();
} }
s0 = s1; s0 = s1;

View File

@ -82,6 +82,9 @@ class TimeSpan {
withTime(func_time) { withTime(func_time) {
return new TimeSpan(func_time(this.begin), func_time(this.end)); return new TimeSpan(func_time(this.begin), func_time(this.end));
} }
withEnd(func_time) {
return new TimeSpan(this.begin, func_time(this.end));
}
intersection(other) { intersection(other) {
const intersect_begin = this.begin.max(other.begin); const intersect_begin = this.begin.max(other.begin);
const intersect_end = this.end.min(other.end); const intersect_end = this.end.min(other.end);
@ -408,6 +411,13 @@ class Pattern {
edit(...funcs) { edit(...funcs) {
return stack(...funcs.map((func) => func(this))); return stack(...funcs.map((func) => func(this)));
} }
_bypass(on2) {
on2 = Boolean(parseInt(on2));
return on2 ? silence : this;
}
hush() {
return silence;
}
} }
Pattern.prototype.patternified = ["fast", "slow", "early", "late"]; Pattern.prototype.patternified = ["fast", "slow", "early", "late"];
Pattern.prototype.factories = {pure, stack, slowcat, fastcat, cat, timeCat, sequence, polymeter, pm, polyrhythm, pr}; Pattern.prototype.factories = {pure, stack, slowcat, fastcat, cat, timeCat, sequence, polymeter, pm, polyrhythm, pr};
@ -554,6 +564,8 @@ Pattern.prototype.define = (name, func, options = {}) => {
Pattern.prototype.patternified = Pattern.prototype.patternified.concat([name]); Pattern.prototype.patternified = Pattern.prototype.patternified.concat([name]);
} }
}; };
Pattern.prototype.define("hush", (pat) => pat.hush(), {patternified: false, composable: true});
Pattern.prototype.define("bypass", (pat) => pat.bypass(on), {patternified: true, composable: true});
Pattern.prototype.bootstrap = () => { Pattern.prototype.bootstrap = () => {
const bootstrapped = Object.fromEntries(Object.entries(Pattern.prototype.composable).map(([functionName, composable]) => { const bootstrapped = Object.fromEntries(Object.entries(Pattern.prototype.composable).map(([functionName, composable]) => {
if (Pattern.prototype[functionName]) { if (Pattern.prototype[functionName]) {

67
docs/dist/App.js vendored
View File

@ -10,7 +10,7 @@ import hot from "../hot.js";
import {isNote} from "../_snowpack/pkg/tone.js"; import {isNote} from "../_snowpack/pkg/tone.js";
import {useWebMidi} from "./midi.js"; import {useWebMidi} from "./midi.js";
const [_, codeParam] = window.location.href.split("#"); const [_, codeParam] = window.location.href.split("#");
const decoded = atob(codeParam || ""); const decoded = atob(decodeURIComponent(codeParam || ""));
const getHotCode = async () => { const getHotCode = async () => {
return fetch("/hot.js").then((res) => res.text()).then((src) => { return fetch("/hot.js").then((res) => res.text()).then((src) => {
return src.split("export default").slice(-1)[0].trim(); return src.split("export default").slice(-1)[0].trim();
@ -30,17 +30,37 @@ function getRandomTune() {
} }
const randomTune = getRandomTune(); const randomTune = getRandomTune();
function App() { function App() {
const [mode, setMode] = useState("javascript");
const [code, setCode] = useState(decoded || randomTune); const [code, setCode] = useState(decoded || randomTune);
const [activeCode, setActiveCode] = useState();
const [log, setLog] = useState(""); const [log, setLog] = useState("");
const logBox = useRef(); const logBox = useRef();
const [error, setError] = useState(); const [error, setError] = useState();
const [pattern, setPattern] = useState(); const [pattern, setPattern] = useState();
const [activePattern, setActivePattern] = useState(); const [activePattern, setActivePattern] = useState();
const activatePattern = (_pattern = pattern) => { const dirty = code !== activeCode;
setActivePattern(() => _pattern); const activateCode = (_code = code) => {
window.location.hash = "#" + btoa(code); if (activeCode && !dirty) {
!cycle.started && cycle.start(); setError(void 0);
return;
}
try {
const parsed = evaluate(_code);
setPattern(() => parsed.pattern);
activatePattern(parsed.pattern);
setError(void 0);
setActiveCode(_code);
} catch (err) {
setError(err);
}
};
const activatePattern = (_pattern) => {
try {
setActivePattern(() => _pattern);
window.location.hash = "#" + encodeURIComponent(btoa(code));
!cycle.started && cycle.start();
} catch (err) {
setError(err);
}
}; };
const [isHot, setIsHot] = useState(false); const [isHot, setIsHot] = useState(false);
const pushLog = (message) => setLog((log2) => log2 + `${log2 ? "\n\n" : ""}${message}`); const pushLog = (message) => setLog((log2) => log2 + `${log2 ? "\n\n" : ""}${message}`);
@ -85,7 +105,7 @@ function App() {
if (e.ctrlKey || e.altKey) { if (e.ctrlKey || e.altKey) {
switch (e.code) { switch (e.code) {
case "Enter": case "Enter":
activatePattern(); activateCode();
break; break;
case "Period": case "Period":
cycle.stop(); cycle.stop();
@ -94,34 +114,19 @@ function App() {
}; };
document.addEventListener("keypress", handleKeyPress); document.addEventListener("keypress", handleKeyPress);
return () => document.removeEventListener("keypress", handleKeyPress); return () => document.removeEventListener("keypress", handleKeyPress);
}, [pattern]); }, [pattern, code]);
useEffect(() => { useEffect(() => {
let _code = code;
if (isHot) { if (isHot) {
if (typeof hot !== "string") { if (typeof hot !== "string") {
getHotCode().then((_code2) => { getHotCode().then((_code) => {
setCode(_code2);
setMode("javascript");
}); });
activatePattern(hot); activatePattern(hot);
return; return;
} else { } else {
_code = hot; setCode(hot);
setCode(_code); activateCode(hot);
} }
} }
try {
const parsed = evaluate(_code);
setPattern(() => parsed.pattern);
if (isHot) {
activatePattern(parsed.pattern);
}
setMode(parsed.mode);
setError(void 0);
} catch (err) {
console.warn(err);
setError(err);
}
}, [code, isHot]); }, [code, isHot]);
useLayoutEffect(() => { useLayoutEffect(() => {
logBox.current.scrollTop = logBox.current?.scrollHeight; logBox.current.scrollTop = logBox.current?.scrollHeight;
@ -175,7 +180,7 @@ function App() {
value: code, value: code,
readOnly: isHot, readOnly: isHot,
options: { options: {
mode, mode: "javascript",
theme: "material", theme: "material",
lineNumbers: true lineNumbers: true
}, },
@ -187,14 +192,14 @@ function App() {
}), /* @__PURE__ */ React.createElement("span", { }), /* @__PURE__ */ React.createElement("span", {
className: "p-4 absolute top-0 right-0 text-xs whitespace-pre text-right" className: "p-4 absolute top-0 right-0 text-xs whitespace-pre text-right"
}, !cycle.started ? `press ctrl+enter to play }, !cycle.started ? `press ctrl+enter to play
` : !isHot && activePattern !== pattern ? `ctrl+enter to update ` : !isHot && code !== activeCode ? `ctrl+enter to update
` : "no changes\n", !isHot && /* @__PURE__ */ React.createElement(React.Fragment, null, {pegjs: "mini"}[mode] || mode, " mode"), isHot && "🔥 hot mode: go to hot.js to edit pattern, then save")), error && /* @__PURE__ */ React.createElement("div", { ` : "no changes\n", isHot && "🔥 hot mode: go to hot.js to edit pattern, then save")), error && /* @__PURE__ */ React.createElement("div", {
className: "absolute right-2 bottom-2 text-red-500" className: cx("absolute right-2 bottom-2", "text-red-500")
}, error?.message || "unknown error")), /* @__PURE__ */ React.createElement("button", { }, error?.message || "unknown error")), /* @__PURE__ */ React.createElement("button", {
className: "flex-none w-full border border-gray-700 p-2 bg-slate-700 hover:bg-slate-500", className: "flex-none w-full border border-gray-700 p-2 bg-slate-700 hover:bg-slate-500",
onClick: () => { onClick: () => {
if (!cycle.started) { if (!cycle.started) {
activatePattern(); activateCode();
} else { } else {
cycle.stop(); cycle.stop();
} }

10
docs/dist/evaluate.js vendored
View File

@ -6,6 +6,8 @@ import "./tonal.js";
import "./groove.js"; import "./groove.js";
import shapeshifter from "./shapeshifter.js"; import shapeshifter from "./shapeshifter.js";
import {minify} from "./parse.js"; import {minify} from "./parse.js";
import * as Tone from "../_snowpack/pkg/tone.js";
import * as toneHelpers from "./tone.js";
const bootstrapped = {...strudel, ...strudel.Pattern.prototype.bootstrap()}; const bootstrapped = {...strudel, ...strudel.Pattern.prototype.bootstrap()};
function hackLiteral(literal, names, func) { function hackLiteral(literal, names, func) {
names.forEach((name) => { names.forEach((name) => {
@ -18,10 +20,14 @@ function hackLiteral(literal, names, func) {
} }
hackLiteral(String, ["mini", "m"], bootstrapped.mini); hackLiteral(String, ["mini", "m"], bootstrapped.mini);
hackLiteral(String, ["pure", "p"], bootstrapped.pure); hackLiteral(String, ["pure", "p"], bootstrapped.pure);
Object.assign(globalThis, bootstrapped); Object.assign(globalThis, bootstrapped, Tone, toneHelpers);
export const evaluate = (code) => { export const evaluate = (code) => {
const shapeshifted = shapeshifter(code); const shapeshifted = shapeshifter(code);
const pattern = minify(eval(shapeshifted)); let evaluated = eval(shapeshifted);
if (typeof evaluated === "function") {
evaluated = evaluated();
}
const pattern = minify(evaluated);
if (pattern?.constructor?.name !== "Pattern") { if (pattern?.constructor?.name !== "Pattern") {
const message = `got "${typeof pattern}" instead of pattern`; const message = `got "${typeof pattern}" instead of pattern`;
throw new Error(message + (typeof pattern === "function" ? ", did you forget to call a function?" : ".")); throw new Error(message + (typeof pattern === "function" ? ", did you forget to call a function?" : "."));

34
docs/dist/parse.js vendored
View File

@ -23,9 +23,40 @@ const applyOptions = (parent) => (pat, i) => {
} }
return pat; return pat;
}; };
function resolveReplications(ast) {
ast.source_ = ast.source_.map((child) => {
const {replicate, ...options} = child.options_ || {};
if (replicate) {
return {
...child,
options_: {...options, weight: replicate},
source_: {
type_: "pattern",
arguments_: {
alignment: "h"
},
source_: [
{
type_: "element",
source_: child.source_,
options_: {
operator: {
type_: "stretch",
arguments_: {amount: String(new Fraction(replicate).inverse().valueOf())}
}
}
}
]
}
};
}
return child;
});
}
export function patternifyAST(ast) { export function patternifyAST(ast) {
switch (ast.type_) { switch (ast.type_) {
case "pattern": case "pattern":
resolveReplications(ast);
const children = ast.source_.map(patternifyAST).map(applyOptions(ast)); const children = ast.source_.map(patternifyAST).map(applyOptions(ast));
const alignment = ast.arguments_.alignment; const alignment = ast.arguments_.alignment;
if (alignment === "v") { if (alignment === "v") {
@ -38,7 +69,8 @@ export function patternifyAST(ast) {
if (weightedChildren) { if (weightedChildren) {
const pat = timeCat(...ast.source_.map((child, i) => [child.options_?.weight || 1, children[i]])); const pat = timeCat(...ast.source_.map((child, i) => [child.options_?.weight || 1, children[i]]));
if (alignment === "t") { if (alignment === "t") {
return pat._slow(children.length); const weightSum = ast.source_.reduce((sum, child) => sum + (child.options_?.weight || 1), 0);
return pat._slow(weightSum);
} }
return pat; return pat;
} }

2
docs/dist/tonal.js vendored
View File

@ -46,7 +46,7 @@ function scaleTranspose(scale, offset, note) {
Pattern.prototype._mapNotes = function(func) { Pattern.prototype._mapNotes = function(func) {
return this.fmap((event) => { return this.fmap((event) => {
const noteEvent = toNoteEvent(event); const noteEvent = toNoteEvent(event);
return func(noteEvent); return {...noteEvent, ...func(noteEvent)};
}); });
}; };
Pattern.prototype._transpose = function(intervalOrSemitones) { Pattern.prototype._transpose = function(intervalOrSemitones) {

59
docs/dist/tone.js vendored
View File

@ -1,6 +1,62 @@
import {Pattern as _Pattern} from "../_snowpack/link/strudel.js"; import {Pattern as _Pattern} from "../_snowpack/link/strudel.js";
import {AutoFilter, Destination, Filter, Gain, isNote, Synth} from "../_snowpack/pkg/tone.js"; import {AutoFilter, Destination, Filter, Gain, isNote, Synth, PolySynth} from "../_snowpack/pkg/tone.js";
const Pattern = _Pattern; const Pattern = _Pattern;
Pattern.prototype.tone = function(instrument) {
return this.fmap((value) => {
value = typeof value !== "object" && !Array.isArray(value) ? {value} : value;
const onTrigger = (time, event) => {
if (instrument.constructor.name === "PluckSynth") {
instrument.triggerAttack(value.value, time);
} else if (instrument.constructor.name === "NoiseSynth") {
instrument.triggerAttackRelease(event.duration, time);
} else {
instrument.triggerAttackRelease(value.value, event.duration, time);
}
};
return {...value, instrument, onTrigger};
});
};
Pattern.prototype.define("tone", (type, pat) => pat.tone(type), {composable: true, patternified: false});
export const vol = (v) => new Gain(v);
export const lowpass = (v) => new Filter(v, "lowpass");
export const highpass = (v) => new Filter(v, "highpass");
export const adsr = (a, d = 0.1, s = 0.4, r = 0.01) => ({envelope: {attack: a, decay: d, sustain: s, release: r}});
export const osc = (type) => ({oscillator: {type}});
export const out = Destination;
const chainable = function(instr) {
const _chain = instr.chain.bind(instr);
let chained = [];
instr.chain = (...args) => {
chained = chained.concat(args);
instr.disconnect();
return _chain(...chained, Destination);
};
instr.filter = (freq = 1e3, type = "lowpass") => instr.chain(new Filter(freq, type));
instr.gain = (gain2 = 0.9) => instr.chain(new Gain(gain2));
return instr;
};
export const poly = (type) => {
const s = new PolySynth(Synth, {oscillator: {type}}).toDestination();
return chainable(s);
};
Pattern.prototype._poly = function(type = "triangle") {
const instrumentConfig = {
oscillator: {type},
envelope: {attack: 0.01, decay: 0.01, sustain: 0.6, release: 0.01}
};
if (!this.instrument) {
this.instrument = poly(type);
}
return this.fmap((value) => {
value = typeof value !== "object" && !Array.isArray(value) ? {value} : value;
const onTrigger = (time, event) => {
this.instrument.set(instrumentConfig);
this.instrument.triggerAttackRelease(value.value, event.duration, time);
};
return {...value, instrumentConfig, onTrigger};
});
};
Pattern.prototype.define("poly", (type, pat) => pat.poly(type), {composable: true, patternified: true});
const getTrigger = (getChain, value) => (time, event) => { const getTrigger = (getChain, value) => (time, event) => {
const chain = getChain(); const chain = getChain();
if (!isNote(value)) { if (!isNote(value)) {
@ -68,7 +124,6 @@ Pattern.prototype._filter = function(freq, q, type = "lowpass") {
Pattern.prototype.autofilter = function(g) { Pattern.prototype.autofilter = function(g) {
return this.chain(autofilter(g)); return this.chain(autofilter(g));
}; };
Pattern.prototype.patternified = Pattern.prototype.patternified.concat(["synth", "gain", "filter"]);
Pattern.prototype.define("synth", (type, pat) => pat.synth(type), {composable: true, patternified: true}); Pattern.prototype.define("synth", (type, pat) => pat.synth(type), {composable: true, patternified: true});
Pattern.prototype.define("gain", (gain2, pat) => pat.synth(gain2), {composable: true, patternified: true}); Pattern.prototype.define("gain", (gain2, pat) => pat.synth(gain2), {composable: true, patternified: true});
Pattern.prototype.define("filter", (cutoff, pat) => pat.filter(cutoff), {composable: true, patternified: true}); Pattern.prototype.define("filter", (cutoff, pat) => pat.filter(cutoff), {composable: true, patternified: true});

91
docs/dist/tunes.js vendored
View File

@ -250,12 +250,11 @@ export const groove = `stack(
.voicings(['G3','A4']) .voicings(['G3','A4'])
).slow(4)`; ).slow(4)`;
export const magicSofa = `stack( export const magicSofa = `stack(
'[C^7 F^7 ~]/3 [Dm7 G7 A7 ~]/4'.mini '<C^7 F^7 ~> <Dm7 G7 A7 ~>'.m
.every(2, fast(2)) .every(2, fast(2))
.voicings(), .voicings(),
'[c2 f2 g2]/3 [d2 g2 a2 e2]/4'.mini '<c2 f2 g2> <d2 g2 a2 e2>'.m
).slow(1) ).slow(1).transpose.slowcat(0, 2, 3, 4)`;
.transpose.slowcat(0, 2, 3, 4)`;
export const confusedPhoneDynamic = `stack('[g2 ~@1.3] [c3 ~@1.3]'.mini.slow(2)) export const confusedPhoneDynamic = `stack('[g2 ~@1.3] [c3 ~@1.3]'.mini.slow(2))
.superimpose( .superimpose(
...[-12,7,10,12,24].slice(0,5).map((t,i,{length}) => x => transpose(t,x).late(i/length)) ...[-12,7,10,12,24].slice(0,5).map((t,i,{length}) => x => transpose(t,x).late(i/length))
@ -274,3 +273,87 @@ export const confusedPhone = `'[g2 ~@1.3] [c3 ~@1.3]'.mini
.scale(slowcat('C dorian', 'C mixolydian')) .scale(slowcat('C dorian', 'C mixolydian'))
.scaleTranspose(slowcat(0,1,2,1)) .scaleTranspose(slowcat(0,1,2,1))
.slow(2)`; .slow(2)`;
export const zeldasRescue = `stack(
// melody
\`[B3@2 D4] [A3@2 [G3 A3]] [B3@2 D4] [A3]
[B3@2 D4] [A4@2 G4] [D4@2 [C4 B3]] [A3]
[B3@2 D4] [A3@2 [G3 A3]] [B3@2 D4] [A3]
[B3@2 D4] [A4@2 G4] D5@2
[D5@2 [C5 B4]] [[C5 B4] G4@2] [C5@2 [B4 A4]] [[B4 A4] E4@2]
[D5@2 [C5 B4]] [[C5 B4] G4 C5] [G5] [~ ~ B3]\`.mini,
// bass
\`[[C2 G2] E3@2] [[C2 G2] F#3@2] [[C2 G2] E3@2] [[C2 G2] F#3@2]
[[B1 D3] G3@2] [[Bb1 Db3] G3@2] [[A1 C3] G3@2] [[D2 C3] F#3@2]
[[C2 G2] E3@2] [[C2 G2] F#3@2] [[C2 G2] E3@2] [[C2 G2] F#3@2]
[[B1 D3] G3@2] [[Bb1 Db3] G3@2] [[A1 C3] G3@2] [[D2 C3] F#3@2]
[[F2 C3] E3@2] [[E2 B2] D3@2] [[D2 A2] C3@2] [[C2 G2] B2@2]
[[F2 C3] E3@2] [[E2 B2] D3@2] [[Eb2 Bb2] Db3@2] [[D2 A2] C3 [F3,G2]]\`.mini
).transpose(12).slow(48).tone(
new PolySynth().chain(
new Gain(0.3),
new Chorus(2, 2.5, 0.5).start(),
new Freeverb(),
Destination)
)`;
export const technoDrums = `stack(
'c1*2'.m.tone(new Tone.MembraneSynth().toDestination()),
'~ x'.m.tone(new Tone.NoiseSynth().toDestination()),
'[~ c4]*2'.m.tone(new Tone.MetalSynth().set({envelope:{decay:0.06,sustain:0}}).chain(new Gain(0.5),Destination))
)`;
export const loungerave = `() => {
const delay = new FeedbackDelay(1/8, .2).chain(vol(0.5), out);
const kick = new MembraneSynth().chain(vol(.8), out);
const snare = new NoiseSynth().chain(vol(.8), out);
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out);
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out);
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out);
const drums = stack(
'c1*2'.m.tone(kick).bypass('<0@7 1>/8'.m),
'~ <x!7 [x@3 x]>'.m.tone(snare).bypass('<0@7 1>/4'.m),
'[~ c4]*2'.m.tone(hihat)
);
const thru = (x) => x.transpose('<0 1>/8'.m).transpose(1);
const synths = stack(
'<C2 Bb1 Ab1 [G1 [G2 G1]]>/2'.m.groove('[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2'.m).edit(thru).tone(bass),
'<Cm7 Bb7 Fm7 G7b9>/2'.m.groove('~ [x@0.1 ~]'.m).voicings().edit(thru).every(2, early(1/4)).tone(keys).bypass('<0@7 1>/8'.m.early(1/4))
)
return stack(
drums,
synths
)
//.bypass('<0 1>*4'.m)
//.early('0.25 0'.m);
}`;
export const caverave = `() => {
const delay = new FeedbackDelay(1/8, .4).chain(vol(0.5), out);
const kick = new MembraneSynth().chain(vol(.8), out);
const snare = new NoiseSynth().chain(vol(.8), out);
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out);
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out);
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out);
const drums = stack(
'c1*2'.m.tone(kick).bypass('<0@7 1>/8'.m),
'~ <x!7 [x@3 x]>'.m.tone(snare).bypass('<0@7 1>/4'.m),
'[~ c4]*2'.m.tone(hihat)
);
const thru = (x) => x.transpose('<0 1>/8'.m).transpose(-1);
const synths = stack(
'<eb4 d4 c4 b3>/2'.m.scale(timeCat([3,'C minor'],[1,'C melodic minor']).slow(8)).groove('[~ x]*2'.m)
.edit(
scaleTranspose(0).early(0),
scaleTranspose(2).early(1/8),
scaleTranspose(7).early(1/4),
scaleTranspose(8).early(3/8)
).edit(thru).tone(keys).bypass('<1 0>/16'.m),
'<C2 Bb1 Ab1 [G1 [G2 G1]]>/2'.m.groove('[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2'.m.fast(2)).edit(thru).tone(bass),
'<Cm7 Bb7 Fm7 G7b13>/2'.m.groove('~ [x@0.1 ~]'.m.fast(2)).voicings().edit(thru).every(2, early(1/8)).tone(keys).bypass('<0@7 1>/8'.m.early(1/4))
)
return stack(
drums.fast(2),
synths
).slow(2);
}`;

12
docs/dist/useCycle.js vendored
View File

@ -8,12 +8,8 @@ function useCycle(props) {
const activeCycle = () => Math.floor(Tone.Transport.seconds / cycleDuration); const activeCycle = () => Math.floor(Tone.Transport.seconds / cycleDuration);
const query = (cycle = activeCycle()) => { const query = (cycle = activeCycle()) => {
const timespan = new TimeSpan(cycle, cycle + 1); const timespan = new TimeSpan(cycle, cycle + 1);
const _events = onQuery?.(timespan) || []; const events = onQuery?.(timespan) || [];
onSchedule?.(_events, cycle); onSchedule?.(events, cycle);
schedule(_events, cycle);
};
const schedule = (events, cycle = activeCycle()) => {
const timespan = new TimeSpan(cycle, cycle + 1);
const cancelFrom = timespan.begin.valueOf(); const cancelFrom = timespan.begin.valueOf();
Tone.Transport.cancel(cancelFrom); Tone.Transport.cancel(cancelFrom);
const queryNextTime = (cycle + 1) * cycleDuration - 0.1; const queryNextTime = (cycle + 1) * cycleDuration - 0.1;
@ -29,7 +25,7 @@ function useCycle(props) {
Tone.Transport.schedule((time) => { Tone.Transport.schedule((time) => {
const toneEvent = { const toneEvent = {
time: event.part.begin.valueOf(), time: event.part.begin.valueOf(),
duration: event.whole.end.valueOf() - event.whole.begin.valueOf(), duration: event.whole.end.sub(event.whole.begin).valueOf(),
value: event.value value: event.value
}; };
onEvent(time, toneEvent); onEvent(time, toneEvent);
@ -51,6 +47,6 @@ function useCycle(props) {
Tone.Transport.pause(); Tone.Transport.pause();
}; };
const toggle = () => started ? stop() : start(); const toggle = () => started ? stop() : start();
return {start, stop, onEvent, started, toggle, schedule, query, activeCycle}; return {start, stop, onEvent, started, toggle, query, activeCycle};
} }
export default useCycle; export default useCycle;

View File

@ -621,9 +621,6 @@ select {
.flex { .flex {
display: flex; display: flex;
} }
.contents {
display: contents;
}
.h-16 { .h-16 {
height: 4rem; height: 4rem;
} }