File size: 2,055 Bytes
022e8a2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
export default () => {
class BufferedAudioWorkletProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.bufferQueue = [];
this.currentChunkOffset = 0;
this.hadData = false;
this.port.onmessage = (event) => {
const data = event.data;
if (data instanceof Float32Array) {
this.hadData = true;
this.bufferQueue.push(data);
} else if (data === "stop") {
this.bufferQueue = [];
this.currentChunkOffset = 0;
}
};
}
process(inputs, outputs) {
const channel = outputs[0][0];
if (!channel) return true;
const numSamples = channel.length;
let outputIndex = 0;
if (this.hadData && this.bufferQueue.length === 0) {
this.port.postMessage({ type: "playback_ended" });
this.hadData = false;
}
while (outputIndex < numSamples) {
if (this.bufferQueue.length > 0) {
const currentChunk = this.bufferQueue[0];
const remainingSamples =
currentChunk.length - this.currentChunkOffset;
const samplesToCopy = Math.min(
remainingSamples,
numSamples - outputIndex,
);
channel.set(
currentChunk.subarray(
this.currentChunkOffset,
this.currentChunkOffset + samplesToCopy,
),
outputIndex,
);
this.currentChunkOffset += samplesToCopy;
outputIndex += samplesToCopy;
// Remove the chunk if fully consumed.
if (this.currentChunkOffset >= currentChunk.length) {
this.bufferQueue.shift();
this.currentChunkOffset = 0;
}
} else {
// If no data is available, fill the rest of the buffer with silence.
channel.fill(0, outputIndex);
outputIndex = numSamples;
}
}
return true;
}
}
registerProcessor(
"buffered-audio-worklet-processor",
BufferedAudioWorkletProcessor,
);
};
|