nickjillings@1353: // Decode and perform WAVE file byte level manipulation nickjillings@1353: nickjillings@1353: find_subarray = function(arr,subarr) { nickjillings@1353: var arr_length = arr.length; nickjillings@1353: var subarr_length = subarr.length; nickjillings@1353: var last_check_index = arr_length - subarr_length; nickjillings@1353: nickjillings@1353: positionLoop: nickjillings@1353: for (var i=0; i <= last_check_index; i++) nickjillings@1353: { nickjillings@1353: for (var j=0; j< subarr_length; j++) nickjillings@1353: { nickjillings@1353: if (arr[i + j] !== subarr[j]) { nickjillings@1353: continue positionLoop; nickjillings@1353: } nickjillings@1353: } nickjillings@1353: return i; nickjillings@1353: } nickjillings@1353: return -1; nickjillings@1353: }; nickjillings@1353: nickjillings@1353: function WAVE() nickjillings@1353: { nickjillings@1353: // The WAVE file object nickjillings@1353: this.status == 'WAVE_DECLARED' nickjillings@1353: nickjillings@1353: this.decoded_data = null; nickjillings@1353: nickjillings@1353: this.RIFF = String(); //ChunkID nickjillings@1353: this.size; //ChunkSize nickjillings@1353: this.FT_Header; //Format nickjillings@1353: this.fmt_marker; //Subchunk1ID nickjillings@1353: this.formatDataLength; //Subchunk1Size nickjillings@1353: this.type; //AudioFormat nickjillings@1353: this.num_channels; //NumChannels nickjillings@1353: this.sample_rate; //SampleRate nickjillings@1353: this.byte_rate; //ByteRate nickjillings@1353: this.block_align; //BlockAlign nickjillings@1353: this.bits_per_sample; //BitsPerSample nickjillings@1353: this.data_header; //Subchunk2ID nickjillings@1353: this.data_size; //Subchunk2Size nickjillings@1353: this.num_samples; nickjillings@1353: nickjillings@1353: this.open = function(IOArrayBuffer) nickjillings@1353: { nickjillings@1353: var IOView8 = new Uint8Array(IOArrayBuffer); nickjillings@1353: IOView8.subarray(0,4).forEach(function(i){ nickjillings@1353: var char = String.fromCharCode(i); nickjillings@1353: this.RIFF = this.RIFF.concat(char); nickjillings@1353: },this); nickjillings@1353: if (this.RIFF != 'RIFF') nickjillings@1353: { nickjillings@1353: console.log('WAVE ERR - Not a RIFF file'); nickjillings@1353: return 1; nickjillings@1353: } nickjillings@1353: this.size = 0; nickjillings@1353: IOView8.subarray(4,8).forEach(function(i,a){this.size += Number(i)<<(8*a);},this); nickjillings@1353: this.FT_Header = String(); nickjillings@1353: IOView8.subarray(8,12).forEach(function(i){this.FT_Header = this.FT_Header.concat(String.fromCharCode(i));},this); nickjillings@1353: this.fmt_marker = String(); nickjillings@1353: IOView8.subarray(12,16).forEach(function(i){this.fmt_marker = this.fmt_marker.concat(String.fromCharCode(i));},this); nickjillings@1353: this.formatDataLength = 0; nickjillings@1353: IOView8.subarray(16,20).forEach(function(i,a){this.formatDataLength += Number(i)<<(8*a);},this); nickjillings@1353: this.type = 0; nickjillings@1353: IOView8.subarray(20,22).forEach(function(i,a){this.type += Number(i)<<(8*a);},this); nickjillings@1353: this.num_channels = 0; nickjillings@1353: IOView8.subarray(22,24).forEach(function(i,a){this.num_channels += Number(i)<<(8*a);},this); nickjillings@1353: this.sample_rate = 0; nickjillings@1353: IOView8.subarray(24,28).forEach(function(i,a){this.sample_rate += Number(i)<<(8*a);},this); nickjillings@1353: this.byte_rate = 0; nickjillings@1353: IOView8.subarray(28,32).forEach(function(i,a){this.byte_rate += Number(i)<<(8*a);},this); nickjillings@1353: this.block_align = 0; nickjillings@1353: IOView8.subarray(32,34).forEach(function(i,a){this.block_align += Number(i)<<(8*a);},this); nickjillings@1353: this.bits_per_sample = 0; nickjillings@1353: IOView8.subarray(34,36).forEach(function(i,a){this.bits_per_sample += Number(i)<<(8*a);},this); nickjillings@1353: nickjillings@1353: // Find the data header first nickjillings@1353: var data_start = find_subarray(IOView8,[100, 97, 116, 97]); nickjillings@1353: nickjillings@1353: this.data_header = String(); nickjillings@1353: IOView8.subarray(data_start,data_start+4).forEach(function(i){this.data_header = this.data_header.concat(String.fromCharCode(i));},this); nickjillings@1353: this.data_size = 0; nickjillings@1353: IOView8.subarray(data_start+4,data_start+8).forEach(function(i,a){this.data_size += Number(i)<<(8*a);},this); nickjillings@1353: nickjillings@1353: this.num_samples = this.data_size / this.block_align; nickjillings@1353: nickjillings@1353: this.decoded_data = []; nickjillings@1353: if (this.type != 1 && this.type != 3) { nickjillings@1353: console.log("Neither PCM nor IEEE float, cannot decode"); nickjillings@1353: return 1; nickjillings@1353: } nickjillings@1353: for (var c=0; c= channels) { nickjillings@1353: channel_index = 0; nickjillings@1353: dst_index++; nickjillings@1353: } nickjillings@1353: } nickjillings@1353: } nickjillings@1353: nickjillings@1353: function integerConvert(srcView,dstView,srcBytes) nickjillings@1353: { nickjillings@1353: //Convert integers of a Uint8Array of certain byte length into a Float32Array nickjillings@1353: var number = dstView.length; nickjillings@1353: var outBits = srcBytes*8; nickjillings@1353: var endShift = 32 - outBits; nickjillings@1353: if (srcView.length != dstView.length*srcBytes) nickjillings@1353: { nickjillings@1353: return -1; nickjillings@1353: } nickjillings@1353: for (var n=0; n