UNPKG

wavtools

Version:

Record and stream WAV audio data in the browser across all platforms

97 lines (92 loc) 3.03 kB
export const StreamProcessorWorklet = ` class StreamProcessor extends AudioWorkletProcessor { constructor() { super(); this.hasStarted = false; this.hasInterrupted = false; this.outputBuffers = []; this.bufferLength = 128; this.write = { buffer: new Float32Array(this.bufferLength), trackId: null }; this.writeOffset = 0; this.trackSampleOffsets = {}; this.port.onmessage = (event) => { if (event.data) { const payload = event.data; if (payload.event === 'write') { const int16Array = payload.buffer; const float32Array = new Float32Array(int16Array.length); for (let i = 0; i < int16Array.length; i++) { float32Array[i] = int16Array[i] / 0x8000; // Convert Int16 to Float32 } this.writeData(float32Array, payload.trackId); } else if ( payload.event === 'offset' || payload.event === 'interrupt' ) { const requestId = payload.requestId; const trackId = this.write.trackId; const offset = this.trackSampleOffsets[trackId] || 0; this.port.postMessage({ event: 'offset', requestId, trackId, offset, }); if (payload.event === 'interrupt') { this.hasInterrupted = true; } } else { throw new Error(\`Unhandled event "\${payload.event}"\`); } } }; } writeData(float32Array, trackId = null) { let { buffer } = this.write; let offset = this.writeOffset; for (let i = 0; i < float32Array.length; i++) { buffer[offset++] = float32Array[i]; if (offset >= buffer.length) { this.outputBuffers.push(this.write); this.write = { buffer: new Float32Array(this.bufferLength), trackId }; buffer = this.write.buffer; offset = 0; } } this.writeOffset = offset; return true; } process(inputs, outputs, parameters) { const output = outputs[0]; const outputChannelData = output[0]; const outputBuffers = this.outputBuffers; if (this.hasInterrupted) { this.port.postMessage({ event: 'stop' }); return false; } else if (outputBuffers.length) { this.hasStarted = true; const { buffer, trackId } = outputBuffers.shift(); for (let i = 0; i < outputChannelData.length; i++) { outputChannelData[i] = buffer[i] || 0; } if (trackId) { this.trackSampleOffsets[trackId] = this.trackSampleOffsets[trackId] || 0; this.trackSampleOffsets[trackId] += buffer.length; } return true; } else if (this.hasStarted) { this.port.postMessage({ event: 'stop' }); return false; } else { return true; } } } registerProcessor('stream_processor', StreamProcessor); `; const script = new Blob([StreamProcessorWorklet], { type: 'application/javascript', }); const src = URL.createObjectURL(script); export const StreamProcessorSrc = src;