From e9aef9e4d49cb451e7e96fd989101949c72c9121 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 17 Aug 2025 16:49:10 -0400 Subject: [PATCH] working --- packages/core/controls.mjs | 22 ++++++++++++++++++++++ packages/core/pattern.mjs | 2 +- packages/superdough/reverb.mjs | 20 ++++++++++++++------ packages/superdough/superdough.mjs | 17 +++++++++++------ 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/packages/core/controls.mjs b/packages/core/controls.mjs index e6181d453..9f07f8c76 100644 --- a/packages/core/controls.mjs +++ b/packages/core/controls.mjs @@ -1516,6 +1516,28 @@ export const { roomfade, rfade } = registerControl('roomfade', 'rfade'); * */ export const { ir, iresponse } = registerControl(['ir', 'i'], 'iresponse'); + +/** + * Sets the sample to use as an impulse response for the reverb. + * @name iresponse + * @param {string | Pattern} sample to use as an impulse response + * @synonyms ir + * @example + * s("bd sd [~ bd] sd").room(.8).ir("") + * + */ +export const { irspeed } = registerControl('irspeed'); + +/** + * Sets the sample to use as an impulse response for the reverb. + * @name iresponse + * @param {string | Pattern} sample to use as an impulse response + * @synonyms ir + * @example + * s("bd sd [~ bd] sd").room(.8).ir("") + * + */ +export const { irbegin } = registerControl('irbegin'); /** * Sets the room size of the reverb, see `room`. * When this property is changed, the reverb will be recaculated, so only change this sparsely.. diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index dbf1b17f7..56f2c16e3 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -3276,7 +3276,7 @@ export const slice = register( * @memberof Pattern * @returns Pattern * @example - * s("bd!8").onTriggerTime((hap) => {console.info(hap)}) + * s("bd!8").onTriggerTime((hap) => {console.log(hap)}) */ Pattern.prototype.onTriggerTime = function (func) { return this.onTrigger((hap, currentTime, _cps, targetTime) => { diff --git a/packages/superdough/reverb.mjs b/packages/superdough/reverb.mjs index 0f638ca80..4d62aafdc 100644 --- a/packages/superdough/reverb.mjs +++ b/packages/superdough/reverb.mjs @@ -1,7 +1,8 @@ import reverbGen from './reverbGen.mjs'; if (typeof AudioContext !== 'undefined') { - AudioContext.prototype.adjustLength = function (duration, buffer) { + AudioContext.prototype.adjustLength = function (duration, buffer, speed = 1, offsetSeconds = 0) { + const offset = offsetSeconds * buffer.sampleRate; const newLength = buffer.sampleRate * duration; const newBuffer = this.createBuffer(buffer.numberOfChannels, buffer.length, buffer.sampleRate); for (let channel = 0; channel < buffer.numberOfChannels; channel++) { @@ -9,22 +10,29 @@ if (typeof AudioContext !== 'undefined') { let newData = newBuffer.getChannelData(channel); for (let i = 0; i < newLength; i++) { - newData[i] = oldData[i] || 0; + let position = (offset + i * Math.abs(speed)) % oldData.length; + if (speed < 1) { + position = position * -1; + } + + newData[i] = oldData.at(position) || 0; } } return newBuffer; }; - AudioContext.prototype.createReverb = function (duration, fade, lp, dim, ir) { + AudioContext.prototype.createReverb = function (duration, fade, lp, dim, ir, irspeed, irbegin) { const convolver = this.createConvolver(); - convolver.generate = (d = 2, fade = 0.1, lp = 15000, dim = 1000, ir) => { + convolver.generate = (d = 2, fade = 0.1, lp = 15000, dim = 1000, ir, irspeed, irbegin) => { convolver.duration = d; convolver.fade = fade; convolver.lp = lp; convolver.dim = dim; convolver.ir = ir; + convolver.irspeed = irspeed; + convolver.irbegin = irbegin; if (ir) { - convolver.buffer = this.adjustLength(d, ir); + convolver.buffer = this.adjustLength(d, ir, irspeed, irbegin); } else { reverbGen.generateReverb( { @@ -41,7 +49,7 @@ if (typeof AudioContext !== 'undefined') { ); } }; - convolver.generate(duration, fade, lp, dim, ir); + convolver.generate(duration, fade, lp, dim, ir, irspeed, irbegin); return convolver; }; } diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index eb1466d91..ccdb15abf 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -326,7 +326,7 @@ export const panic = () => { channelMerger == null; }; -function getDelay(orbit, delaytime, delayfeedback, t, channels) { +function getDelay(orbit, delaytime, delayfeedback, t) { if (delayfeedback > maxfeedback) { //logger(`delayfeedback was clamped to ${maxfeedback} to save your ears`); } @@ -442,19 +442,22 @@ function duckOrbit(audioContext, targetOrbit, t, attacktime = 0.1, duckdepth = 1 } let hasChanged = (now, before) => now !== undefined && now !== before; -function getReverb(orbit, duration, fade, lp, dim, ir) { +function getReverb(orbit, duration, fade, lp, dim, ir, irspeed, irbegin) { // If no reverb has been created for a given orbit, create one if (!orbits[orbit].reverbNode) { const ac = getAudioContext(); - const reverb = ac.createReverb(duration, fade, lp, dim, ir); + const reverb = ac.createReverb(duration, fade, lp, dim, ir, irspeed, irbegin); connectToOrbit(reverb, orbit); orbits[orbit].reverbNode = reverb; } + if ( hasChanged(duration, orbits[orbit].reverbNode.duration) || hasChanged(fade, orbits[orbit].reverbNode.fade) || hasChanged(lp, orbits[orbit].reverbNode.lp) || hasChanged(dim, orbits[orbit].reverbNode.dim) || + hasChanged(irspeed, orbits[orbit].reverbNode.irspeed) || + hasChanged(irbegin, orbits[orbit].reverbNode.irbegin) || orbits[orbit].reverbNode.ir !== ir ) { // only regenerate when something has changed @@ -462,7 +465,7 @@ function getReverb(orbit, duration, fade, lp, dim, ir) { // stack(s("a"), s("b").rsize(8)).room(.5) // this only works when args may stay undefined until here // setting default values breaks this - orbits[orbit].reverbNode.generate(duration, fade, lp, dim, ir); + orbits[orbit].reverbNode.generate(duration, fade, lp, dim, ir, irspeed, irbegin); } return orbits[orbit].reverbNode; } @@ -619,6 +622,8 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) roomdim, roomsize, ir, + irspeed, + irbegin, i = getDefaultValue('i'), velocity = getDefaultValue('velocity'), analyze, // analyser wet @@ -832,7 +837,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) // delay let delaySend; if (delay > 0 && delaytime > 0 && delayfeedback > 0) { - const delayNode = getDelay(orbit, delaytime, delayfeedback, t, orbitChannels); + const delayNode = getDelay(orbit, delaytime, delayfeedback, t); delaySend = effectSend(post, delayNode, delay); audioNodes.push(delaySend); } @@ -850,7 +855,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5) } roomIR = await loadBuffer(url, ac, ir, 0); } - const reverbNode = getReverb(orbit, roomsize, roomfade, roomlp, roomdim, roomIR, orbitChannels); + const reverbNode = getReverb(orbit, roomsize, roomfade, roomlp, roomdim, roomIR, irspeed, irbegin); reverbSend = effectSend(post, reverbNode, room); audioNodes.push(reverbSend); }