standardise on hap rather than event, especially in function names

This commit is contained in:
alex
2022-05-05 17:20:36 +01:00
parent b0dfb44e96
commit f8f744dd87
13 changed files with 159 additions and 153 deletions
+68 -65
View File
@@ -24,14 +24,14 @@ export class Pattern {
}
/**
* query events insude the tiven time span
* query haps insude the tiven time span
*
* @param {Fraction | number} begin from time
* @param {Fraction | number} end to time
* @returns Hap[]
* @example
* const pattern = sequence('a', ['b', 'c']);
* const events = pattern.queryArc(0, 1);
* const haps = pattern.queryArc(0, 1);
*/
queryArc(begin, end) {
return this.query(new State(new TimeSpan(begin, end)));
@@ -39,7 +39,7 @@ export class Pattern {
/**
* Returns a new pattern, with queries split at cycle boundaries. This makes
* some calculations easier to express, as all events are then constrained to
* some calculations easier to express, as all haps are then constrained to
* happen within a cycle.
* @returns Pattern
*/
@@ -78,40 +78,43 @@ export class Pattern {
* @param {Function} func
* @returns Pattern
*/
withEventSpan(func) {
withHapSpan(func) {
return new Pattern((state) => this.query(state).map((hap) => hap.withSpan(func)));
}
/**
* As with {@link Pattern#withEventSpan|withEventSpan}, but the function is applied to both the
* As with {@link Pattern#withHapSpan|withHapSpan}, but the function is applied to both the
* begin and end time of the hap timespans.
* @param {Function} func the function to apply
* @returns Pattern
*/
withEventTime(func) {
// Returns a new pattern, with the function applied to both the begin
// and end of each event timespan.
return this.withEventSpan((span) => span.withTime(func));
withHapTime(func) {
return this.withHapSpan((span) => span.withTime(func));
}
_withEvents(func) {
/**
* Returns a new pattern with the given function applied to all haps returned by queries.
* @param {Function} func
* @returns Pattern
*/
_withHaps(func) {
return new Pattern((state) => func(this.query(state)));
}
_withEvent(func) {
return this._withEvents((events) => events.map(func));
_withHap(func) {
return this._withHaps((haps) => haps.map(func));
}
_setContext(context) {
return this._withEvent((event) => event.setContext(context));
return this._withHap((hap) => hap.setContext(context));
}
_withContext(func) {
return this._withEvent((event) => event.setContext(func(event.context)));
return this._withHap((hap) => hap.setContext(func(hap.context)));
}
_stripContext() {
return this._withEvent((event) => event.setContext({}));
return this._withHap((hap) => hap.setContext({}));
}
withLocation(start, end) {
@@ -153,7 +156,7 @@ export class Pattern {
/**
* Returns a new pattern, with the function applied to the value of
* each event. It has the alias {@link Pattern#fmap|fmap}.
* each hap. It has the alias {@link Pattern#fmap|fmap}.
* @param {Function} func
* @returns Pattern
*/
@@ -168,8 +171,8 @@ export class Pattern {
return this.withValue(func);
}
_filterEvents(event_test) {
return new Pattern((state) => this.query(state).filter(event_test));
_filterHaps(hap_test) {
return new Pattern((state) => this.query(state).filter(hap_test));
}
_filterValues(value_test) {
@@ -187,15 +190,15 @@ export class Pattern {
* @returns Pattern
*/
onsetsOnly() {
// Returns a new pattern that will only return events where the start
// Returns a new pattern that will only return haps where the start
// of the 'whole' timespan matches the start of the 'part'
// timespan, i.e. the events that include their 'onset'.
return this._filterEvents((hap) => hap.hasOnset());
// timespan, i.e. the haps that include their 'onset'.
return this._filterHaps((hap) => hap.hasOnset());
}
discreteOnly() {
// removes continuous events that don't have a 'whole' timespan
return this._filterEvents((hap) => hap.whole);
// removes continuous haps that don't have a 'whole' timespan
return this._filterHaps((hap) => hap.whole);
}
_appWhole(whole_func, pat_val) {
@@ -204,22 +207,22 @@ export class Pattern {
// pattern of functions.
const pat_func = this;
const query = function (state) {
const event_funcs = pat_func.query(state);
const event_vals = pat_val.query(state);
const apply = function (event_func, event_val) {
const s = event_func.part.intersection(event_val.part);
const hap_funcs = pat_func.query(state);
const hap_vals = pat_val.query(state);
const apply = function (hap_func, hap_val) {
const s = hap_func.part.intersection(hap_val.part);
if (s == undefined) {
return undefined;
}
return new Hap(
whole_func(event_func.whole, event_val.whole),
whole_func(hap_func.whole, hap_val.whole),
s,
event_func.value(event_val.value),
event_val.combineContext(event_func),
hap_func.value(hap_val.value),
hap_val.combineContext(hap_func),
);
};
return flatten(
event_funcs.map((event_func) => removeUndefineds(event_vals.map((event_val) => apply(event_func, event_val)))),
hap_funcs.map((hap_func) => removeUndefineds(hap_vals.map((hap_val) => apply(hap_func, hap_val)))),
);
};
return new Pattern(query);
@@ -262,8 +265,8 @@ export class Pattern {
const query = function (state) {
const haps = [];
for (const hap_func of pat_func.query(state)) {
const event_vals = pat_val.query(state.setSpan(hap_func.wholeOrPart()));
for (const hap_val of event_vals) {
const hap_vals = pat_val.query(state.setSpan(hap_func.wholeOrPart()));
for (const hap_val of hap_vals) {
const new_whole = hap_func.whole;
const new_part = hap_func.part.intersection(hap_val.part);
if (new_part) {
@@ -326,9 +329,9 @@ export class Pattern {
);
}
_sortEventsByPart() {
return this._withEvents((events) =>
events.sort((a, b) =>
_sortHapsByPart() {
return this._withHaps((haps) =>
haps.sort((a, b) =>
a.part.begin
.sub(b.part.begin)
.or(a.part.end.sub(b.part.end))
@@ -365,21 +368,21 @@ export class Pattern {
}
_asNumber(dropfails = false, softfail = false) {
return this._withEvent((event) => {
const asNumber = Number(event.value);
return this._withHap((hap) => {
const asNumber = Number(hap.value);
if (!isNaN(asNumber)) {
return event.withValue(() => asNumber);
return hap.withValue(() => asNumber);
}
const specialValue = {
e: Math.E,
pi: Math.PI,
}[event.value];
}[hap.value];
if (typeof specialValue !== 'undefined') {
return event.withValue(() => specialValue);
return hap.withValue(() => specialValue);
}
if (isNote(event.value)) {
if (isNote(hap.value)) {
// set context type to midi to let the player know its meant as midi number and not as frequency
return new Hap(event.whole, event.part, toMidi(event.value), { ...event.context, type: 'midi' });
return new Hap(hap.whole, hap.part, toMidi(hap.value), { ...hap.context, type: 'midi' });
}
if (dropfail) {
// return 'nothing'
@@ -387,10 +390,10 @@ export class Pattern {
}
if (softfail) {
// return original hap
return event;
return hap;
}
throw new Error('cannot parse as number: "' + event.value + '"');
return event;
throw new Error('cannot parse as number: "' + hap.value + '"');
return hap;
});
if (dropfail) {
return result._removeUndefineds();
@@ -466,7 +469,7 @@ export class Pattern {
join() {
// Flattens a pattern of patterns into a pattern, where wholes are
// the intersection of matched inner and outer events.
// the intersection of matched inner and outer haps.
return this.bind(id);
}
@@ -476,7 +479,7 @@ export class Pattern {
outerJoin() {
// Flattens a pattern of patterns into a pattern, where wholes are
// taken from inner events.
// taken from inner haps.
return this.outerBind(id);
}
@@ -486,35 +489,35 @@ export class Pattern {
innerJoin() {
// Flattens a pattern of patterns into a pattern, where wholes are
// taken from inner events.
// taken from inner haps.
return this.innerBind(id);
}
// Flatterns patterns of patterns, by retriggering/resetting inner patterns at onsets of outer pattern events
// Flatterns patterns of patterns, by retriggering/resetting inner patterns at onsets of outer pattern haps
_trigJoin(cycleZero = false) {
const pat_of_pats = this;
return new Pattern((state) => {
return (
pat_of_pats
// drop continuous events from the outer pattern.
// drop continuous haps from the outer pattern.
.discreteOnly()
.query(state)
.map((outer_hap) => {
return (
outer_hap.value
// trig = align the inner pattern cycle start to outer pattern events
// Trigzero = align the inner pattern cycle zero to outer pattern events
// trig = align the inner pattern cycle start to outer pattern haps
// Trigzero = align the inner pattern cycle zero to outer pattern haps
.late(cycleZero ? outer_hap.whole.begin : outer_hap.whole.begin.cyclePos())
.query(state)
.map((inner_hap) =>
new Hap(
// Supports continuous events in the inner pattern
// Supports continuous haps in the inner pattern
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)),
)
// Drop events that didn't intersect
// Drop haps that didn't intersect
.filter((hap) => hap.part)
);
})
@@ -604,7 +607,7 @@ export class Pattern {
const end = cycle.add(span.end.sub(cycle).div(factor).min(1));
return new TimeSpan(begin, end);
};
return this.withQuerySpan(qf).withEventSpan(ef)._splitQueries();
return this.withQuerySpan(qf).withHapSpan(ef)._splitQueries();
}
_compress(b, e) {
@@ -620,7 +623,7 @@ export class Pattern {
_fast(factor) {
const fastQuery = this.withQueryTime((t) => t.mul(factor));
return fastQuery.withEventTime((t) => t.div(factor));
return fastQuery.withHapTime((t) => t.div(factor));
}
_slow(factor) {
@@ -655,7 +658,7 @@ export class Pattern {
_early(offset) {
// Equivalent of Tidal's <~ operator
offset = Fraction(offset);
return this.withQueryTime((t) => t.add(offset)).withEventTime((t) => t.sub(offset));
return this.withQueryTime((t) => t.add(offset)).withHapTime((t) => t.sub(offset));
}
_late(offset) {
@@ -669,7 +672,7 @@ export class Pattern {
s = Fraction(s);
const d = e.sub(s);
return this.withQuerySpan((span) => span.withCycle((t) => t.mul(d).add(s)))
.withEventSpan((span) => span.withCycle((t) => t.sub(s).div(d)))
.withHapSpan((span) => span.withCycle((t) => t.sub(s).div(d)))
._splitQueries();
}
@@ -709,7 +712,7 @@ export class Pattern {
}
log() {
return this._withEvent((e) => {
return this._withHap((e) => {
return e.setContext({ ...e.context, logs: (e.context?.logs || []).concat([e.show()]) });
});
}
@@ -877,14 +880,14 @@ export class Pattern {
return silence;
}
// sets absolute duration of events
// sets absolute duration of haps
_duration(value) {
return this.withEventSpan((span) => new TimeSpan(span.begin, span.begin.add(value)));
return this.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(value)));
}
// sets event relative duration of events
// sets hap relative duration of haps
_legato(value) {
return this.withEventSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value))));
return this.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value))));
}
_velocity(velocity) {
@@ -1101,7 +1104,7 @@ export function slowcat(...pats) {
// For example if three patterns are slowcat-ed, the fourth cycle of the result should
// be the second (rather than fourth) cycle from the first pattern.
const offset = span.begin.floor().sub(span.begin.div(pats.length).floor());
return pat.withEventTime((t) => t.add(offset)).query(state.setSpan(span.withTime((t) => t.sub(offset))));
return pat.withHapTime((t) => t.add(offset)).query(state.setSpan(span.withTime((t) => t.sub(offset))));
};
return new Pattern(query)._splitQueries();
}