integrated with envelopes
This commit is contained in:
parent
d49c9dce4f
commit
4160639d88
3 changed files with 24 additions and 12 deletions
|
|
@ -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)];
|
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 curve = 'exponential';
|
||||||
const [attack, decay, sustain, release] = getADSRValues([att, dec, sus, rel], curve, [0.005, 0.14, 0, 0.1]);
|
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
|
// envelope is active when any of these values is set
|
||||||
const hasEnvelope = att ?? dec ?? sus ?? rel ?? fenv;
|
const hasEnvelope = att ?? dec ?? sus ?? rel ?? fenv;
|
||||||
// Apply ADSR to filter frequency
|
// 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 min = clamp(2 ** -offset * frequency, 0, 20000);
|
||||||
let max = clamp(2 ** (fenvAbs - offset) * frequency, 0, 20000);
|
let max = clamp(2 ** (fenvAbs - offset) * frequency, 0, 20000);
|
||||||
if (fenv < 0) [min, max] = [max, min];
|
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;
|
||||||
}
|
}
|
||||||
return filter;
|
return filter;
|
||||||
|
|
|
||||||
|
|
@ -395,6 +395,8 @@ export const superdough = async (value, t, hapDuration) => {
|
||||||
chain.push(gainNode(gain));
|
chain.push(gainNode(gain));
|
||||||
|
|
||||||
if (cutoff !== undefined) {
|
if (cutoff !== undefined) {
|
||||||
|
// chain.push(getWorklet(ac, 'ladder-processor', { frequency: cutoff, q: resonance, drive: 1 }));
|
||||||
|
|
||||||
let lp = () =>
|
let lp = () =>
|
||||||
createFilter(
|
createFilter(
|
||||||
ac,
|
ac,
|
||||||
|
|
@ -409,6 +411,7 @@ export const superdough = async (value, t, hapDuration) => {
|
||||||
t,
|
t,
|
||||||
t + hapDuration,
|
t + hapDuration,
|
||||||
fanchor,
|
fanchor,
|
||||||
|
ftype,
|
||||||
);
|
);
|
||||||
chain.push(lp());
|
chain.push(lp());
|
||||||
if (ftype === '24db') {
|
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 }));
|
shape !== undefined && chain.push(getWorklet(ac, 'shape-processor', { shape, postgain: shapevol }));
|
||||||
distort !== undefined && chain.push(getWorklet(ac, 'distort-processor', { distort, postgain: distortvol }));
|
distort !== undefined && chain.push(getWorklet(ac, 'distort-processor', { distort, postgain: distortvol }));
|
||||||
|
|
||||||
chain.push(getWorklet(ac, 'ladder-processor', { cutoff: 500, q: 1 }));
|
|
||||||
|
|
||||||
compressorThreshold !== undefined &&
|
compressorThreshold !== undefined &&
|
||||||
chain.push(
|
chain.push(
|
||||||
getCompressor(ac, compressorThreshold, compressorRatio, compressorKnee, compressorAttack, compressorRelease),
|
getCompressor(ac, compressorThreshold, compressorRatio, compressorKnee, compressorAttack, compressorRelease),
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,9 @@ const _PI = 3.14159265359;
|
||||||
class LadderProcessor extends AudioWorkletProcessor {
|
class LadderProcessor extends AudioWorkletProcessor {
|
||||||
static get parameterDescriptors() {
|
static get parameterDescriptors() {
|
||||||
return [
|
return [
|
||||||
{ name: 'cutoff', defaultValue: 500 },
|
{ name: 'frequency', defaultValue: 500 },
|
||||||
{ name: 'q', defaultValue: 1 },
|
{ name: 'q', defaultValue: 1 },
|
||||||
|
{ name: 'drive', defaultValue: 1 },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,11 +144,13 @@ class LadderProcessor extends AudioWorkletProcessor {
|
||||||
this.started = hasInput;
|
this.started = hasInput;
|
||||||
|
|
||||||
const resonance = parameters.q[0];
|
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 * 2 * _PI) / sampleRate;
|
||||||
cutoff = cutoff > 1 ? 1 : cutoff;
|
cutoff = cutoff > 1 ? 1 : cutoff;
|
||||||
|
|
||||||
const k = resonance * 4;
|
const k = resonance * 4;
|
||||||
|
const makeupgain = 1 / drive;
|
||||||
|
|
||||||
for (let n = 0; n < blockSize; n++) {
|
for (let n = 0; n < blockSize; n++) {
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
|
|
@ -157,12 +160,12 @@ class LadderProcessor extends AudioWorkletProcessor {
|
||||||
this.p33 = this.p32;
|
this.p33 = this.p32;
|
||||||
this.p32 = this.p3;
|
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.p1 += (fast_tanh(this.p0) - fast_tanh(this.p1)) * cutoff;
|
||||||
this.p2 += (fast_tanh(this.p1) - fast_tanh(this.p2)) * cutoff;
|
this.p2 += (fast_tanh(this.p1) - fast_tanh(this.p2)) * cutoff;
|
||||||
this.p3 += (fast_tanh(this.p2) - fast_tanh(this.p3)) * cutoff;
|
this.p3 += (fast_tanh(this.p2) - fast_tanh(this.p3)) * cutoff;
|
||||||
|
|
||||||
output[i][n] = out;
|
output[i][n] = out * makeupgain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue