mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-26 04:58:27 +00:00
Tidy up composers, supporting function patterns
This commit is contained in:
parent
a194b908e7
commit
df5ffb4736
@ -2,6 +2,7 @@ import TimeSpan from './timespan.mjs';
|
|||||||
import Fraction from './fraction.mjs';
|
import Fraction from './fraction.mjs';
|
||||||
import Hap from './hap.mjs';
|
import Hap from './hap.mjs';
|
||||||
import State from './state.mjs';
|
import State from './state.mjs';
|
||||||
|
import { unionWithObj } from './value.mjs';
|
||||||
|
|
||||||
import { isNote, toMidi, compose, removeUndefineds, flatten, id, listRange, curry, mod } from './util.mjs';
|
import { isNote, toMidi, compose, removeUndefineds, flatten, id, listRange, curry, mod } from './util.mjs';
|
||||||
|
|
||||||
@ -395,26 +396,36 @@ export class Pattern {
|
|||||||
return this.innerBind(id);
|
return this.innerBind(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
_resetJoin(restart=false) {
|
// Flatterns patterns of patterns, by resetting inner patterns at onsets of outer pattern events
|
||||||
|
_resetJoin(restart = false) {
|
||||||
const pat_of_pats = this;
|
const pat_of_pats = this;
|
||||||
return new Pattern((state) => {
|
return new Pattern((state) => {
|
||||||
return pat_of_pats
|
return (
|
||||||
.discreteOnly()
|
pat_of_pats
|
||||||
.query(state)
|
// drop continuous events from the outer pattern.
|
||||||
.map((outer_hap) => {
|
.discreteOnly()
|
||||||
return outer_hap.value
|
.query(state)
|
||||||
.late(restart ? outer_hap.whole.begin : outer_hap.whole.begin.cyclePos())
|
.map((outer_hap) => {
|
||||||
.query(state)
|
return (
|
||||||
.map((inner_hap) =>
|
outer_hap.value
|
||||||
new Hap(
|
// reset = align the inner pattern cycle start to outer pattern events
|
||||||
inner_hap.whole ? inner_hap.whole.intersection(outer_hap.whole) : undefined,
|
// restart = align the inner pattern cycle zero to outer pattern events
|
||||||
inner_hap.part.intersection(outer_hap.part),
|
.late(restart ? outer_hap.whole.begin : outer_hap.whole.begin.cyclePos())
|
||||||
inner_hap.value,
|
.query(state)
|
||||||
).setContext(outer_hap.combineContext(inner_hap)),
|
.map((inner_hap) =>
|
||||||
)
|
new Hap(
|
||||||
.filter((hap) => hap.part);
|
// Supports continuous events in the inner pattern
|
||||||
})
|
inner_hap.whole ? inner_hap.whole.intersection(outer_hap.whole) : undefined,
|
||||||
.flat();
|
inner_hap.part.intersection(outer_hap.part),
|
||||||
|
inner_hap.value,
|
||||||
|
).setContext(outer_hap.combineContext(inner_hap)),
|
||||||
|
)
|
||||||
|
// Drop events that didn't intersect
|
||||||
|
.filter((hap) => hap.part)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.flat()
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +436,7 @@ export class Pattern {
|
|||||||
_squeezeJoin() {
|
_squeezeJoin() {
|
||||||
const pat_of_pats = this;
|
const pat_of_pats = this;
|
||||||
function query(state) {
|
function query(state) {
|
||||||
const haps = pat_of_pats.query(state);
|
const haps = pat_of_pats.discreteOnly().query(state);
|
||||||
function flatHap(outerHap) {
|
function flatHap(outerHap) {
|
||||||
const pat = outerHap.value._compressSpan(outerHap.wholeOrPart().cycleArc());
|
const pat = outerHap.value._compressSpan(outerHap.wholeOrPart().cycleArc());
|
||||||
const innerHaps = pat.query(state.setSpan(outerHap.part));
|
const innerHaps = pat.query(state.setSpan(outerHap.part));
|
||||||
@ -763,54 +774,41 @@ export class Pattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO - adopt value.mjs fully..
|
||||||
|
function _composeOp(a, b, func) {
|
||||||
|
function _nonFunctionObject(x) {
|
||||||
|
return x instanceof Object && (!(x instanceof Function))
|
||||||
|
}
|
||||||
|
if (_nonFunctionObject(a) || _nonFunctionObject(b)) {
|
||||||
|
if (!_nonFunctionObject(a)) {
|
||||||
|
a = { value: a };
|
||||||
|
}
|
||||||
|
if (!_nonFunctionObject(b)) {
|
||||||
|
b = { value: b };
|
||||||
|
}
|
||||||
|
return unionWithObj(a, b, func);
|
||||||
|
}
|
||||||
|
return func(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
// pattern composers
|
// pattern composers
|
||||||
const composers = {
|
const composers = {
|
||||||
set: [
|
set: (a, b) => b,
|
||||||
(a) => (b) => {
|
const: id,
|
||||||
// If an object is involved, do a union, discarding matching keys from a.
|
add: (a, b) => a + b,
|
||||||
// Otherwise, just return b.
|
sub: (a, b) => a - b,
|
||||||
if (a instanceof Object || b instanceof Object) {
|
mul: (a, b) => a * b,
|
||||||
if (!a instanceof Object) {
|
div: (a, b) => a / b,
|
||||||
a = { value: a };
|
mod: mod,
|
||||||
}
|
func: (a, b) => b(a)
|
||||||
if (!b instanceof Object) {
|
|
||||||
b = { value: b };
|
|
||||||
}
|
|
||||||
return Object.assign({}, a, b);
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
},
|
|
||||||
id,
|
|
||||||
],
|
|
||||||
const: [
|
|
||||||
(a) => (b) => {
|
|
||||||
// If an object is involved, do a union, discarding matching keys from a.
|
|
||||||
// Otherwise, just return b.
|
|
||||||
if (a instanceof Object || b instanceof Object) {
|
|
||||||
if (!a instanceof Object) {
|
|
||||||
a = { value: a };
|
|
||||||
}
|
|
||||||
if (!b instanceof Object) {
|
|
||||||
b = { value: b };
|
|
||||||
}
|
|
||||||
return Object.assign({}, b, a);
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
},
|
|
||||||
id,
|
|
||||||
],
|
|
||||||
add: [(a) => (b) => a + b, (x) => x._asNumber()],
|
|
||||||
sub: [(a) => (b) => a - b, (x) => x._asNumber()],
|
|
||||||
mul: [(a) => (b) => a * b, (x) => x._asNumber()],
|
|
||||||
div: [(a) => (b) => a / b, (x) => x._asNumber()],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [name, op] of Object.entries(composers)) {
|
for (const [name, op] of Object.entries(composers)) {
|
||||||
for (const opType of ['', 'Flip', 'Sect', 'Squeeze', 'SqueezeFlip', 'Reset', 'Restart']) {
|
for (const opType of ['', 'Flip', 'Sect', 'Squeeze', 'SqueezeFlip', 'Reset', 'Restart']) {
|
||||||
Pattern.prototype[name + opType] = function (...other) {
|
Pattern.prototype[name + opType] = function (...other) {
|
||||||
return op[1](this)['_op' + opType](sequence(other), op[0]);
|
return this['_op' + opType](sequence(other), (a) => (b) => _composeOp(a, b, op));
|
||||||
};
|
};
|
||||||
if (name === "set" && opType !== '') {
|
if (name === 'set' && opType !== '') {
|
||||||
Pattern.prototype[opType.toLowerCase()] = Pattern.prototype[name + opType];
|
Pattern.prototype[opType.toLowerCase()] = Pattern.prototype[name + opType];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user