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
'getBuffer'
:
getBuffer();
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
getBuffer() {
var
buffers = [];
buffers.push(mergeBuffers(recBuffersL, recLength));
buffers.push( mergeBuffers(recBuffersR, recLength) );
this
.postMessage(buffers);
}
function
clear(inputBuffer) {
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) {
var
buffer =
new
ArrayBuffer(44 + samples.length * 2);
var
view =
new
DataView(buffer);
writeString(view, 0,
'RIFF'
);
view.setUint32(4, 32 + samples.length * 2,
true
);
writeString(view, 8,
'WAVE'
);
writeString(view, 12,
'fmt '
);
view.setUint32(16, 16,
true
);
view.setUint16(20, 1,
true
);
view.setUint16(22, 2,
true
);
view.setUint32(24, sampleRate,
true
);
view.setUint32(28, sampleRate * 4,
true
);
view.setUint16(32, 4,
true
);
view.setUint16(34, 16,
true
);
writeString(view, 36,
'data'
);
view.setUint32(40, samples.length * 2,
true
);
floatTo16BitPCM(view, 44, samples);
return
view;
}