annotate WAVE.js @ 1384:7cd2a8dcdc51

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