UNPKG

waveform-playlist

Version:

Multiple track web audio editor and player with waveform preview

154 lines (122 loc) 3.5 kB
export default function () { let recLength = 0; let recBuffersL = []; let recBuffersR = []; let sampleRate; function init(config) { sampleRate = config.sampleRate; } function record(inputBuffer) { recBuffersL.push(inputBuffer[0]); recBuffersR.push(inputBuffer[1]); recLength += inputBuffer[0].length; } function writeString(view, offset, string) { for (let i = 0; i < string.length; i += 1) { view.setUint8(offset + i, string.charCodeAt(i)); } } function floatTo16BitPCM(output, offset, input) { let writeOffset = offset; for (let i = 0; i < input.length; i += 1, writeOffset += 2) { const s = Math.max(-1, Math.min(1, input[i])); output.setInt16(writeOffset, s < 0 ? s * 0x8000 : s * 0x7fff, true); } } function encodeWAV(samples, mono = false) { const buffer = new ArrayBuffer(44 + samples.length * 2); const view = new DataView(buffer); /* RIFF identifier */ writeString(view, 0, "RIFF"); /* file length */ view.setUint32(4, 32 + samples.length * 2, true); /* RIFF type */ writeString(view, 8, "WAVE"); /* format chunk identifier */ writeString(view, 12, "fmt "); /* format chunk length */ view.setUint32(16, 16, true); /* sample format (raw) */ view.setUint16(20, 1, true); /* channel count */ view.setUint16(22, mono ? 1 : 2, true); /* sample rate */ view.setUint32(24, sampleRate, true); /* byte rate (sample rate * block align) */ view.setUint32(28, sampleRate * 4, true); /* block align (channel count * bytes per sample) */ view.setUint16(32, 4, true); /* bits per sample */ view.setUint16(34, 16, true); /* data chunk identifier */ writeString(view, 36, "data"); /* data chunk length */ view.setUint32(40, samples.length * 2, true); floatTo16BitPCM(view, 44, samples); return view; } function mergeBuffers(recBuffers, length) { const result = new Float32Array(length); let offset = 0; for (let i = 0; i < recBuffers.length; i += 1) { result.set(recBuffers[i], offset); offset += recBuffers[i].length; } return result; } function interleave(inputL, inputR) { const length = inputL.length + inputR.length; const result = new Float32Array(length); let index = 0; let inputIndex = 0; while (index < length) { result[index += 1] = inputL[inputIndex]; result[index += 1] = inputR[inputIndex]; inputIndex += 1; } return result; } function exportWAV(type) { const bufferL = mergeBuffers(recBuffersL, recLength); const bufferR = mergeBuffers(recBuffersR, recLength); const interleaved = interleave(bufferL, bufferR); const dataview = encodeWAV(interleaved); const audioBlob = new Blob([dataview], { type }); postMessage(audioBlob); } function clear() { recLength = 0; recBuffersL = []; recBuffersR = []; } onmessage = function onmessage(e) { switch (e.data.command) { case "init": { init(e.data.config); break; } case "record": { record(e.data.buffer); break; } case "exportWAV": { exportWAV(e.data.type); break; } case "clear": { clear(); break; } default: { throw new Error("Unknown export worker command"); } } }; }