Experimental rejig of the pattern composers.

Now `restart` is `setRestart`, use `constRestart` for the old behavior.
Same for `reset`.
This commit is contained in:
alex 2022-04-24 01:02:32 +01:00
parent 08f8a7a17c
commit 5c3f095ef2

View File

@ -135,6 +135,11 @@ export class Pattern {
return this._filterEvents((hap) => hap.hasOnset());
}
discreteOnly() {
// removes continuous events that don't have a 'whole' timespan
return this._filterEvents((hap) => hap.whole);
}
_appWhole(whole_func, pat_val) {
// Assumes 'this' is a pattern of functions, and given a function to
// resolve wholes, applies a given pattern of values to that
@ -247,13 +252,13 @@ export class Pattern {
);
}
_opLeft(other, func) {
_op(other, func) {
return this.fmap(func).appLeft(reify(other));
}
_opRight(other, func) {
_opFlip(other, func) {
return this.fmap(func).appRight(reify(other));
}
_opBoth(other, func) {
_opSect(other, func) {
return this.fmap(func).appBoth(reify(other));
}
_opSqueeze(other, func) {
@ -265,6 +270,14 @@ export class Pattern {
const otherPat = reify(other);
return otherPat.fmap((a) => thisPat.fmap((b) => func(b)(a)))._squeezeJoin();
}
_opReset(other, func) {
const otherPat = reify(other);
return otherPat.fmap((b) => this.fmap((a) => func(a)(b)))._resetJoin();
}
_opRestart(other, func) {
const otherPat = reify(other);
return otherPat.fmap((b) => this.fmap((a) => func(a)(b)))._restartJoin();
}
_asNumber(silent = false) {
return this._withEvent((event) => {
@ -382,6 +395,33 @@ export class Pattern {
return this.innerBind(id);
}
_resetJoin(restart=false) {
const pat_of_pats = this;
return new Pattern((state) => {
return pat_of_pats
.discreteOnly()
.query(state)
.map((outer_hap) => {
return outer_hap.value
.late(restart ? outer_hap.whole.begin : outer_hap.whole.begin.cyclePos())
.query(state)
.map((inner_hap) =>
new Hap(
inner_hap.whole ? inner_hap.whole.intersection(outer_hap.whole) : undefined,
inner_hap.part.intersection(outer_hap.part),
inner_hap.value,
).setContext(outer_hap.combineContext(inner_hap)),
)
.filter((hap) => hap.part);
})
.flat();
});
}
_restartJoin() {
return this._resetJoin(true);
}
_squeezeJoin() {
const pat_of_pats = this;
function query(state) {
@ -721,21 +761,6 @@ export class Pattern {
_velocity(velocity) {
return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity }));
}
restart(pat) {
pat = reify(pat);
return new Pattern((state) =>
pat
.query(state)
.map((event) => {
const resetSpan = new TimeSpan(event.part.begin.sub(event.whole.begin), event.duration);
return this.query(new State(resetSpan)).map((hap) =>
hap.withSpan((s) => s.withTime((t) => t.add(event.whole.begin))).setContext(hap.combineContext(event)),
);
})
.flat(),
);
}
}
// pattern composers
@ -757,6 +782,23 @@ const composers = {
},
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()],
@ -764,21 +806,14 @@ const composers = {
};
for (const [name, op] of Object.entries(composers)) {
Pattern.prototype[name] = function (...other) {
return op[1](this)._opLeft(sequence(other), op[0]);
};
Pattern.prototype[name + 'Flip'] = function (...other) {
return op[1](this)._opRight(sequence(other), op[0]);
};
Pattern.prototype[name + 'Sect'] = function (...other) {
return op[1](this)._opBoth(sequence(other), op[0]);
};
Pattern.prototype[name + 'Squeeze'] = function (...other) {
return op[1](this)._opSqueeze(sequence(other), op[0]);
};
Pattern.prototype[name + 'SqueezeFlip'] = function (...other) {
return op[1](this)._opSqueezeFlip(sequence(other), op[0]);
};
for (const opType of ['', 'Flip', 'Sect', 'Squeeze', 'SqueezeFlip', 'Reset', 'Restart']) {
Pattern.prototype[name + opType] = function (...other) {
return op[1](this)['_op' + opType](sequence(other), op[0]);
};
if (name === "set" && opType !== '') {
Pattern.prototype[opType.toLowerCase()] = Pattern.prototype[name + opType];
}
}
}
// methods of Pattern that get callable factories