Merge branch 'main' into glossing/wavetable-synth

This commit is contained in:
Aria 2025-09-04 20:31:01 -05:00
commit 1205573bc6
10 changed files with 151 additions and 29 deletions

View file

@ -1,7 +1,9 @@
import reverbGen from './reverbGen.mjs';
import { clamp } from './util.mjs';
if (typeof AudioContext !== 'undefined') {
AudioContext.prototype.adjustLength = function (duration, buffer) {
AudioContext.prototype.adjustLength = function (duration, buffer, speed = 1, offsetAmount = 0) {
const sampleOffset = Math.floor(clamp(offsetAmount, 0, 1) * buffer.length);
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 +11,30 @@ if (typeof AudioContext !== 'undefined') {
let newData = newBuffer.getChannelData(channel);
for (let i = 0; i < newLength; i++) {
newData[i] = oldData[i] || 0;
// loop the buffer around to prevent
let position = (sampleOffset + 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 +51,7 @@ if (typeof AudioContext !== 'undefined') {
);
}
};
convolver.generate(duration, fade, lp, dim, ir);
convolver.generate(duration, fade, lp, dim, ir, irspeed, irbegin);
return convolver;
};
}

View file

@ -282,7 +282,6 @@ export async function initAudioOnFirstClick(options) {
return audioReady;
}
let delays = {};
const maxfeedback = 0.98;
let channelMerger, destinationGain;
@ -326,7 +325,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 +441,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 +464,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;
}
@ -620,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
@ -836,7 +840,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);
}
@ -854,7 +858,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);
}