annotate js/WAVE.js @ 2438:02df8de58e7b

Merge branch 'master' of https://github.com/BrechtDeMan/WebAudioEvaluationTool
author www-data <www-data@sucuk.dcs.qmul.ac.uk>
date Thu, 02 Jun 2016 17:20:55 +0100
parents 760719986df3
children 464c6c6692d6
rev   line source
nicholas@2224 1 // Decode and perform WAVE file byte level manipulation
nicholas@2224 2
nicholas@2224 3 find_subarray = function(arr,subarr) {
nicholas@2224 4 var arr_length = arr.length;
nicholas@2224 5 var subarr_length = subarr.length;
nicholas@2224 6 var last_check_index = arr_length - subarr_length;
nicholas@2224 7
nicholas@2224 8 positionLoop:
nicholas@2224 9 for (var i=0; i <= last_check_index; i++)
nicholas@2224 10 {
nicholas@2224 11 for (var j=0; j< subarr_length; j++)
nicholas@2224 12 {
nicholas@2224 13 if (arr[i + j] !== subarr[j]) {
nicholas@2224 14 continue positionLoop;
nicholas@2224 15 }
nicholas@2224 16 }
nicholas@2224 17 return i;
nicholas@2224 18 }
nicholas@2224 19 return -1;
nicholas@2224 20 };
nicholas@2224 21
nicholas@2224 22 function convertToInteger(arr) {
nicholas@2224 23 var value = 0;
nicholas@2224 24 for (var i=0; i<arr.length; i++)
nicholas@2224 25 {
nicholas@2224 26 value += arr[i]<<(i*8);
nicholas@2224 27 }
nicholas@2224 28 return value;
nicholas@2224 29 }
nicholas@2224 30 function convertToString(arr) {
nicholas@2224 31 var str = "";
nicholas@2224 32 for (var i=0; i<arr.length; i++)
nicholas@2224 33 {
nicholas@2224 34 str = str.concat(String.fromCharCode(arr[i]));
nicholas@2224 35 }
nicholas@2224 36 return str;
nicholas@2224 37 }
nicholas@2224 38
nicholas@2224 39 function WAVE()
nicholas@2224 40 {
nicholas@2224 41 // The WAVE file object
nicholas@2224 42 this.status == 'WAVE_DECLARED'
nicholas@2224 43
nicholas@2224 44 this.decoded_data = null;
nicholas@2224 45
nicholas@2224 46 this.RIFF = String(); //ChunkID
nicholas@2224 47 this.size; //ChunkSize
nicholas@2224 48 this.FT_Header; //Format
nicholas@2224 49 this.fmt_marker; //Subchunk1ID
nicholas@2224 50 this.formatDataLength; //Subchunk1Size
nicholas@2224 51 this.type; //AudioFormat
nicholas@2224 52 this.num_channels; //NumChannels
nicholas@2224 53 this.sample_rate; //SampleRate
nicholas@2224 54 this.byte_rate; //ByteRate
nicholas@2224 55 this.block_align; //BlockAlign
nicholas@2224 56 this.bits_per_sample; //BitsPerSample
nicholas@2224 57 this.data_header; //Subchunk2ID
nicholas@2224 58 this.data_size; //Subchunk2Size
nicholas@2224 59 this.num_samples;
nicholas@2224 60
nicholas@2224 61 this.open = function(IOArrayBuffer)
nicholas@2224 62 {
nicholas@2224 63 var IOView8 = new Uint8Array(IOArrayBuffer);
nicholas@2224 64 this.RIFF = convertToString(IOView8.subarray(0,4));
nicholas@2224 65 if (this.RIFF != 'RIFF')
nicholas@2224 66 {
nicholas@2224 67 console.log('WAVE ERR - Not a RIFF file');
nicholas@2224 68 return 1;
nicholas@2224 69 }
nicholas@2224 70 this.size = convertToInteger(IOView8.subarray(4,8));
nicholas@2224 71 this.FT_Header = convertToString(IOView8.subarray(8,12));
nicholas@2224 72 this.fmt_marker = convertToString(IOView8.subarray(12,16));
nicholas@2224 73 this.formatDataLength = convertToInteger(IOView8.subarray(16,20));
nicholas@2224 74 this.type = convertToInteger(IOView8.subarray(20,22));
nicholas@2224 75 this.num_channels = convertToInteger(IOView8.subarray(22,24));
nicholas@2224 76 this.sample_rate = convertToInteger(IOView8.subarray(24,28));
nicholas@2224 77 this.byte_rate = convertToInteger(IOView8.subarray(28,32));
nicholas@2224 78 this.block_align = convertToInteger(IOView8.subarray(32,34));
nicholas@2224 79 this.bits_per_sample = convertToInteger(IOView8.subarray(34,36));
nicholas@2224 80
nicholas@2224 81 // Find the data header first
nicholas@2224 82 var data_start = find_subarray(IOView8,[100, 97, 116, 97]);
nicholas@2224 83
nicholas@2224 84 this.data_header = convertToString(IOView8.subarray(data_start,data_start+4));
nicholas@2224 85 this.data_size = convertToInteger(IOView8.subarray(data_start+4,data_start+8));
nicholas@2224 86
nicholas@2224 87 this.num_samples = this.data_size / this.block_align;
nicholas@2224 88
nicholas@2224 89 this.decoded_data = [];
nicholas@2224 90 if (this.type != 1 && this.type != 3) {
nicholas@2224 91 console.log("Neither PCM nor IEEE float, cannot decode");
nicholas@2224 92 return 1;
nicholas@2224 93 }
nicholas@2224 94 for (var c=0; c<this.num_channels; c++)
nicholas@2224 95 {
nicholas@2224 96 this.decoded_data.push(new Float32Array(this.num_samples));
nicholas@2224 97 }
nicholas@2224 98 var sampleDataOffset = data_start+8;
nicholas@2224 99
nicholas@2224 100 // Now need to decode the data from sampleDataOffset
nicholas@2224 101 // Data is always interleved
nicholas@2224 102 var data_view;
nicholas@2224 103 if (this.type == 3)
nicholas@2224 104 {
nicholas@2224 105 // Already in float
nicholas@2224 106 if (this.bits_per_sample == 32) {
nicholas@2224 107 data_view = new Float32Array(IOArrayBuffer.slice(sampleDataOffset,sampleDataOffset+this.data_size));
nicholas@2224 108 } else if (this.bits_per_sample == 64) {
nicholas@2224 109 data_view = new Float64Array(IOArrayBuffer.slice(sampleDataOffset,sampleDataOffset+this.data_size));
nicholas@2224 110 }
nicholas@2224 111 } else if (this.type == 1)
nicholas@2224 112 {
nicholas@2224 113 data_view = new Float32Array(this.num_samples*this.num_channels);
nicholas@2224 114 integerConvert(new Uint8Array(IOArrayBuffer.slice(sampleDataOffset,sampleDataOffset+this.data_size)),data_view,this.bits_per_sample/8);
nicholas@2224 115 }
nicholas@2224 116 deInterlace(data_view,this.decoded_data);
nicholas@2224 117 return 0;
nicholas@2224 118 };
nicholas@2224 119 }
nicholas@2224 120
nicholas@2224 121 function deInterlace(src_array, dst_array)
nicholas@2224 122 {
nicholas@2224 123 var number = src_array.length;
nicholas@2224 124 var channels = dst_array.length;
nicholas@2224 125 var channel_index = 0;
nicholas@2224 126 var dst_index = 0;
nicholas@2224 127 for (var n=0; n<number; n++)
nicholas@2224 128 {
nicholas@2224 129 dst_array[channel_index][dst_index] = src_array[n];
nicholas@2224 130 channel_index++;
nicholas@2224 131 if (channel_index >= channels) {
nicholas@2224 132 channel_index = 0;
nicholas@2224 133 dst_index++;
nicholas@2224 134 }
nicholas@2224 135 }
nicholas@2224 136 }
nicholas@2224 137
nicholas@2224 138 function integerConvert(srcView,dstView,srcBytes)
nicholas@2224 139 {
nicholas@2224 140 //Convert integers of a Uint8Array of certain byte length into a Float32Array
nicholas@2224 141 var number = dstView.length;
nicholas@2224 142 var outBits = srcBytes*8;
nicholas@2224 143 var endShift = 32 - outBits;
nicholas@2224 144 if (srcView.length != dstView.length*srcBytes)
nicholas@2224 145 {
nicholas@2224 146 return -1;
nicholas@2224 147 }
nicholas@2224 148 for (var n=0; n<number; n++)
nicholas@2224 149 {
nicholas@2224 150 var srcIndex = n*srcBytes;
nicholas@2224 151 var intData = convertToInteger(srcView.subarray(srcIndex,srcIndex+srcBytes));
nicholas@2224 152 intData = (intData << (endShift));
nicholas@2224 153 dstView[n] = intData / 2147483648;
nicholas@2224 154 }
nicholas@2224 155 }