93 lines
2.2 KiB
JavaScript
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)
|