/**
* BytebeatProcessor runs in the AudioWorkletScope
* @param {object} options
* @param {string} options.processorOptions.beatcode
* Main block of the bytebeat function and its execution
* @param {number} options.processorOptions.frequency
* The frequency at which 't' will be incremented
* @param {number} options.processorOptions.sampleRate
* The sample rate of the audio context
* @param {number} options.processorOptions.tempo
* The tempo which the speed that tt will be incremented depends on
* @param {boolean} [options.processorOptions.floatMode=false]
* Whether the function expects an output between 0:255 (default) or -1:1
*/
class BytebeatProcessor extends AudioWorkletProcessor {
constructor (options) {
super(options)
this.beatcode = new Function('t,tt', options.processorOptions.beatcode)
this.sampleRate = options.processorOptions.sampleRate
this.frequency = options.processorOptions.frequency
this.tDelta = this.frequency / this.sampleRate
this.t = 0
this.tt = 0
this.tempo = options.processorOptions.tempo
this.ttDelta = this.tempo * 8192 / 120 / this.sampleRate
this.startTime = Infinity
this.stopTime = Infinity
this.port.onmessage = event => {
switch (event.data.message) {
case 'stop':
this.stopTime = currentTime + event.data.stopTime
break
case 'start':
this.startTime = currentTime + event.data.startTime
break
default:
}
}
if (options.processorOptions.floatMode) {
this.postprocess = t => Math.min(1, Math.max(-1, t))
} else {
this.postprocess = t => (t % 256) / 128 - 1
}
}
process (inputs, outputs) {
const output = outputs[0]
if (currentTime >= this.startTime) {
for (let i = 0; i < output[0].length; ++i) {
const data = this.postprocess(
this.beatcode(Math.floor(this.t), Math.floor(this.tt)))
for (let channel = 0; channel < output.length; ++channel) {
output[channel][i] = data
}
this.t += this.tDelta
this.tt += this.ttDelta
}
} else {
for (let channel = 0; channel < output.length; ++channel) {
for (let i = 0; i < output[channel].length; ++i) {
output[channel][i] = 0
}
}
}
return currentTime < this.stopTime
}
}
registerProcessor('bytebeat-processor', BytebeatProcessor)