131 lines
		
	
	
	
		
			3.1 KiB
			
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
	
		
			3.1 KiB
			
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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(){
 | 
						|
  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);
 | 
						|
 | 
						|
  /* RIFF identifier */
 | 
						|
  writeString(view, 0, 'RIFF');
 | 
						|
  /* RIFF chunk length */
 | 
						|
  view.setUint32(4, 36 + 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, 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;
 | 
						|
}
 |