mirror of
https://codeberg.org/uzu/strudel
synced 2026-08-13 00:50:31 -04:00
add loopBegin and loopEnd
This commit is contained in:
@@ -193,16 +193,34 @@ const generic_params = [
|
||||
*/
|
||||
['end'],
|
||||
/**
|
||||
* Loops the sample (from `begin` to `end`) the specified number of times.
|
||||
* Note that the tempo of the loop is not synced with the cycle tempo.
|
||||
* Loops the sample from `loopBegin` to `loopEnd`. If one or both of those are set,
|
||||
* the sample is looped to fill the event duration, instead of playing the whole sample.
|
||||
* If only `loopBegin` is set, `loopEnd` defaults to 1.
|
||||
* If only `loopEnd` is set, `loopBegin` defaults to 0.
|
||||
*
|
||||
* @name loop
|
||||
* @param {number | Pattern} times How often the sample is looped
|
||||
* @name loopBegin
|
||||
* @param {number | Pattern} position position from 0 - 1 where the loop starts
|
||||
* @example
|
||||
* s("bd").loop("<1 2 3 4>").osc()
|
||||
* note("<c a f e>").s("piano")
|
||||
* .loopBegin("<0 .24 .32>").loopEnd(.5)
|
||||
*
|
||||
*/
|
||||
['loop'],
|
||||
['loopBegin'],
|
||||
/**
|
||||
* Loops the sample from `loopBegin` to `loopEnd`. If one or both of those are set,
|
||||
* the sample is looped to fill the event duration, instead of playing the whole sample.
|
||||
* If only `loopBegin` is set, `loopEnd` defaults to 1.
|
||||
* If only `loopEnd` is set, `loopBegin` defaults to 0.
|
||||
*
|
||||
* @name loopEnd
|
||||
* @param {number | Pattern} position position from 0 - 1 where the loop ends
|
||||
* @example
|
||||
* @example
|
||||
* note("<c a f e>").s("piano")
|
||||
* .loopBegin(.2).loopEnd("<.3 .4 .5 .6>")
|
||||
*
|
||||
*/
|
||||
['loopEnd'],
|
||||
// TODO: currently duplicated with "native" legato
|
||||
// TODO: superdirt legato will do more: https://youtu.be/dQPmE1WaD1k?t=419
|
||||
/**
|
||||
|
||||
@@ -231,7 +231,8 @@ export const webaudioOutput = async (hap, deadline, hapDuration, cps) => {
|
||||
unit,
|
||||
nudge = 0, // TODO: is this in seconds?
|
||||
cut,
|
||||
loop,
|
||||
loopBegin,
|
||||
loopEnd,
|
||||
orbit = 1,
|
||||
room,
|
||||
size = 2,
|
||||
@@ -307,17 +308,21 @@ export const webaudioOutput = async (hap, deadline, hapDuration, cps) => {
|
||||
// are there other units?
|
||||
bufferSource.playbackRate.value = bufferSource.playbackRate.value * bufferSource.buffer.duration * cps;
|
||||
}
|
||||
let duration = soundfont || clip ? hapDuration : bufferSource.buffer.duration / bufferSource.playbackRate.value;
|
||||
const loop = loopBegin !== undefined || loopEnd !== undefined;
|
||||
let duration =
|
||||
soundfont || clip || loop ? hapDuration : bufferSource.buffer.duration / bufferSource.playbackRate.value;
|
||||
// "The computation of the offset into the sound is performed using the sound buffer's natural sample rate,
|
||||
// rather than the current playback rate, so even if the sound is playing at twice its normal speed,
|
||||
// the midway point through a 10-second audio buffer is still 5."
|
||||
const offset = begin * duration * bufferSource.playbackRate.value;
|
||||
duration = (end - begin) * duration;
|
||||
if (loop) {
|
||||
loopBegin = loopBegin ?? 0;
|
||||
loopEnd = loopEnd ?? 1;
|
||||
bufferSource.loop = true;
|
||||
bufferSource.loopStart = offset;
|
||||
bufferSource.loopEnd = offset + duration;
|
||||
duration = loop * duration;
|
||||
bufferSource.loopStart = offset + loopBegin * duration;
|
||||
bufferSource.loopEnd = offset + duration - (1 - loopEnd) * duration;
|
||||
duration = hapDuration;
|
||||
}
|
||||
t += nudge;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user