104 lines
2.3 KiB
JavaScript
104 lines
2.3 KiB
JavaScript
class SVFProcessor extends AudioWorkletProcessor {
|
|
static get parameterDescriptors() {
|
|
return [
|
|
{
|
|
name: 'frequency',
|
|
defaultValue: 1000,
|
|
minValue: 20,
|
|
maxValue: 20000,
|
|
automationRate: 'k-rate'
|
|
},
|
|
{
|
|
name: 'resonance',
|
|
defaultValue: 0.707,
|
|
minValue: 0.05,
|
|
maxValue: 10,
|
|
automationRate: 'k-rate'
|
|
}
|
|
]
|
|
}
|
|
|
|
constructor() {
|
|
super()
|
|
|
|
this.mode = 'lowpass'
|
|
this.ic1eq = 0
|
|
this.ic2eq = 0
|
|
|
|
this.port.onmessage = (event) => {
|
|
const { type, value } = event.data
|
|
if (type === 'mode') {
|
|
this.mode = value
|
|
}
|
|
}
|
|
}
|
|
|
|
process(inputs, outputs, parameters) {
|
|
const input = inputs[0]
|
|
const output = outputs[0]
|
|
|
|
if (input.length === 0 || output.length === 0) {
|
|
return true
|
|
}
|
|
|
|
const inputChannel = input[0]
|
|
const outputChannel = output[0]
|
|
const frequency = parameters.frequency
|
|
const resonance = parameters.resonance
|
|
|
|
const sampleRate = globalThis.sampleRate || 44100
|
|
const isFreqArray = frequency.length > 1
|
|
const isResArray = resonance.length > 1
|
|
|
|
for (let i = 0; i < inputChannel.length; i++) {
|
|
const freq = isFreqArray ? frequency[i] : frequency[0]
|
|
const res = isResArray ? resonance[i] : resonance[0]
|
|
|
|
const g = Math.tan(Math.PI * Math.min(freq, sampleRate * 0.49) / sampleRate)
|
|
const k = 1 / Math.max(0.05, res)
|
|
|
|
const inputSample = inputChannel[i]
|
|
|
|
const a1 = 1 / (1 + g * (g + k))
|
|
const a2 = g * a1
|
|
const a3 = g * a2
|
|
|
|
const v3 = inputSample - this.ic2eq
|
|
const v1 = a1 * this.ic1eq + a2 * v3
|
|
const v2 = this.ic2eq + a2 * this.ic1eq + a3 * v3
|
|
|
|
this.ic1eq = 2 * v1 - this.ic1eq
|
|
this.ic2eq = 2 * v2 - this.ic2eq
|
|
|
|
const lp = v2
|
|
const bp = v1
|
|
const hp = inputSample - k * v1 - v2
|
|
const notch = inputSample - k * v1
|
|
|
|
let outSample
|
|
switch (this.mode) {
|
|
case 'lowpass':
|
|
outSample = lp
|
|
break
|
|
case 'highpass':
|
|
outSample = hp
|
|
break
|
|
case 'bandpass':
|
|
outSample = bp
|
|
break
|
|
case 'notch':
|
|
outSample = notch
|
|
break
|
|
default:
|
|
outSample = lp
|
|
}
|
|
|
|
outputChannel[i] = outSample
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|
|
|
|
registerProcessor('svf-processor', SVFProcessor)
|