Merge pull request #965 from tidalcycles/legato-fix

remove legacy legato + duration implementations
This commit is contained in:
Felix Roos 2024-02-29 15:12:45 +01:00 committed by GitHub
commit 4cadbcbbdf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 49 additions and 90 deletions

View File

@ -400,19 +400,6 @@ export const { loopEnd, loope } = registerControl('loopEnd', 'loope');
* s("<bd sd>,hh*3").fast(2).crush("<16 8 7 6 5 4 3 2>")
*
*/
// TODO: currently duplicated with "native" legato
// TODO: superdirt legato will do more: https://youtu.be/dQPmE1WaD1k?t=419
/**
* a pattern of numbers from 0 to 1. Skips the beginning of each sample, e.g. `0.25` to cut off the first quarter from each sample.
*
* @name legato
* @param {number | Pattern} duration between 0 and 1, where 1 is the length of the whole hap time
* @noAutocomplete
* @example
* "c4 eb4 g4 bb4".legato("<0.125 .25 .5 .75 1 2 4>")
*
*/
// ['legato'],
// ['clhatdecay'],
export const { crush } = registerControl('crush');
/**
@ -1389,8 +1376,6 @@ export const { waveloss } = registerControl('waveloss');
*
*/
export const { density } = registerControl('density');
// TODO: midi effects?
export const { dur } = registerControl('dur');
// ['modwheel'],
export const { expression } = registerControl('expression');
export const { sustainpedal } = registerControl('sustainpedal');
@ -1455,16 +1440,27 @@ export const { val } = registerControl('val');
export const { cps } = registerControl('cps');
/**
* Multiplies the duration with the given number. Also cuts samples off at the end if they exceed the duration.
* In tidal, this would be done with legato, [which has a complicated history in strudel](https://github.com/tidalcycles/strudel/issues/111).
* For now, if you're coming from tidal, just think clip = legato.
*
* @name clip
* @synonyms legato
* @param {number | Pattern} factor >= 0
* @example
* note("c a f e").s("piano").clip("<.5 1 2>")
*
*/
export const { clip } = registerControl('clip');
export const { clip, legato } = registerControl('clip', 'legato');
/**
* Sets the duration of the event in cycles. Similar to clip / legato, it also cuts samples off at the end if they exceed the duration.
*
* @name duration
* @synonyms dur
* @param {number | Pattern} seconds >= 0
* @example
* note("c a f e").s("piano").dur("<.5 1 2>")
*
*/
export const { duration, dur } = registerControl('duration', 'dur');
// ZZFX
export const { zrand } = registerControl('zrand');

View File

@ -134,7 +134,7 @@ export class Drawer {
this.lastFrame = phase;
this.visibleHaps = (this.visibleHaps || [])
// filter out haps that are too far in the past (think left edge of screen for pianoroll)
.filter((h) => h.whole?.end >= phase - lookbehind - lookahead)
.filter((h) => h.endClipped >= phase - lookbehind - lookahead)
// add new haps with onset (think right edge bars scrolling in)
.concat(haps.filter((h) => h.hasOnset()));
const time = phase - lookahead;

View File

@ -3,6 +3,7 @@ hap.mjs - <short description TODO>
Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/strudel/blob/main/packages/core/hap.mjs>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import Fraction from './fraction.mjs';
export class Hap {
/*
@ -32,7 +33,16 @@ export class Hap {
}
get duration() {
return this.whole.end.sub(this.whole.begin).mul(typeof this.value?.clip === 'number' ? this.value?.clip : 1);
let duration;
if (typeof this.value?.duration === 'number') {
duration = Fraction(this.value.duration);
} else {
duration = this.whole.end.sub(this.whole.begin);
}
if (typeof this.value?.clip === 'number') {
return duration.mul(this.value.clip);
}
return duration;
}
get endClipped() {

View File

@ -2203,12 +2203,6 @@ export const bypass = register('bypass', function (on, pat) {
*/
export const ribbon = register('ribbon', (offset, cycles, pat) => pat.early(offset).restart(pure(1).slow(cycles)));
// sets absolute duration of haps
// TODO - fix
export const duration = register('duration', function (value, pat) {
return pat.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(value)));
});
export const hsla = register('hsla', (h, s, l, a, pat) => {
return pat.color(`hsla(${h}turn,${s * 100}%,${l * 100}%,${a})`);
});
@ -2241,21 +2235,6 @@ export const velocity = register('velocity', function (velocity, pat) {
return pat.withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity }));
});
/**
*
* Multiplies the hap duration with the given factor.
* With samples, `clip` might be a better function to use ([more info](https://github.com/tidalcycles/strudel/pull/598))
* @name legato
* @memberof Pattern
* @example
* note("c3 eb3 g3 c4").legato("<.25 .5 1 2>")
*/
// TODO - fix
export const legato = register('legato', function (value, pat) {
value = Fraction(value);
return pat.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value))));
});
//////////////////////////////////////////////////////////////////////
// Control-related functions, i.e. ones that manipulate patterns of
// objects

View File

@ -251,7 +251,7 @@ export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
nudge = 0, // TODO: is this in seconds?
cut,
loop,
clip = undefined, // if 1, samples will be cut off when the hap ends
clip = undefined, // if set, samples will be cut off when the hap ends
n = 0,
note,
speed = 1, // sample playback speed

View File

@ -15,7 +15,6 @@ const hap2value = (hap) => {
return { ...hap.value, velocity: hap.context.velocity };
};
// TODO: bind logger
export const webaudioOutputTrigger = (t, hap, ct, cps) => superdough(hap2value(hap), t - ct, hap.duration / cps, cps);
export const webaudioOutput = (hap, deadline, hapDuration) => superdough(hap2value(hap), deadline, hapDuration);

View File

@ -2001,6 +2001,27 @@ exports[`runs examples > example "dry" example index 0 1`] = `
]
`;
exports[`runs examples > example "duration" example index 0 1`] = `
[
"[ 0/1 → 1/4 | note:c s:piano duration:0.5 ]",
"[ 1/4 → 1/2 | note:a s:piano duration:0.5 ]",
"[ 1/2 → 3/4 | note:f s:piano duration:0.5 ]",
"[ 3/4 → 1/1 | note:e s:piano duration:0.5 ]",
"[ 1/1 → 5/4 | note:c s:piano duration:1 ]",
"[ 5/4 → 3/2 | note:a s:piano duration:1 ]",
"[ 3/2 → 7/4 | note:f s:piano duration:1 ]",
"[ 7/4 → 2/1 | note:e s:piano duration:1 ]",
"[ 2/1 → 9/4 | note:c s:piano duration:2 ]",
"[ 9/4 → 5/2 | note:a s:piano duration:2 ]",
"[ 5/2 → 11/4 | note:f s:piano duration:2 ]",
"[ 11/4 → 3/1 | note:e s:piano duration:2 ]",
"[ 3/1 → 13/4 | note:c s:piano duration:0.5 ]",
"[ 13/4 → 7/2 | note:a s:piano duration:0.5 ]",
"[ 7/2 → 15/4 | note:f s:piano duration:0.5 ]",
"[ 15/4 → 4/1 | note:e s:piano duration:0.5 ]",
]
`;
exports[`runs examples > example "early" example index 0 1`] = `
[
"[ -1/10 ⇜ (0/1 → 2/5) | s:hh ]",
@ -3521,48 +3542,6 @@ exports[`runs examples > example "layer" example index 0 1`] = `
]
`;
exports[`runs examples > example "legato" example index 0 1`] = `
[
"[ 0/1 → 1/32 | c4 ]",
"[ 1/4 → 9/32 | eb4 ]",
"[ 1/2 → 17/32 | g4 ]",
"[ 3/4 → 25/32 | bb4 ]",
"[ 1/1 → 17/16 | c4 ]",
"[ 5/4 → 21/16 | eb4 ]",
"[ 3/2 → 25/16 | g4 ]",
"[ 7/4 → 29/16 | bb4 ]",
"[ 2/1 → 17/8 | c4 ]",
"[ 9/4 → 19/8 | eb4 ]",
"[ 5/2 → 21/8 | g4 ]",
"[ 11/4 → 23/8 | bb4 ]",
"[ 3/1 → 51/16 | c4 ]",
"[ 13/4 → 55/16 | eb4 ]",
"[ 7/2 → 59/16 | g4 ]",
"[ 15/4 → 63/16 | bb4 ]",
]
`;
exports[`runs examples > example "legato" example index 0 2`] = `
[
"[ 0/1 → 1/16 | note:c3 ]",
"[ 1/4 → 5/16 | note:eb3 ]",
"[ 1/2 → 9/16 | note:g3 ]",
"[ 3/4 → 13/16 | note:c4 ]",
"[ 1/1 → 9/8 | note:c3 ]",
"[ 5/4 → 11/8 | note:eb3 ]",
"[ 3/2 → 13/8 | note:g3 ]",
"[ 7/4 → 15/8 | note:c4 ]",
"[ 2/1 → 9/4 | note:c3 ]",
"[ 9/4 → 5/2 | note:eb3 ]",
"[ 5/2 → 11/4 | note:g3 ]",
"[ 11/4 → 3/1 | note:c4 ]",
"[ 3/1 → 7/2 | note:c3 ]",
"[ 13/4 → 15/4 | note:eb3 ]",
"[ 7/2 → 4/1 | note:g3 ]",
"[ 15/4 → 17/4 | note:c4 ]",
]
`;
exports[`runs examples > example "leslie" example index 0 1`] = `
[
"[ 0/1 → 1/1 | n:0 s:supersquare leslie:0 ]",

View File

@ -34,11 +34,7 @@ Some of these have equivalent operators in the Mini Notation:
<JsDoc client:idle name="Pattern.late" h={0} />
## legato
<JsDoc client:idle name="Pattern.legato" h={0} />
## clip
## clip / legato
<JsDoc client:idle name="clip" h={0} />