xxxxxxxxxx
76
// Simple peak compressor using leaky integrator
class CompressorProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [{
name: 'threshold',
defaultValue: -12
},{
name: 'threshold2',
defaultValue: -48
},{
name: 'upperLimit',
defaultValue: 60
},{
name: 'lowerLimit',
defaultValue: 30
},{
name: 'ratio',
defaultValue: 2
},{
name: 'ratio2',
defaultValue: 1
},{
name: 'attack',
defaultValue: 5,
minValue: 0
},{
name: 'release',
defaultValue: 50,
minValue: 0
},{
name: 'makeupGain',
defaultValue: 0
},{
name: 'mix',
defaultValue: 100,
minValue: 0,
maxValue: 100
}];
}
constructor() {
super();
this.envelopeValues = [];
this.ampTodB = x => {
return 20*Math.log10(x);
};
this.dBToAmp = x => {
return 10 ** (x/20);
}
}
process(inputs, outputs, parameters) {
const input = inputs[0],
output = outputs[0],
attTime = Math.E ** (-1/(parameters.attack[0]*sampleRate/1000)),
relTime = Math.E ** (-1/(parameters.release[0]*sampleRate/1000)),
slope = 1 - (1/parameters.ratio[0]),
slope2 = 1 - (1/parameters.ratio2[0]);
this.envelopeValues.length = input.length;
input.forEach((channel, x) => {
for (let i = 0; i < channel.length; i++) {
const amp = this.ampTodB(Math.abs(channel[i]));
const gainReduction =
(Math.abs(slope) <= 0 ? 0 : Math.max(Math.min((-amp+parameters.threshold[0]), 0), -parameters.upperLimit[0]/Math.abs(slope)))*slope -
(Math.abs(slope2) <= 0 ? 0 : Math.min(Math.max((amp-parameters.threshold2[0]), -parameters.lowerLimit[0]/Math.abs(slope2)), 0))*slope2;
const smoothingTimeConstant = gainReduction > this.envelopeValues[x] ? relTime : attTime;
this.envelopeValues[x] = isFinite(this.envelopeValues[x]) ? gainReduction * (1-smoothingTimeConstant) + this.envelopeValues[x] * (smoothingTimeConstant) : gainReduction;
output[x][i] = input[x][i] * (this.dBToAmp(this.envelopeValues[x]) * parameters.mix[0]/100 + (1-parameters.mix[0]/100)) * this.dBToAmp(parameters.makeupGain[0]);
}
});
return true;
}
}
registerProcessor('compressor-processor', CompressorProcessor);