48 lines
1.8 KiB
JavaScript
48 lines
1.8 KiB
JavaScript
class PCM16CaptureProcessor extends AudioWorkletProcessor {
|
|||
|
|
constructor(options) {
|
||
|
|
super();
|
||
|
|
this.targetRate = Number(options.processorOptions?.targetSampleRate || 16000);
|
||
|
|
this.frameSamples = Number(options.processorOptions?.frameSamples || 320);
|
||
|
|
this.ratio = sampleRate / this.targetRate;
|
||
|
|
this.source = [];
|
||
|
|
this.position = 0;
|
||
|
|
this.output = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
process(inputs) {
|
||
|
|
const channel = inputs[0]?.[0];
|
||
|
|
if (!channel?.length) return true;
|
||
|
|
for (const sample of channel) this.source.push(sample);
|
||
|
|
while (this.position + this.ratio <= this.source.length) {
|
||
|
|
const start = Math.floor(this.position);
|
||
|
|
const end = Math.max(start + 1, Math.floor(this.position + this.ratio));
|
||
|
|
let sum = 0;
|
||
|
|
for (let index = start; index < end && index < this.source.length; index += 1) sum += this.source[index];
|
||
|
|
this.output.push(sum / Math.max(1, end - start));
|
||
|
|
this.position += this.ratio;
|
||
|
|
if (this.output.length >= this.frameSamples) this.flush();
|
||
|
|
}
|
||
|
|
const consumed = Math.floor(this.position);
|
||
|
|
if (consumed > 0) {
|
||
|
|
this.source.splice(0, consumed);
|
||
|
|
this.position -= consumed;
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
flush() {
|
||
|
|
const frame = this.output.splice(0, this.frameSamples);
|
||
|
|
const pcm = new Int16Array(frame.length);
|
||
|
|
let energy = 0;
|
||
|
|
for (let index = 0; index < frame.length; index += 1) {
|
||
|
|
const sample = Math.max(-1, Math.min(1, frame[index]));
|
||
|
|
energy += sample * sample;
|
||
|
|
pcm[index] = sample < 0 ? Math.round(sample * 32768) : Math.round(sample * 32767);
|
||
|
|
}
|
||
|
|
const volume = Math.min(100, Math.round(Math.sqrt(energy / Math.max(1, frame.length)) * 280));
|
||
|
|
this.port.postMessage({ type: "pcm", bytes: pcm.buffer, volume }, [pcm.buffer]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
registerProcessor("pcm16-capture", PCM16CaptureProcessor);
|