From 8c9e06c32904d084438c7051804d5af353d9e692 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 12 Jun 2023 22:39:32 +0200 Subject: [PATCH] - clip now works like legato in tidal - supports floats - hap.duration now respects clip value - hap.endClipped is now end*clip - visualizations show clipped length - clip(0) will now be silence --- packages/codemirror/codemirror.mjs | 2 +- packages/core/hap.mjs | 6 +++++- packages/core/pianoroll.mjs | 4 ++-- packages/react/src/hooks/useHighlighting.mjs | 2 +- packages/webaudio/sampler.mjs | 4 ++-- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/codemirror/codemirror.mjs b/packages/codemirror/codemirror.mjs index 39429432..a466e621 100644 --- a/packages/codemirror/codemirror.mjs +++ b/packages/codemirror/codemirror.mjs @@ -133,7 +133,7 @@ export class StrudelMirror { this.code = initialCode; this.drawer = new Drawer((haps, time) => { - const currentFrame = haps.filter((hap) => time >= hap.whole.begin && time <= hap.whole.end); + const currentFrame = haps.filter((hap) => time >= hap.whole.begin && time <= hap.endClipped); this.highlight(currentFrame); onDraw?.(haps, time, currentFrame); }, drawTime); diff --git a/packages/core/hap.mjs b/packages/core/hap.mjs index c9c91c3b..6a1eb987 100644 --- a/packages/core/hap.mjs +++ b/packages/core/hap.mjs @@ -32,7 +32,11 @@ export class Hap { } get duration() { - return this.whole.end.sub(this.whole.begin); + return this.whole.end.sub(this.whole.begin).mul(typeof this.value?.clip === 'number' ? this.value?.clip : 1); + } + + get endClipped() { + return this.whole.begin.add(this.duration); } wholeOrPart() { diff --git a/packages/core/pianoroll.mjs b/packages/core/pianoroll.mjs index 66b56dc8..02aac373 100644 --- a/packages/core/pianoroll.mjs +++ b/packages/core/pianoroll.mjs @@ -83,9 +83,9 @@ Pattern.prototype.pianoroll = function ({ ctx.fillRect(0, 0, w, h); } const inFrame = (event) => - (!hideNegative || event.whole.begin >= 0) && event.whole.begin <= t + to && event.whole.end >= t + from; + (!hideNegative || event.whole.begin >= 0) && event.whole.begin <= t + to && event.endClipped >= t + from; events.filter(inFrame).forEach((event) => { - const isActive = event.whole.begin <= t && event.whole.end > t; + const isActive = event.whole.begin <= t && event.endClipped > t; ctx.fillStyle = event.context?.color || inactive; ctx.strokeStyle = event.context?.color || active; ctx.globalAlpha = event.context.velocity ?? event.value?.gain ?? 1; diff --git a/packages/react/src/hooks/useHighlighting.mjs b/packages/react/src/hooks/useHighlighting.mjs index 4ce2a936..26239871 100644 --- a/packages/react/src/hooks/useHighlighting.mjs +++ b/packages/react/src/hooks/useHighlighting.mjs @@ -17,7 +17,7 @@ function useHighlighting({ view, pattern, active, getTime }) { const begin = Math.max(lastEnd.current ?? audioTime, audioTime - 1 / 10, -0.01); // negative time seems buggy const span = [round(begin), round(audioTime + 1 / 60)]; lastEnd.current = span[1]; - highlights.current = highlights.current.filter((hap) => hap.whole.end > audioTime); // keep only highlights that are still active + highlights.current = highlights.current.filter((hap) => hap.endClipped > audioTime); // keep only highlights that are still active const haps = pattern.queryArc(...span).filter((hap) => hap.hasOnset()); highlights.current = highlights.current.concat(haps); // add potential new onsets view.dispatch({ effects: setHighlights.of({ haps: highlights.current }) }); // highlight all still active + new active haps diff --git a/packages/webaudio/sampler.mjs b/packages/webaudio/sampler.mjs index cda4415e..a3296a69 100644 --- a/packages/webaudio/sampler.mjs +++ b/packages/webaudio/sampler.mjs @@ -170,7 +170,7 @@ export async function onTriggerSample(t, value, onended, bank) { nudge = 0, // TODO: is this in seconds? cut, loop, - clip = 0, // if 1, samples will be cut off when the hap ends + clip = undefined, // if 1, samples will be cut off when the hap ends n = 0, note, speed = 1, // sample playback speed @@ -232,7 +232,7 @@ export async function onTriggerSample(t, value, onended, bank) { out.disconnect(); onended(); }; - const stop = (endTime, playWholeBuffer = !clip) => { + const stop = (endTime, playWholeBuffer = [undefined, false, null].includes(clip)) => { let releaseTime = endTime; if (playWholeBuffer) { releaseTime = t + (end - begin) * bufferDuration;