You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			132 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
		
		
			
		
	
	
			132 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
| 
											9 years ago
										 | 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; | ||
|  | } |