2019-10-18 23:19:19 +00:00
|
|
|
class OwrxAudioProcessor extends AudioWorkletProcessor {
|
|
|
|
constructor(options){
|
|
|
|
super(options);
|
2019-10-19 16:09:50 +00:00
|
|
|
// initialize ringbuffer, make sure it aligns with the expected buffer size of 128
|
2019-10-20 21:38:58 +00:00
|
|
|
this.bufferSize = Math.round(options.processorOptions.maxBufferSize / 128) * 128;
|
2019-10-19 16:09:50 +00:00
|
|
|
this.audioBuffer = new Float32Array(this.bufferSize);
|
|
|
|
this.inPos = 0;
|
|
|
|
this.outPos = 0;
|
2019-10-26 20:32:25 +00:00
|
|
|
this.samplesProcessed = 0;
|
2019-10-18 23:19:19 +00:00
|
|
|
this.port.addEventListener('message', (m) => {
|
|
|
|
if (typeof(m.data) === 'string') {
|
|
|
|
const json = JSON.parse(m.data);
|
2019-10-26 20:32:25 +00:00
|
|
|
if (json.cmd && json.cmd === 'getStats') {
|
|
|
|
this.reportStats();
|
2019-10-18 23:19:19 +00:00
|
|
|
}
|
|
|
|
} else {
|
2019-10-19 16:09:50 +00:00
|
|
|
// the ringbuffer size is aligned to the output buffer size, which means that the input buffers might
|
|
|
|
// need to wrap around the end of the ringbuffer, back to the start.
|
|
|
|
// it is better to have this processing here instead of in the time-critical process function.
|
|
|
|
if (this.inPos + m.data.length <= this.bufferSize) {
|
|
|
|
// we have enough space, so just copy data over.
|
|
|
|
this.audioBuffer.set(m.data, this.inPos);
|
|
|
|
} else {
|
|
|
|
// we don't have enough space, so we need to split the data.
|
|
|
|
const remaining = this.bufferSize - this.inPos;
|
|
|
|
this.audioBuffer.set(m.data.subarray(0, remaining), this.inPos);
|
|
|
|
this.audioBuffer.set(m.data.subarray(remaining));
|
|
|
|
}
|
|
|
|
this.inPos = (this.inPos + m.data.length) % this.bufferSize;
|
2019-10-18 23:19:19 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
this.port.addEventListener('messageerror', console.error);
|
|
|
|
this.port.start();
|
|
|
|
}
|
2019-10-20 21:38:58 +00:00
|
|
|
process(inputs, outputs) {
|
2019-10-20 21:48:49 +00:00
|
|
|
if (this.remaining() < 128) return true;
|
2019-10-18 23:19:19 +00:00
|
|
|
outputs[0].forEach((output) => {
|
2019-10-20 21:48:49 +00:00
|
|
|
output.set(this.audioBuffer.subarray(this.outPos, this.outPos + 128));
|
2019-10-18 23:19:19 +00:00
|
|
|
});
|
2019-10-20 21:48:49 +00:00
|
|
|
this.outPos = (this.outPos + 128) % this.bufferSize;
|
2019-10-26 20:32:25 +00:00
|
|
|
this.samplesProcessed += 128;
|
2019-10-18 23:19:19 +00:00
|
|
|
return true;
|
|
|
|
}
|
2019-10-19 16:09:50 +00:00
|
|
|
remaining() {
|
|
|
|
const mod = (this.inPos - this.outPos) % this.bufferSize;
|
|
|
|
if (mod >= 0) return mod;
|
|
|
|
return mod + this.bufferSize;
|
2019-10-18 23:19:19 +00:00
|
|
|
}
|
2019-10-26 20:32:25 +00:00
|
|
|
reportStats() {
|
|
|
|
this.port.postMessage(JSON.stringify({
|
|
|
|
buffersize: this.remaining(),
|
|
|
|
samplesProcessed: this.samplesProcessed
|
|
|
|
}));
|
|
|
|
this.samplesProcessed = 0;
|
2019-10-18 23:19:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
registerProcessor('openwebrx-audio-processor', OwrxAudioProcessor);
|