Spaces:
Sleeping
Sleeping
var recLength = 0, | |
recBuffersL = [], | |
recBuffersR = [], | |
sampleRate; | |
this.onmessage = function(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 'exportMonoWAV': | |
exportMonoWAV(e.data.type); | |
break; | |
case 'getBuffers': | |
getBuffers(); | |
break; | |
case 'clear': | |
clear(); | |
break; | |
} | |
}; | |
function init(config){ | |
sampleRate = config.sampleRate; | |
} | |
function record(inputBuffer){ | |
recBuffersL.push(inputBuffer[0]); | |
recBuffersR.push(inputBuffer[1]); | |
recLength += inputBuffer[0].length; | |
} | |
function exportWAV(type){ | |
var bufferL = mergeBuffers(recBuffersL, recLength); | |
var bufferR = mergeBuffers(recBuffersR, recLength); | |
var interleaved = interleave(bufferL, bufferR); | |
var dataview = encodeWAV(interleaved); | |
var audioBlob = new Blob([dataview], { type: type }); | |
this.postMessage(audioBlob); | |
} | |
function exportMonoWAV(type){ | |
var bufferL = mergeBuffers(recBuffersL, recLength); | |
var dataview = encodeWAV(bufferL, true); | |
var audioBlob = new Blob([dataview], { type: type }); | |
this.postMessage(audioBlob); | |
} | |
function getBuffers() { | |
var buffers = []; | |
buffers.push( mergeBuffers(recBuffersL, recLength) ); | |
buffers.push( mergeBuffers(recBuffersR, recLength) ); | |
this.postMessage(buffers); | |
} | |
function clear(){ | |
recLength = 0; | |
recBuffersL = []; | |
recBuffersR = []; | |
} | |
function mergeBuffers(recBuffers, recLength){ | |
var result = new Float32Array(recLength); | |
var offset = 0; | |
for (var i = 0; i < recBuffers.length; i++){ | |
result.set(recBuffers[i], offset); | |
offset += recBuffers[i].length; | |
} | |
return result; | |
} | |
function interleave(inputL, inputR){ | |
var length = inputL.length + inputR.length; | |
var result = new Float32Array(length); | |
var index = 0, | |
inputIndex = 0; | |
while (index < length){ | |
result[index++] = inputL[inputIndex]; | |
result[index++] = inputR[inputIndex]; | |
inputIndex++; | |
} | |
return result; | |
} | |
function floatTo16BitPCM(output, offset, input){ | |
for (var i = 0; i < input.length; i++, offset+=2){ | |
var s = Math.max(-1, Math.min(1, input[i])); | |
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); | |
} | |
} | |
function writeString(view, offset, string){ | |
for (var i = 0; i < string.length; i++){ | |
view.setUint8(offset + i, string.charCodeAt(i)); | |
} | |
} | |
function encodeWAV(samples, mono){ | |
var buffer = new ArrayBuffer(44 + samples.length * 2); | |
var 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; | |
} | |