Files
bruitiste/public/worklets/ring-mod-processor.js
2025-10-06 16:36:59 +02:00

93 lines
2.2 KiB
JavaScript

class RingModProcessor extends AudioWorkletProcessor {
constructor() {
super()
this.frequency = 200
this.shape = 'sine'
this.spread = 0
this.bypassed = false
this.phase = 0
this.phaseRight = 0
this.port.onmessage = (event) => {
const { type, value } = event.data
switch (type) {
case 'frequency':
this.frequency = value
break
case 'shape':
this.shape = value
break
case 'spread':
this.spread = value
break
case 'bypass':
this.bypassed = value
break
}
}
}
generateWaveform(phase, shape) {
switch (shape) {
case 'sine':
return Math.sin(phase * Math.PI * 2)
case 'square':
return phase < 0.5 ? 1 : -1
case 'saw':
return 2 * phase - 1
case 'triangle':
return phase < 0.5 ? 4 * phase - 1 : 3 - 4 * phase
default:
return Math.sin(phase * Math.PI * 2)
}
}
process(inputs, outputs) {
const input = inputs[0]
const output = outputs[0]
if (!input || input.length === 0 || !output || output.length === 0) {
return true
}
const inputL = input[0]
const inputR = input[1] || input[0]
const outputL = output[0]
const outputR = output[1] || output[0]
if (!inputL || !outputL) {
return true
}
for (let i = 0; i < inputL.length; i++) {
if (this.bypassed) {
outputL[i] = inputL[i]
if (outputR) outputR[i] = inputR[i]
continue
}
const spreadAmount = this.spread * 0.1
const freqL = this.frequency * (1 - spreadAmount)
const freqR = this.frequency * (1 + spreadAmount)
this.phase += freqL / sampleRate
this.phaseRight += freqR / sampleRate
if (this.phase >= 1) this.phase -= 1
if (this.phaseRight >= 1) this.phaseRight -= 1
const carrierL = this.generateWaveform(this.phase, this.shape)
const carrierR = this.generateWaveform(this.phaseRight, this.shape)
outputL[i] = inputL[i] * carrierL
if (outputR) outputR[i] = inputR[i] * carrierR
}
return true
}
}
registerProcessor('ring-mod-processor', RingModProcessor)