mirror of
https://codeberg.org/uzu/strudel
synced 2026-08-10 16:09:35 -04:00
standardise on hap rather than event, especially in function names
This commit is contained in:
+68
-65
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user