implement random choice in mini notation

this will require update to krill-parser.js (aggregated
in later commit) to work properly
This commit is contained in:
Bradford Powell 2022-07-29 18:54:53 -04:00
parent 964ee68974
commit f858d89f7b
2 changed files with 25 additions and 6 deletions

View File

@ -8,6 +8,7 @@ This program is free software: you can redistribute it and/or modify it under th
// a sequence = a serie of elements placed between quotes // a sequence = a serie of elements placed between quotes
// a stack = a serie of vertically aligned slices sharing the same overall length // a stack = a serie of vertically aligned slices sharing the same overall length
// a slice = a serie of horizontally aligned elements // a slice = a serie of horizontally aligned elements
// a choose = a serie of elements, one of which is chosen at random
{ {
@ -81,7 +82,8 @@ DIGIT = [0-9]
// ------------------ delimiters --------------------------- // ------------------ delimiters ---------------------------
ws "whitespace" = [ \n\r\t]* ws "whitespace" = [ \n\r\t]*
comma = ws "," ws; comma = ws "," ws
pipe = ws "|" ws
quote = '"' / "'" quote = '"' / "'"
// ------------------ steps and cycles --------------------------- // ------------------ steps and cycles ---------------------------
@ -91,7 +93,7 @@ step_char = [0-9a-zA-Z~] / "-" / "#" / "." / "^" / "_" / ":"
step = ws chars:step_char+ ws { return chars.join("") } step = ws chars:step_char+ ws { return chars.join("") }
// define a sub cycle e.g. [1 2, 3 [4]] // define a sub cycle e.g. [1 2, 3 [4]]
sub_cycle = ws "[" ws s:stack ws "]" ws { return s} sub_cycle = ws "[" ws s:stack_or_choose ws "]" ws { return s}
// define a timeline e.g <1 3 [3 5]>. We simply defer to a stack and change the alignement // define a timeline e.g <1 3 [3 5]>. We simply defer to a stack and change the alignement
timeline = ws "<" ws sc:single_cycle ws ">" ws timeline = ws "<" ws sc:single_cycle ws ">" ws
@ -135,14 +137,22 @@ single_cycle = s:(slice_with_modifier)+
{ return new PatternStub(s,"h"); } { return new PatternStub(s,"h"); }
// a stack is a serie of vertically aligned single cycles, separated by a comma // a stack is a serie of vertically aligned single cycles, separated by a comma
stack_tail = tail:(comma @single_cycle)+
{ return { alignment: 'v', list: tail }; }
// a choose is a serie of pipe-separated single cycles, one of which is chosen
// at random each time through the pattern
choose_tail = tail:(pipe @single_cycle)+
{ return { alignment: 'r', list: tail }; }
// if the stack contains only one element, we don't create a stack but return the // if the stack contains only one element, we don't create a stack but return the
// underlying element // underlying element
stack = c:single_cycle cs:(comma v:single_cycle { return v})* stack_or_choose = head:single_cycle tail:(stack_tail / choose_tail)?
{ if (cs.length == 0 && c instanceof Object) { return c;} else { cs.unshift(c); return new PatternStub(cs,"v");} } { if (tail && tail.list.length > 0) { return new PatternStub([head, ...tail.list], tail.alignment); } else { return head; } }
// a sequence is a quoted stack // a sequence is a quoted stack
sequence = ws quote s:stack quote sequence = ws quote sc:stack_or_choose quote
{ return s; } { return sc; }
// ------------------ operators --------------------------- // ------------------ operators ---------------------------

View File

@ -10,6 +10,12 @@ import { addMiniLocations } from '@strudel.cycles/eval/shapeshifter.mjs';
const { pure, Pattern, Fraction, stack, slowcat, sequence, timeCat, silence, reify } = strudel; const { pure, Pattern, Fraction, stack, slowcat, sequence, timeCat, silence, reify } = strudel;
var _seedState = 0;
function _nextSeed() {
return _seedState++;
}
const applyOptions = (parent) => (pat, i) => { const applyOptions = (parent) => (pat, i) => {
const ast = parent.source_[i]; const ast = parent.source_[i];
const options = ast.options_; const options = ast.options_;
@ -84,6 +90,9 @@ export function patternifyAST(ast) {
if (alignment === 'v') { if (alignment === 'v') {
return stack(...children); return stack(...children);
} }
if (alignment === 'r') {
return strudel.chooseInWith(strudel.rand.early(0.0001 * _nextSeed()).segment(1), children);
}
const weightedChildren = ast.source_.some((child) => !!child.options_?.weight); const weightedChildren = ast.source_.some((child) => !!child.options_?.weight);
if (!weightedChildren && alignment === 't') { if (!weightedChildren && alignment === 't') {
return slowcat(...children); return slowcat(...children);