This commit is contained in:
Jade (Rose) Rowland 2025-08-17 16:49:10 -04:00
parent 8c4f10464b
commit e9aef9e4d4
4 changed files with 48 additions and 13 deletions

View file

@ -1516,6 +1516,28 @@ export const { roomfade, rfade } = registerControl('roomfade', 'rfade');
* *
*/ */
export const { ir, iresponse } = registerControl(['ir', 'i'], 'iresponse'); 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("<shaker_large:0 shaker_large:2>")
*
*/
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("<shaker_large:0 shaker_large:2>")
*
*/
export const { irbegin } = registerControl('irbegin');
/** /**
* Sets the room size of the reverb, see `room`. * Sets the room size of the reverb, see `room`.
* When this property is changed, the reverb will be recaculated, so only change this sparsely.. * When this property is changed, the reverb will be recaculated, so only change this sparsely..

View file

@ -3276,7 +3276,7 @@ export const slice = register(
* @memberof Pattern * @memberof Pattern
* @returns Pattern * @returns Pattern
* @example * @example
* s("bd!8").onTriggerTime((hap) => {console.info(hap)}) * s("bd!8").onTriggerTime((hap) => {console.log(hap)})
*/ */
Pattern.prototype.onTriggerTime = function (func) { Pattern.prototype.onTriggerTime = function (func) {
return this.onTrigger((hap, currentTime, _cps, targetTime) => { return this.onTrigger((hap, currentTime, _cps, targetTime) => {

View file

@ -1,7 +1,8 @@
import reverbGen from './reverbGen.mjs'; import reverbGen from './reverbGen.mjs';
if (typeof AudioContext !== 'undefined') { 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 newLength = buffer.sampleRate * duration;
const newBuffer = this.createBuffer(buffer.numberOfChannels, buffer.length, buffer.sampleRate); const newBuffer = this.createBuffer(buffer.numberOfChannels, buffer.length, buffer.sampleRate);
for (let channel = 0; channel < buffer.numberOfChannels; channel++) { for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
@ -9,22 +10,29 @@ if (typeof AudioContext !== 'undefined') {
let newData = newBuffer.getChannelData(channel); let newData = newBuffer.getChannelData(channel);
for (let i = 0; i < newLength; i++) { 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; 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(); 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.duration = d;
convolver.fade = fade; convolver.fade = fade;
convolver.lp = lp; convolver.lp = lp;
convolver.dim = dim; convolver.dim = dim;
convolver.ir = ir; convolver.ir = ir;
convolver.irspeed = irspeed;
convolver.irbegin = irbegin;
if (ir) { if (ir) {
convolver.buffer = this.adjustLength(d, ir); convolver.buffer = this.adjustLength(d, ir, irspeed, irbegin);
} else { } else {
reverbGen.generateReverb( 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; return convolver;
}; };
} }

View file

@ -326,7 +326,7 @@ export const panic = () => {
channelMerger == null; channelMerger == null;
}; };
function getDelay(orbit, delaytime, delayfeedback, t, channels) { function getDelay(orbit, delaytime, delayfeedback, t) {
if (delayfeedback > maxfeedback) { if (delayfeedback > maxfeedback) {
//logger(`delayfeedback was clamped to ${maxfeedback} to save your ears`); //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; 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 no reverb has been created for a given orbit, create one
if (!orbits[orbit].reverbNode) { if (!orbits[orbit].reverbNode) {
const ac = getAudioContext(); 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); connectToOrbit(reverb, orbit);
orbits[orbit].reverbNode = reverb; orbits[orbit].reverbNode = reverb;
} }
if ( if (
hasChanged(duration, orbits[orbit].reverbNode.duration) || hasChanged(duration, orbits[orbit].reverbNode.duration) ||
hasChanged(fade, orbits[orbit].reverbNode.fade) || hasChanged(fade, orbits[orbit].reverbNode.fade) ||
hasChanged(lp, orbits[orbit].reverbNode.lp) || hasChanged(lp, orbits[orbit].reverbNode.lp) ||
hasChanged(dim, orbits[orbit].reverbNode.dim) || hasChanged(dim, orbits[orbit].reverbNode.dim) ||
hasChanged(irspeed, orbits[orbit].reverbNode.irspeed) ||
hasChanged(irbegin, orbits[orbit].reverbNode.irbegin) ||
orbits[orbit].reverbNode.ir !== ir orbits[orbit].reverbNode.ir !== ir
) { ) {
// only regenerate when something has changed // 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) // stack(s("a"), s("b").rsize(8)).room(.5)
// this only works when args may stay undefined until here // this only works when args may stay undefined until here
// setting default values breaks this // 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; return orbits[orbit].reverbNode;
} }
@ -619,6 +622,8 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
roomdim, roomdim,
roomsize, roomsize,
ir, ir,
irspeed,
irbegin,
i = getDefaultValue('i'), i = getDefaultValue('i'),
velocity = getDefaultValue('velocity'), velocity = getDefaultValue('velocity'),
analyze, // analyser wet analyze, // analyser wet
@ -832,7 +837,7 @@ export const superdough = async (value, t, hapDuration, cps = 0.5, cycle = 0.5)
// delay // delay
let delaySend; let delaySend;
if (delay > 0 && delaytime > 0 && delayfeedback > 0) { 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); delaySend = effectSend(post, delayNode, delay);
audioNodes.push(delaySend); 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); 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); reverbSend = effectSend(post, reverbNode, room);
audioNodes.push(reverbSend); audioNodes.push(reverbSend);
} }