mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 13:48:40 +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$f4 = function(a) { return { weight: 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$f8 = function(a) { return { operator : { type_: "stretch", arguments_ :{ amount:"1/"+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$f15 = function(s) { return { name: "struct", args: { sequence: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$f19 = 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() {
|
||||
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;
|
||||
if (input.charCodeAt(peg$currPos) === 40) {
|
||||
@ -1043,16 +1043,26 @@ function peg$parse(input, options) {
|
||||
s7 = peg$parsenumber();
|
||||
if (s7 !== peg$FAILED) {
|
||||
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) {
|
||||
s9 = peg$c17;
|
||||
s13 = peg$c17;
|
||||
peg$currPos++;
|
||||
} else {
|
||||
s9 = peg$FAILED;
|
||||
s13 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e24); }
|
||||
}
|
||||
if (s9 !== peg$FAILED) {
|
||||
if (s13 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f6(s3, s7);
|
||||
s0 = peg$f6(s3, s7, s11);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
@ -1383,7 +1393,7 @@ function peg$parse(input, options) {
|
||||
}
|
||||
|
||||
function peg$parsebjorklund() {
|
||||
var s0, s1, s2, s3, s4, s5;
|
||||
var s0, s1, s2, s3, s4, s5, s6, s7;
|
||||
|
||||
s0 = peg$currPos;
|
||||
if (input.substr(peg$currPos, 6) === peg$c23) {
|
||||
@ -1400,8 +1410,13 @@ function peg$parse(input, options) {
|
||||
s4 = peg$parsews();
|
||||
s5 = peg$parseint();
|
||||
if (s5 !== peg$FAILED) {
|
||||
s6 = peg$parsews();
|
||||
s7 = peg$parseint();
|
||||
if (s7 === peg$FAILED) {
|
||||
s7 = null;
|
||||
}
|
||||
peg$savedPos = s0;
|
||||
s0 = peg$f17(s3, s5);
|
||||
s0 = peg$f17(s3, s5, s7);
|
||||
} else {
|
||||
peg$currPos = s0;
|
||||
s0 = peg$FAILED;
|
||||
|
||||
@ -104,8 +104,8 @@ slice_weight = "@" a:number
|
||||
slice_replicate = "!"a:number
|
||||
{ return { replicate: a } }
|
||||
|
||||
slice_bjorklund = "(" ws p:number ws comma ws s:number ws")"
|
||||
{ return { operator : { type_: "bjorklund", arguments_ :{ pulse: p, step:s } } } }
|
||||
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, rotation:r || 0 } } } }
|
||||
|
||||
slice_slow = "/"a:number
|
||||
{ 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
|
||||
{ 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) }}}
|
||||
|
||||
slow = "slow" ws a:number
|
||||
|
||||
11
repl/package-lock.json
generated
11
repl/package-lock.json
generated
@ -7,6 +7,7 @@
|
||||
"dependencies": {
|
||||
"@tonaljs/tonal": "^4.6.5",
|
||||
"@tonejs/piano": "^0.2.1",
|
||||
"bjork": "^0.0.1",
|
||||
"chord-voicings": "^0.0.1",
|
||||
"codemirror": "^5.65.1",
|
||||
"estraverse": "^5.3.0",
|
||||
@ -4195,6 +4196,11 @@
|
||||
"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": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
@ -15511,6 +15517,11 @@
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true
|
||||
},
|
||||
"bjork": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bjork/-/bjork-0.0.1.tgz",
|
||||
"integrity": "sha1-br1a3pkWSwvgMIeI1kaRQ9XJrZw="
|
||||
},
|
||||
"bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"dependencies": {
|
||||
"@tonaljs/tonal": "^4.6.5",
|
||||
"@tonejs/piano": "^0.2.1",
|
||||
"bjork": "^0.0.1",
|
||||
"chord-voicings": "^0.0.1",
|
||||
"codemirror": "^5.65.1",
|
||||
"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 './xen.mjs';
|
||||
import './tune.mjs';
|
||||
import './tune.mjs';
|
||||
import './euclid.mjs';
|
||||
import euclid from './euclid.mjs';
|
||||
import './pianoroll.mjs';
|
||||
import './draw.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
|
||||
|
||||
// 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) => {
|
||||
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':
|
||||
const speed = new Fraction(operator.arguments_.amount).inverse().valueOf();
|
||||
return reify(pat).fast(speed);
|
||||
case 'bjorklund':
|
||||
return pat.euclid(operator.arguments_.pulse, operator.arguments_.step, operator.arguments_.rotation);
|
||||
// TODO: case 'fixed-step': "%"
|
||||
}
|
||||
console.warn(`operator "${operator.type_}" not implemented`);
|
||||
|
||||
@ -543,3 +543,32 @@ stack(
|
||||
.fast(2 / 3)
|
||||
.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:
|
||||
|
||||
- Tie symbols "\_"
|
||||
- Euclidean algorithm "c3(3,2,1)"
|
||||
- feet marking "."
|
||||
- random choice "|"
|
||||
- Random removal "?"
|
||||
- Polymetric sequences "{ ... }"
|
||||
- Fixed steps using "%"
|
||||
- [x] Euclidean algorithm "c3(3,2,1)" TODO: document
|
||||
- [ ] Tie symbols "\_"
|
||||
- [ ] feet marking "."
|
||||
- [ ] random choice "|"
|
||||
- [ ] Random removal "?"
|
||||
- [ ] Polymetric sequences "{ ... }"
|
||||
- [ ] Fixed steps using "%"
|
||||
|
||||
<br />
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user