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