mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-24 12:08:28 +00:00
add euclid
This commit is contained in:
parent
eaa250a962
commit
91c0a46ba9
@ -262,7 +262,7 @@ function peg$parse(input, options) {
|
|||||||
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(a) { return { replicate: a } };
|
var peg$f5 = function(a) { return { replicate: a } };
|
||||||
var peg$f6 = function(p, s) { return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s } } } };
|
var peg$f6 = function(p, s, r) { return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r || 0 } } } };
|
||||||
var peg$f7 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:a } } } };
|
var peg$f7 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:a } } } };
|
||||||
var peg$f8 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:"1/"+a } } } };
|
var peg$f8 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:"1/"+a } } } };
|
||||||
var peg$f9 = function(a) { return { operator : { type_: "fixed-step", arguments_ :{ amount:a } } } };
|
var peg$f9 = function(a) { return { operator : { type_: "fixed-step", arguments_ :{ amount:a } } } };
|
||||||
@ -273,7 +273,7 @@ function peg$parse(input, options) {
|
|||||||
var peg$f14 = function(s) { return s; };
|
var peg$f14 = function(s) { return s; };
|
||||||
var peg$f15 = function(s) { return { name: "struct", args: { sequence:s }}};
|
var peg$f15 = function(s) { return { name: "struct", args: { sequence:s }}};
|
||||||
var peg$f16 = function(s) { return { name: "target", args : { name:s}}};
|
var peg$f16 = function(s) { return { name: "target", args : { name:s}}};
|
||||||
var peg$f17 = function(p, s) { return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}};
|
var peg$f17 = function(p, s, r) { return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}};
|
||||||
var peg$f18 = function(a) { return { name: "stretch", 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: "shift", args :{ amount: a}}};
|
var peg$f20 = function(a) { return { name: "shift", args :{ amount: a}}};
|
||||||
@ -1022,7 +1022,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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, s10, s11, s12, s13;
|
||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.charCodeAt(peg$currPos) === 40) {
|
if (input.charCodeAt(peg$currPos) === 40) {
|
||||||
@ -1043,16 +1043,26 @@ function peg$parse(input, options) {
|
|||||||
s7 = peg$parsenumber();
|
s7 = peg$parsenumber();
|
||||||
if (s7 !== peg$FAILED) {
|
if (s7 !== peg$FAILED) {
|
||||||
s8 = peg$parsews();
|
s8 = peg$parsews();
|
||||||
|
s9 = peg$parsecomma();
|
||||||
|
if (s9 === peg$FAILED) {
|
||||||
|
s9 = null;
|
||||||
|
}
|
||||||
|
s10 = peg$parsews();
|
||||||
|
s11 = peg$parsenumber();
|
||||||
|
if (s11 === peg$FAILED) {
|
||||||
|
s11 = null;
|
||||||
|
}
|
||||||
|
s12 = peg$parsews();
|
||||||
if (input.charCodeAt(peg$currPos) === 41) {
|
if (input.charCodeAt(peg$currPos) === 41) {
|
||||||
s9 = peg$c17;
|
s13 = peg$c17;
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s9 = peg$FAILED;
|
s13 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e24); }
|
if (peg$silentFails === 0) { peg$fail(peg$e24); }
|
||||||
}
|
}
|
||||||
if (s9 !== peg$FAILED) {
|
if (s13 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f6(s3, s7);
|
s0 = peg$f6(s3, s7, s11);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
@ -1383,7 +1393,7 @@ function peg$parse(input, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function peg$parsebjorklund() {
|
function peg$parsebjorklund() {
|
||||||
var s0, s1, s2, s3, s4, s5;
|
var s0, s1, s2, s3, s4, s5, s6, s7;
|
||||||
|
|
||||||
s0 = peg$currPos;
|
s0 = peg$currPos;
|
||||||
if (input.substr(peg$currPos, 6) === peg$c23) {
|
if (input.substr(peg$currPos, 6) === peg$c23) {
|
||||||
@ -1400,8 +1410,13 @@ function peg$parse(input, options) {
|
|||||||
s4 = peg$parsews();
|
s4 = peg$parsews();
|
||||||
s5 = peg$parseint();
|
s5 = peg$parseint();
|
||||||
if (s5 !== peg$FAILED) {
|
if (s5 !== peg$FAILED) {
|
||||||
|
s6 = peg$parsews();
|
||||||
|
s7 = peg$parseint();
|
||||||
|
if (s7 === peg$FAILED) {
|
||||||
|
s7 = null;
|
||||||
|
}
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
s0 = peg$f17(s3, s5);
|
s0 = peg$f17(s3, s5, s7);
|
||||||
} else {
|
} else {
|
||||||
peg$currPos = s0;
|
peg$currPos = s0;
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
|
|||||||
@ -104,8 +104,8 @@ slice_weight = "@" a:number
|
|||||||
slice_replicate = "!"a:number
|
slice_replicate = "!"a:number
|
||||||
{ return { replicate: a } }
|
{ return { replicate: a } }
|
||||||
|
|
||||||
slice_bjorklund = "(" ws p:number ws comma ws s:number ws")"
|
slice_bjorklund = "(" ws p:number ws comma ws s:number ws comma? ws r:number? ws ")"
|
||||||
{ return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s } } } }
|
{ return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s, rotation:r || 0 } } } }
|
||||||
|
|
||||||
slice_slow = "/"a:number
|
slice_slow = "/"a:number
|
||||||
{ return { operator : { type_: "stretch", arguments_ :{ amount:a } } } }
|
{ return { operator : { type_: "stretch", arguments_ :{ amount:a } } } }
|
||||||
@ -145,7 +145,7 @@ struct = "struct" ws s:sequence_or_operator
|
|||||||
target = "target" ws quote s:step quote
|
target = "target" ws quote s:step quote
|
||||||
{ return { name: "target", args : { name:s}}}
|
{ return { name: "target", args : { name:s}}}
|
||||||
|
|
||||||
bjorklund = "euclid" ws p:int ws s:int
|
bjorklund = "euclid" ws p:int ws s:int ws r:int?
|
||||||
{ return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}}
|
{ return { name: "bjorklund", args :{ pulse: parseInt(p), step:parseInt(s) }}}
|
||||||
|
|
||||||
slow = "slow" ws a:number
|
slow = "slow" ws a:number
|
||||||
|
|||||||
11
repl/package-lock.json
generated
11
repl/package-lock.json
generated
@ -7,6 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tonaljs/tonal": "^4.6.5",
|
"@tonaljs/tonal": "^4.6.5",
|
||||||
"@tonejs/piano": "^0.2.1",
|
"@tonejs/piano": "^0.2.1",
|
||||||
|
"bjork": "^0.0.1",
|
||||||
"chord-voicings": "^0.0.1",
|
"chord-voicings": "^0.0.1",
|
||||||
"codemirror": "^5.65.1",
|
"codemirror": "^5.65.1",
|
||||||
"estraverse": "^5.3.0",
|
"estraverse": "^5.3.0",
|
||||||
@ -4195,6 +4196,11 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bjork": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/bjork/-/bjork-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-br1a3pkWSwvgMIeI1kaRQ9XJrZw="
|
||||||
|
},
|
||||||
"node_modules/bl": {
|
"node_modules/bl": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
@ -15511,6 +15517,11 @@
|
|||||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"bjork": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/bjork/-/bjork-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-br1a3pkWSwvgMIeI1kaRQ9XJrZw="
|
||||||
|
},
|
||||||
"bl": {
|
"bl": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tonaljs/tonal": "^4.6.5",
|
"@tonaljs/tonal": "^4.6.5",
|
||||||
"@tonejs/piano": "^0.2.1",
|
"@tonejs/piano": "^0.2.1",
|
||||||
|
"bjork": "^0.0.1",
|
||||||
"chord-voicings": "^0.0.1",
|
"chord-voicings": "^0.0.1",
|
||||||
"codemirror": "^5.65.1",
|
"codemirror": "^5.65.1",
|
||||||
"estraverse": "^5.3.0",
|
"estraverse": "^5.3.0",
|
||||||
|
|||||||
17
repl/src/euclid.mjs
Normal file
17
repl/src/euclid.mjs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Pattern } from '../../strudel.mjs';
|
||||||
|
import bjork from 'bjork';
|
||||||
|
import { rotate } from '../../util.mjs';
|
||||||
|
|
||||||
|
const euclid = (pulses, steps, rotation = 0) => {
|
||||||
|
const b = bjork(steps, pulses);
|
||||||
|
if (rotation) {
|
||||||
|
return rotate(b, -rotation);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
|
||||||
|
Pattern.prototype.euclid = function (pulses, steps, rotation = 0) {
|
||||||
|
return this.struct(euclid(pulses, steps, rotation));
|
||||||
|
};
|
||||||
|
|
||||||
|
export default euclid;
|
||||||
@ -5,7 +5,8 @@ import './voicings';
|
|||||||
import './tonal.mjs';
|
import './tonal.mjs';
|
||||||
import './xen.mjs';
|
import './xen.mjs';
|
||||||
import './tune.mjs';
|
import './tune.mjs';
|
||||||
import './tune.mjs';
|
import './euclid.mjs';
|
||||||
|
import euclid from './euclid.mjs';
|
||||||
import './pianoroll.mjs';
|
import './pianoroll.mjs';
|
||||||
import './draw.mjs';
|
import './draw.mjs';
|
||||||
import * as uiHelpers from './ui.mjs';
|
import * as uiHelpers from './ui.mjs';
|
||||||
@ -36,7 +37,7 @@ hackLiteral(String, ['mini', 'm'], bootstrapped.mini); // comment out this line
|
|||||||
hackLiteral(String, ['pure', 'p'], bootstrapped.pure); // comment out this line if you panic
|
hackLiteral(String, ['pure', 'p'], bootstrapped.pure); // comment out this line if you panic
|
||||||
|
|
||||||
// this will add everything to global scope, which is accessed by eval
|
// this will add everything to global scope, which is accessed by eval
|
||||||
Object.assign(globalThis, bootstrapped, Tone, toneHelpers, voicingHelpers, drawHelpers, uiHelpers, { gist });
|
Object.assign(globalThis, bootstrapped, Tone, toneHelpers, voicingHelpers, drawHelpers, uiHelpers, { gist, euclid });
|
||||||
|
|
||||||
export const evaluate: any = async (code: string) => {
|
export const evaluate: any = async (code: string) => {
|
||||||
const shapeshifted = shapeshifter(code); // transform syntactically correct js code to semantically usable code
|
const shapeshifted = shapeshifter(code); // transform syntactically correct js code to semantically usable code
|
||||||
|
|||||||
@ -14,6 +14,8 @@ const applyOptions = (parent: any) => (pat: any, i: number) => {
|
|||||||
case 'stretch':
|
case 'stretch':
|
||||||
const speed = new Fraction(operator.arguments_.amount).inverse().valueOf();
|
const speed = new Fraction(operator.arguments_.amount).inverse().valueOf();
|
||||||
return reify(pat).fast(speed);
|
return reify(pat).fast(speed);
|
||||||
|
case 'bjorklund':
|
||||||
|
return pat.euclid(operator.arguments_.pulse, operator.arguments_.step, operator.arguments_.rotation);
|
||||||
// TODO: case 'fixed-step': "%"
|
// TODO: case 'fixed-step': "%"
|
||||||
}
|
}
|
||||||
console.warn(`operator "${operator.type_}" not implemented`);
|
console.warn(`operator "${operator.type_}" not implemented`);
|
||||||
|
|||||||
@ -543,3 +543,32 @@ stack(
|
|||||||
.fast(2 / 3)
|
.fast(2 / 3)
|
||||||
.tone(p.toDestination())
|
.tone(p.toDestination())
|
||||||
)`;
|
)`;
|
||||||
|
|
||||||
|
export const festivalOfFingers = `const chords = "<Cm7 Fm7 G7 F#7>";
|
||||||
|
piano().then(p=>stack(
|
||||||
|
chords.voicings().struct("x(3,8,-1)").velocity(.5).off(1/7,x=>x.transpose(12).velocity(.2)),
|
||||||
|
chords.rootNotes(2).struct("x(4,8,-2)"),
|
||||||
|
chords.rootNotes(4)
|
||||||
|
.scale(slowcat('C minor','F dorian','G dorian','F# mixolydian'))
|
||||||
|
.struct("x(3,8,-2)".fast(2))
|
||||||
|
.scaleTranspose("0 4 0 6".early(".125 .5")).layer(scaleTranspose("0,<2 [4,6] [5,7]>/4"))
|
||||||
|
).slow(2)
|
||||||
|
//.pianoroll()
|
||||||
|
.velocity(sine.struct("x*8").add(3/5).mul(2/5).fast(8))
|
||||||
|
.tone(p.chain(out())))`;
|
||||||
|
|
||||||
|
export const festivalOfFingers2 = `const chords = "<Cm7 Fm7 G7 F#7 >";
|
||||||
|
const scales = slowcat('C minor','F dorian','G dorian','F# mixolydian')
|
||||||
|
piano().then(p=>stack(
|
||||||
|
chords.voicings().struct("x(3,8,-1)").velocity(.5).off(1/7,x=>x.transpose(12).velocity(.2)),
|
||||||
|
chords.rootNotes(2).struct("x(4,8)"),
|
||||||
|
chords.rootNotes(4)
|
||||||
|
.scale(scales)
|
||||||
|
.struct("x(3,8,-2)".fast(2))
|
||||||
|
.scaleTranspose("0 4 0 6".early(".125 .5")).layer(scaleTranspose("0,<2 [4,6] [5,7]>/3"))
|
||||||
|
).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))
|
||||||
|
// .pianoroll()
|
||||||
|
.tone(p.chain(out())).fast(3/4)
|
||||||
|
)`;
|
||||||
|
|||||||
@ -180,13 +180,13 @@ In essence, the `x!n` is like a shortcut for `[x*n]@n`.
|
|||||||
|
|
||||||
Compared to [tidal mini notation](https://tidalcycles.org/docs/patternlib/tutorials/mini_notation/), the following mini notation features are missing from Strudel:
|
Compared to [tidal mini notation](https://tidalcycles.org/docs/patternlib/tutorials/mini_notation/), the following mini notation features are missing from Strudel:
|
||||||
|
|
||||||
- Tie symbols "\_"
|
- [x] Euclidean algorithm "c3(3,2,1)" TODO: document
|
||||||
- Euclidean algorithm "c3(3,2,1)"
|
- [ ] Tie symbols "\_"
|
||||||
- feet marking "."
|
- [ ] feet marking "."
|
||||||
- random choice "|"
|
- [ ] random choice "|"
|
||||||
- Random removal "?"
|
- [ ] Random removal "?"
|
||||||
- Polymetric sequences "{ ... }"
|
- [ ] Polymetric sequences "{ ... }"
|
||||||
- Fixed steps using "%"
|
- [ ] Fixed steps using "%"
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user