const SAMPLE_RATE = 48000; const PACKET_MS = 20; const PACKET_FRAMES = PACKET_MS / 1000 * SAMPLE_RATE; console.log("Frames per packet:", PACKET_FRAMES); class RustWorklet extends AudioWorkletProcessor { constructor(options) { super(); this.module = options.processorOptions; this.timestamp = null; this.buffer = new Float32Array(PACKET_FRAMES); this.buffer_offset = 0; if (sampleRate != SAMPLE_RATE) { throw Error(`sample rate ${sampleRate} should be ${SAMPLE_RATE}`); } console.log('RustWorklet:', this); } do_send() { const data = { format: 'f32', sampleRate: SAMPLE_RATE, numberOfFrames: this.buffer_offset, numberOfChannels: 1, timestamp: this.timestamp, data: this.buffer.slice(0, this.buffer_offset), }; this.port.postMessage(data); this.buffer_offset = 0; this.timestamp = null; } process(inputs) { const input = inputs[0]; if (input.length == 0) { return true } if (this.timestamp == null) { this.timestamp = currentFrame / SAMPLE_RATE * 1e6; } const frames = input[0]; if (this.buffer_offset + frames.length > this.buffer.length) { // too full, send now this.do_send(); } this.buffer.set(frames, this.buffer_offset); this.buffer_offset += frames.length; if (this.buffer_offset + 128 > this.buffer.length) { // full enough, send now this.do_send(); } return true; } }; registerProcessor("rust_mic_worklet", RustWorklet);