Files
bruitiste/public/worklets/bytebeat-processor.js
2025-10-04 14:52:20 +02:00

86 lines
2.1 KiB
JavaScript

class BytebeatProcessor extends AudioWorkletProcessor {
constructor() {
super()
this.t = 0
this.a = 8
this.b = 16
this.c = 32
this.d = 64
this.formula = null
this.compiledFormula = null
this.sampleRate = 8000
this.duration = 4
this.loopLength = this.sampleRate * this.duration
this.error = false
this.port.onmessage = (event) => {
const { type, value } = event.data
switch (type) {
case 'formula':
this.setFormula(value)
break
case 'variables':
this.a = value.a ?? this.a
this.b = value.b ?? this.b
this.c = value.c ?? this.c
this.d = value.d ?? this.d
break
case 'reset':
this.t = 0
break
case 'loopLength':
this.loopLength = value
break
}
}
}
setFormula(formulaString) {
try {
this.compiledFormula = new Function('t', 'a', 'b', 'c', 'd', `return ${formulaString}`)
this.formula = formulaString
this.error = false
} catch (e) {
console.error('Failed to compile bytebeat formula:', e)
this.error = true
this.compiledFormula = null
}
}
process(inputs, outputs) {
const output = outputs[0]
if (output.length > 0) {
const outputChannel = output[0]
for (let i = 0; i < outputChannel.length; i++) {
if (!this.compiledFormula || this.error) {
outputChannel[i] = 0
} else {
try {
const value = this.compiledFormula(this.t, this.a, this.b, this.c, this.d)
const byteValue = value & 0xFF
outputChannel[i] = (byteValue - 128) / 128
} catch (e) {
outputChannel[i] = 0
if (!this.error) {
console.error('Bytebeat runtime error:', e)
this.error = true
}
}
}
this.t++
if (this.loopLength > 0 && this.t >= this.loopLength) {
this.t = 0
}
}
}
return true
}
}
registerProcessor('bytebeat-processor', BytebeatProcessor)