integrated with envelopes

This commit is contained in:
Jade (Rose) Rowland 2024-05-17 17:38:44 -04:00
parent d49c9dce4f
commit 4160639d88
3 changed files with 24 additions and 12 deletions

View File

@ -103,14 +103,22 @@ export const getADSRValues = (params, curve = 'linear', defaultValues) => {
return [Math.max(a ?? 0, envmin), Math.max(d ?? 0, envmin), Math.min(sustain, envmax), Math.max(r ?? 0, releaseMin)];
};
export function createFilter(context, type, frequency, Q, att, dec, sus, rel, fenv, start, end, fanchor) {
export function createFilter(context, type, frequency, Q, att, dec, sus, rel, fenv, start, end, fanchor, model) {
const curve = 'exponential';
const [attack, decay, sustain, release] = getADSRValues([att, dec, sus, rel], curve, [0.005, 0.14, 0, 0.1]);
const filter = context.createBiquadFilter();
let filter;
let frequencyParam;
if (model === 'ladder') {
filter = getWorklet(context, 'ladder-processor', { frequency, q: Q, drive: 1 });
frequencyParam = filter.parameters.get('frequency');
} else {
filter = context.createBiquadFilter();
filter.type = type;
filter.Q.value = Q;
filter.frequency.value = frequency;
frequencyParam = filter.frequency;
}
filter.type = type;
filter.Q.value = Q;
filter.frequency.value = frequency;
// envelope is active when any of these values is set
const hasEnvelope = att ?? dec ?? sus ?? rel ?? fenv;
// Apply ADSR to filter frequency
@ -122,7 +130,7 @@ export function createFilter(context, type, frequency, Q, att, dec, sus, rel, fe
let min = clamp(2 ** -offset * frequency, 0, 20000);
let max = clamp(2 ** (fenvAbs - offset) * frequency, 0, 20000);
if (fenv < 0) [min, max] = [max, min];
getParamADSR(filter.frequency, attack, decay, sustain, release, min, max, start, end, curve);
getParamADSR(frequencyParam, attack, decay, sustain, release, min, max, start, end, curve);
return filter;
}
return filter;

View File

@ -395,6 +395,8 @@ export const superdough = async (value, t, hapDuration) => {
chain.push(gainNode(gain));
if (cutoff !== undefined) {
// chain.push(getWorklet(ac, 'ladder-processor', { frequency: cutoff, q: resonance, drive: 1 }));
let lp = () =>
createFilter(
ac,
@ -409,6 +411,7 @@ export const superdough = async (value, t, hapDuration) => {
t,
t + hapDuration,
fanchor,
ftype,
);
chain.push(lp());
if (ftype === '24db') {
@ -471,8 +474,6 @@ export const superdough = async (value, t, hapDuration) => {
shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape, postgain: shapevol }));
distort !== undefined && chain.push(getWorklet(ac, 'distort-processor', { distort, postgain: distortvol }));
chain.push(getWorklet(ac, 'ladder-processor', { cutoff: 500, q: 1 }));
compressorThreshold !== undefined &&
chain.push(
getCompressor(ac, compressorThreshold, compressorRatio, compressorKnee, compressorAttack, compressorRelease),

View File

@ -115,8 +115,9 @@ const _PI = 3.14159265359;
class LadderProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [
{ name: 'cutoff', defaultValue: 500 },
{ name: 'frequency', defaultValue: 500 },
{ name: 'q', defaultValue: 1 },
{ name: 'drive', defaultValue: 1 },
];
}
@ -143,11 +144,13 @@ class LadderProcessor extends AudioWorkletProcessor {
this.started = hasInput;
const resonance = parameters.q[0];
let cutoff = parameters.cutoff[0];
const drive = parameters.drive[0] * 2;
let cutoff = parameters.frequency[0];
cutoff = (cutoff * 2 * _PI) / sampleRate;
cutoff = cutoff > 1 ? 1 : cutoff;
const k = resonance * 4;
const makeupgain = 1 / drive;
for (let n = 0; n < blockSize; n++) {
for (let i = 0; i < input.length; i++) {
@ -157,12 +160,12 @@ class LadderProcessor extends AudioWorkletProcessor {
this.p33 = this.p32;
this.p32 = this.p3;
this.p0 += (fast_tanh(input[i][n] - k * out) - fast_tanh(this.p0)) * cutoff;
this.p0 += (fast_tanh(input[i][n] * drive - k * out) - fast_tanh(this.p0)) * cutoff;
this.p1 += (fast_tanh(this.p0) - fast_tanh(this.p1)) * cutoff;
this.p2 += (fast_tanh(this.p1) - fast_tanh(this.p2)) * cutoff;
this.p3 += (fast_tanh(this.p2) - fast_tanh(this.p3)) * cutoff;
output[i][n] = out;
output[i][n] = out * makeupgain;
}
}
return true;