OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 /** | 6 /** |
7 * @fileOverview This file includes legacy utility functions for the layout | 7 * @fileOverview This file includes legacy utility functions for the layout |
8 * test. | 8 * test. |
9 */ | 9 */ |
10 | 10 |
11 | 11 |
12 function writeString(s, a, offset) { | 12 function writeString(s, a, offset) { |
13 for (var i = 0; i < s.length; ++i) { | 13 for (let i = 0; i < s.length; ++i) { |
14 a[offset + i] = s.charCodeAt(i); | 14 a[offset + i] = s.charCodeAt(i); |
15 } | 15 } |
16 } | 16 } |
17 | 17 |
18 function writeInt16(n, a, offset) { | 18 function writeInt16(n, a, offset) { |
19 n = Math.floor(n); | 19 n = Math.floor(n); |
20 | 20 |
21 var b1 = n & 255; | 21 let b1 = n & 255; |
22 var b2 = (n >> 8) & 255; | 22 let b2 = (n >> 8) & 255; |
23 | 23 |
24 a[offset + 0] = b1; | 24 a[offset + 0] = b1; |
25 a[offset + 1] = b2; | 25 a[offset + 1] = b2; |
26 } | 26 } |
27 | 27 |
28 function writeInt32(n, a, offset) { | 28 function writeInt32(n, a, offset) { |
29 n = Math.floor(n); | 29 n = Math.floor(n); |
30 var b1 = n & 255; | 30 let b1 = n & 255; |
31 var b2 = (n >> 8) & 255; | 31 let b2 = (n >> 8) & 255; |
32 var b3 = (n >> 16) & 255; | 32 let b3 = (n >> 16) & 255; |
33 var b4 = (n >> 24) & 255; | 33 let b4 = (n >> 24) & 255; |
34 | 34 |
35 a[offset + 0] = b1; | 35 a[offset + 0] = b1; |
36 a[offset + 1] = b2; | 36 a[offset + 1] = b2; |
37 a[offset + 2] = b3; | 37 a[offset + 2] = b3; |
38 a[offset + 3] = b4; | 38 a[offset + 3] = b4; |
39 } | 39 } |
40 | 40 |
41 // Return the bits of the float as a 32-bit integer value. This | 41 // Return the bits of the float as a 32-bit integer value. This |
42 // produces the raw bits; no intepretation of the value is done. | 42 // produces the raw bits; no intepretation of the value is done. |
43 function floatBits(f) { | 43 function floatBits(f) { |
44 var buf = new ArrayBuffer(4); | 44 let buf = new ArrayBuffer(4); |
45 (new Float32Array(buf))[0] = f; | 45 (new Float32Array(buf))[0] = f; |
46 var bits = (new Uint32Array(buf))[0]; | 46 let bits = (new Uint32Array(buf))[0]; |
47 // Return as a signed integer. | 47 // Return as a signed integer. |
48 return bits | 0; | 48 return bits | 0; |
49 } | 49 } |
50 | 50 |
51 function writeAudioBuffer(audioBuffer, a, offset, asFloat) { | 51 function writeAudioBuffer(audioBuffer, a, offset, asFloat) { |
52 var n = audioBuffer.length; | 52 let n = audioBuffer.length; |
53 var channels = audioBuffer.numberOfChannels; | 53 let channels = audioBuffer.numberOfChannels; |
54 | 54 |
55 for (var i = 0; i < n; ++i) { | 55 for (let i = 0; i < n; ++i) { |
56 for (var k = 0; k < channels; ++k) { | 56 for (let k = 0; k < channels; ++k) { |
57 var buffer = audioBuffer.getChannelData(k); | 57 let buffer = audioBuffer.getChannelData(k); |
58 if (asFloat) { | 58 if (asFloat) { |
59 var sample = floatBits(buffer[i]); | 59 let sample = floatBits(buffer[i]); |
60 writeInt32(sample, a, offset); | 60 writeInt32(sample, a, offset); |
61 offset += 4; | 61 offset += 4; |
62 } else { | 62 } else { |
63 var sample = buffer[i] * 32768.0; | 63 let sample = buffer[i] * 32768.0; |
64 | 64 |
65 // Clip samples to the limitations of 16-bit. | 65 // Clip samples to the limitations of 16-bit. |
66 // If we don't do this then we'll get nasty wrap-around distortion
. | 66 // If we don't do this then we'll get nasty wrap-around distortion. |
67 if (sample < -32768) | 67 if (sample < -32768) |
68 sample = -32768; | 68 sample = -32768; |
69 if (sample > 32767) | 69 if (sample > 32767) |
70 sample = 32767; | 70 sample = 32767; |
71 | 71 |
72 writeInt16(sample, a, offset); | 72 writeInt16(sample, a, offset); |
73 offset += 2; | 73 offset += 2; |
74 } | 74 } |
75 } | |
76 } | 75 } |
| 76 } |
77 } | 77 } |
78 | 78 |
79 // See http://soundfile.sapp.org/doc/WaveFormat/ and | 79 // See http://soundfile.sapp.org/doc/WaveFormat/ and |
80 // http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html | 80 // http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html |
81 // for a quick introduction to the WAVE PCM format. | 81 // for a quick introduction to the WAVE PCM format. |
82 function createWaveFileData(audioBuffer, asFloat) { | 82 function createWaveFileData(audioBuffer, asFloat) { |
83 var bytesPerSample = asFloat ? 4 : 2; | 83 let bytesPerSample = asFloat ? 4 : 2; |
84 var frameLength = audioBuffer.length; | 84 let frameLength = audioBuffer.length; |
85 var numberOfChannels = audioBuffer.numberOfChannels; | 85 let numberOfChannels = audioBuffer.numberOfChannels; |
86 var sampleRate = audioBuffer.sampleRate; | 86 let sampleRate = audioBuffer.sampleRate; |
87 var bitsPerSample = 8 * bytesPerSample; | 87 let bitsPerSample = 8 * bytesPerSample; |
88 var byteRate = sampleRate * numberOfChannels * bitsPerSample/8; | 88 let byteRate = sampleRate * numberOfChannels * bitsPerSample / 8; |
89 var blockAlign = numberOfChannels * bitsPerSample/8; | 89 let blockAlign = numberOfChannels * bitsPerSample / 8; |
90 var wavDataByteLength = frameLength * numberOfChannels * bytesPerSample; | 90 let wavDataByteLength = frameLength * numberOfChannels * bytesPerSample; |
91 var headerByteLength = 44; | 91 let headerByteLength = 44; |
92 var totalLength = headerByteLength + wavDataByteLength; | 92 let totalLength = headerByteLength + wavDataByteLength; |
93 | 93 |
94 var waveFileData = new Uint8Array(totalLength); | 94 let waveFileData = new Uint8Array(totalLength); |
95 | 95 |
96 var subChunk1Size = 16; // for linear PCM | 96 let subChunk1Size = 16; // for linear PCM |
97 var subChunk2Size = wavDataByteLength; | 97 let subChunk2Size = wavDataByteLength; |
98 var chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size); | 98 let chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size); |
99 | 99 |
100 writeString("RIFF", waveFileData, 0); | 100 writeString('RIFF', waveFileData, 0); |
101 writeInt32(chunkSize, waveFileData, 4); | 101 writeInt32(chunkSize, waveFileData, 4); |
102 writeString("WAVE", waveFileData, 8); | 102 writeString('WAVE', waveFileData, 8); |
103 writeString("fmt ", waveFileData, 12); | 103 writeString('fmt ', waveFileData, 12); |
104 | 104 |
105 writeInt32(subChunk1Size, waveFileData, 16); // SubChunk1Size (4) | 105 writeInt32(subChunk1Size, waveFileData, 16); // SubChunk1Size (4) |
106 // The format tag value is 1 for integer PCM data and 3 for IEEE | 106 // The format tag value is 1 for integer PCM data and 3 for IEEE |
107 // float data. | 107 // float data. |
108 writeInt16(asFloat ? 3 : 1, waveFileData, 20); // AudioFormat (2) | 108 writeInt16(asFloat ? 3 : 1, waveFileData, 20); // AudioFormat (2) |
109 writeInt16(numberOfChannels, waveFileData, 22); // NumChannels (2) | 109 writeInt16(numberOfChannels, waveFileData, 22); // NumChannels (2) |
110 writeInt32(sampleRate, waveFileData, 24); // SampleRate (4) | 110 writeInt32(sampleRate, waveFileData, 24); // SampleRate (4) |
111 writeInt32(byteRate, waveFileData, 28); // ByteRate (4) | 111 writeInt32(byteRate, waveFileData, 28); // ByteRate (4) |
112 writeInt16(blockAlign, waveFileData, 32); // BlockAlign (2) | 112 writeInt16(blockAlign, waveFileData, 32); // BlockAlign (2) |
113 writeInt32(bitsPerSample, waveFileData, 34); // BitsPerSample (4) | 113 writeInt32(bitsPerSample, waveFileData, 34); // BitsPerSample (4) |
114 | 114 |
115 writeString("data", waveFileData, 36); | 115 writeString('data', waveFileData, 36); |
116 writeInt32(subChunk2Size, waveFileData, 40); // SubChunk2Size (4) | 116 writeInt32(subChunk2Size, waveFileData, 40); // SubChunk2Size (4) |
117 | 117 |
118 // Write actual audio data starting at offset 44. | 118 // Write actual audio data starting at offset 44. |
119 writeAudioBuffer(audioBuffer, waveFileData, 44, asFloat); | 119 writeAudioBuffer(audioBuffer, waveFileData, 44, asFloat); |
120 | 120 |
121 return waveFileData; | 121 return waveFileData; |
122 } | 122 } |
123 | 123 |
124 function createAudioData(audioBuffer, asFloat) { | 124 function createAudioData(audioBuffer, asFloat) { |
125 return createWaveFileData(audioBuffer, asFloat); | 125 return createWaveFileData(audioBuffer, asFloat); |
126 } | 126 } |
127 | 127 |
128 function finishAudioTest(event) { | 128 function finishAudioTest(event) { |
129 var audioData = createAudioData(event.renderedBuffer); | 129 let audioData = createAudioData(event.renderedBuffer); |
130 testRunner.setAudioData(audioData); | 130 testRunner.setAudioData(audioData); |
131 testRunner.notifyDone(); | 131 testRunner.notifyDone(); |
132 } | 132 } |
133 | 133 |
134 // Save the given |audioBuffer| to a WAV file using the name given by | 134 // Save the given |audioBuffer| to a WAV file using the name given by |
135 // |filename|. This is intended to be run from a browser. The | 135 // |filename|. This is intended to be run from a browser. The |
136 // developer is expected to use the console to run downloadAudioBuffer | 136 // developer is expected to use the console to run downloadAudioBuffer |
137 // when necessary to create a new reference file for a test. If | 137 // when necessary to create a new reference file for a test. If |
138 // |asFloat| is given and is true, the WAV file produced uses 32-bit | 138 // |asFloat| is given and is true, the WAV file produced uses 32-bit |
139 // float format (full WebAudio resolution). Otherwise a 16-bit PCM | 139 // float format (full WebAudio resolution). Otherwise a 16-bit PCM |
140 // WAV file is produced. | 140 // WAV file is produced. |
141 function downloadAudioBuffer(audioBuffer, filename, asFloat) { | 141 function downloadAudioBuffer(audioBuffer, filename, asFloat) { |
142 // Don't download if testRunner is defined; we're running a layout | 142 // Don't download if testRunner is defined; we're running a layout |
143 // test where this won't be useful in general. | 143 // test where this won't be useful in general. |
144 if (window.testRunner) | 144 if (window.testRunner) |
145 return false; | 145 return false; |
146 // Convert the audio buffer to an array containing the WAV file | 146 // Convert the audio buffer to an array containing the WAV file |
147 // contents. Then convert it to a blob that can be saved as a WAV | 147 // contents. Then convert it to a blob that can be saved as a WAV |
148 // file. | 148 // file. |
149 let wavData = createAudioData(audioBuffer, asFloat); | 149 let wavData = createAudioData(audioBuffer, asFloat); |
150 let blob = new Blob([wavData], {type: 'audio/wav'}); | 150 let blob = new Blob([wavData], {type: 'audio/wav'}); |
151 // Manually create html tags for downloading, and simulate a click | 151 // Manually create html tags for downloading, and simulate a click |
152 // to download the file to the given file name. | 152 // to download the file to the given file name. |
153 let a = document.createElement('a'); | 153 let a = document.createElement('a'); |
154 a.style.display = 'none'; | 154 a.style.display = 'none'; |
155 a.download = filename; | 155 a.download = filename; |
156 let audioURL = window.URL.createObjectURL(blob); | 156 let audioURL = window.URL.createObjectURL(blob); |
157 let audio = new Audio(); | 157 let audio = new Audio(); |
158 audio.src = audioURL; | 158 audio.src = audioURL; |
159 a.href = audioURL; | 159 a.href = audioURL; |
160 document.body.appendChild(a); | 160 document.body.appendChild(a); |
161 a.click(); | 161 a.click(); |
162 return true; | 162 return true; |
163 } | 163 } |
164 | 164 |
165 // Compare two arrays (commonly extracted from buffer.getChannelData()) with | 165 // Compare two arrays (commonly extracted from buffer.getChannelData()) with |
166 // constraints: | 166 // constraints: |
167 // options.thresholdSNR: Minimum allowed SNR between the actual and expected | 167 // options.thresholdSNR: Minimum allowed SNR between the actual and expected |
168 // signal. The default value is 10000. | 168 // signal. The default value is 10000. |
169 // options.thresholdDiffULP: Maximum allowed difference between the actual | 169 // options.thresholdDiffULP: Maximum allowed difference between the actual |
170 // and expected signal in ULP(Unit in the last place). The default is 0. | 170 // and expected signal in ULP(Unit in the last place). The default is 0. |
171 // options.thresholdDiffCount: Maximum allowed number of sample differences | 171 // options.thresholdDiffCount: Maximum allowed number of sample differences |
172 // which exceeds the threshold. The default is 0. | 172 // which exceeds the threshold. The default is 0. |
173 // options.bitDepth: The expected result is assumed to come from an audio | 173 // options.bitDepth: The expected result is assumed to come from an audio |
174 // file with this number of bits of precision. The default is 16. | 174 // file with this number of bits of precision. The default is 16. |
175 function compareBuffersWithConstraints(should, actual, expected, options) { | 175 function compareBuffersWithConstraints(should, actual, expected, options) { |
176 if (!options) | 176 if (!options) |
177 options = {}; | 177 options = {}; |
178 | 178 |
179 // Only print out the message if the lengths are different; the | 179 // Only print out the message if the lengths are different; the |
180 // expectation is that they are the same, so don't clutter up the | 180 // expectation is that they are the same, so don't clutter up the |
181 // output. | 181 // output. |
182 if (actual.length !== expected.length) { | 182 if (actual.length !== expected.length) { |
183 should(actual.length === expected.length, | 183 should( |
184 "Length of actual and expected buffers should match") | 184 actual.length === expected.length, |
185 .beTrue(); | 185 'Length of actual and expected buffers should match') |
| 186 .beTrue(); |
| 187 } |
| 188 |
| 189 let maxError = -1; |
| 190 let diffCount = 0; |
| 191 let errorPosition = -1; |
| 192 let thresholdSNR = (options.thresholdSNR || 10000); |
| 193 |
| 194 let thresholdDiffULP = (options.thresholdDiffULP || 0); |
| 195 let thresholdDiffCount = (options.thresholdDiffCount || 0); |
| 196 |
| 197 // By default, the bit depth is 16. |
| 198 let bitDepth = (options.bitDepth || 16); |
| 199 let scaleFactor = Math.pow(2, bitDepth - 1); |
| 200 |
| 201 let noisePower = 0, signalPower = 0; |
| 202 |
| 203 for (let i = 0; i < actual.length; i++) { |
| 204 let diff = actual[i] - expected[i]; |
| 205 noisePower += diff * diff; |
| 206 signalPower += expected[i] * expected[i]; |
| 207 |
| 208 if (Math.abs(diff) > maxError) { |
| 209 maxError = Math.abs(diff); |
| 210 errorPosition = i; |
186 } | 211 } |
187 | 212 |
188 var maxError = -1; | 213 // The reference file is a 16-bit WAV file, so we will almost never get |
189 var diffCount = 0; | 214 // an exact match between it and the actual floating-point result. |
190 var errorPosition = -1; | 215 if (Math.abs(diff) > scaleFactor) |
191 var thresholdSNR = (options.thresholdSNR || 10000); | 216 diffCount++; |
| 217 } |
192 | 218 |
193 var thresholdDiffULP = (options.thresholdDiffULP || 0); | 219 let snr = 10 * Math.log10(signalPower / noisePower); |
194 var thresholdDiffCount = (options.thresholdDiffCount || 0); | 220 let maxErrorULP = maxError * scaleFactor; |
195 | 221 |
196 // By default, the bit depth is 16. | 222 should(snr, 'SNR').beGreaterThanOrEqualTo(thresholdSNR); |
197 var bitDepth = (options.bitDepth || 16); | |
198 var scaleFactor = Math.pow(2, bitDepth - 1); | |
199 | 223 |
200 var noisePower = 0, signalPower = 0; | 224 should( |
| 225 maxErrorULP, |
| 226 options.prefix + ': Maximum difference (in ulp units (' + bitDepth + |
| 227 '-bits))') |
| 228 .beLessThanOrEqualTo(thresholdDiffULP); |
201 | 229 |
202 for (var i = 0; i < actual.length; i++) { | 230 should(diffCount, options.prefix + ': Number of differences between results') |
203 var diff = actual[i] - expected[i]; | 231 .beLessThanOrEqualTo(thresholdDiffCount); |
204 noisePower += diff * diff; | |
205 signalPower += expected[i] * expected[i]; | |
206 | |
207 if (Math.abs(diff) > maxError) { | |
208 maxError = Math.abs(diff); | |
209 errorPosition = i; | |
210 } | |
211 | |
212 // The reference file is a 16-bit WAV file, so we will almost never get | |
213 // an exact match between it and the actual floating-point result. | |
214 if (Math.abs(diff) > scaleFactor) | |
215 diffCount++; | |
216 } | |
217 | |
218 var snr = 10 * Math.log10(signalPower / noisePower); | |
219 var maxErrorULP = maxError * scaleFactor; | |
220 | |
221 should(snr, "SNR").beGreaterThanOrEqualTo(thresholdSNR); | |
222 | |
223 should(maxErrorULP, | |
224 options.prefix + ': Maximum difference (in ulp units (' + bitDepth + | |
225 '-bits))' | |
226 ).beLessThanOrEqualTo(thresholdDiffULP); | |
227 | |
228 should(diffCount, options.prefix + | |
229 ': Number of differences between results').beLessThanOrEqualTo( | |
230 thresholdDiffCount); | |
231 } | 232 } |
232 | 233 |
233 // Create an impulse in a buffer of length sampleFrameLength | 234 // Create an impulse in a buffer of length sampleFrameLength |
234 function createImpulseBuffer(context, sampleFrameLength) { | 235 function createImpulseBuffer(context, sampleFrameLength) { |
235 var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleR
ate); | 236 let audioBuffer = |
236 var n = audioBuffer.length; | 237 context.createBuffer(1, sampleFrameLength, context.sampleRate); |
237 var dataL = audioBuffer.getChannelData(0); | 238 let n = audioBuffer.length; |
| 239 let dataL = audioBuffer.getChannelData(0); |
238 | 240 |
239 for (var k = 0; k < n; ++k) { | 241 for (let k = 0; k < n; ++k) { |
240 dataL[k] = 0; | 242 dataL[k] = 0; |
241 } | 243 } |
242 dataL[0] = 1; | 244 dataL[0] = 1; |
243 | 245 |
244 return audioBuffer; | 246 return audioBuffer; |
245 } | 247 } |
246 | 248 |
247 // Create a buffer of the given length with a linear ramp having values 0 <= x <
1. | 249 // Create a buffer of the given length with a linear ramp having values 0 <= x < |
| 250 // 1. |
248 function createLinearRampBuffer(context, sampleFrameLength) { | 251 function createLinearRampBuffer(context, sampleFrameLength) { |
249 var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleR
ate); | 252 let audioBuffer = |
250 var n = audioBuffer.length; | 253 context.createBuffer(1, sampleFrameLength, context.sampleRate); |
251 var dataL = audioBuffer.getChannelData(0); | 254 let n = audioBuffer.length; |
| 255 let dataL = audioBuffer.getChannelData(0); |
252 | 256 |
253 for (var i = 0; i < n; ++i) | 257 for (let i = 0; i < n; ++i) |
254 dataL[i] = i / n; | 258 dataL[i] = i / n; |
255 | 259 |
256 return audioBuffer; | 260 return audioBuffer; |
257 } | 261 } |
258 | 262 |
259 // Create an AudioBuffer of length |sampleFrameLength| having a constant value |
constantValue|. If | 263 // Create an AudioBuffer of length |sampleFrameLength| having a constant value |
260 // |constantValue| is a number, the buffer has one channel filled with that valu
e. If | 264 // |constantValue|. If |constantValue| is a number, the buffer has one channel |
261 // |constantValue| is an array, the buffer is created wit a number of channels e
qual to the length | 265 // filled with that value. If |constantValue| is an array, the buffer is created |
262 // of the array, and channel k is filled with the k'th element of the |constantV
alue| array. | 266 // wit a number of channels equal to the length of the array, and channel k is |
| 267 // filled with the k'th element of the |constantValue| array. |
263 function createConstantBuffer(context, sampleFrameLength, constantValue) { | 268 function createConstantBuffer(context, sampleFrameLength, constantValue) { |
264 var channels; | 269 let channels; |
265 var values; | 270 let values; |
266 | 271 |
267 if (typeof constantValue === "number") { | 272 if (typeof constantValue === 'number') { |
268 channels = 1; | 273 channels = 1; |
269 values = [constantValue]; | 274 values = [constantValue]; |
270 } else { | 275 } else { |
271 channels = constantValue.length; | 276 channels = constantValue.length; |
272 values = constantValue; | 277 values = constantValue; |
273 } | 278 } |
274 | 279 |
275 var audioBuffer = context.createBuffer(channels, sampleFrameLength, context.
sampleRate); | 280 let audioBuffer = |
276 var n = audioBuffer.length; | 281 context.createBuffer(channels, sampleFrameLength, context.sampleRate); |
| 282 let n = audioBuffer.length; |
277 | 283 |
278 for (var c = 0; c < channels; ++c) { | 284 for (let c = 0; c < channels; ++c) { |
279 var data = audioBuffer.getChannelData(c); | 285 let data = audioBuffer.getChannelData(c); |
280 for (var i = 0; i < n; ++i) | 286 for (let i = 0; i < n; ++i) |
281 data[i] = values[c]; | 287 data[i] = values[c]; |
282 } | 288 } |
283 | 289 |
284 return audioBuffer; | 290 return audioBuffer; |
285 } | 291 } |
286 | 292 |
287 // Create a stereo impulse in a buffer of length sampleFrameLength | 293 // Create a stereo impulse in a buffer of length sampleFrameLength |
288 function createStereoImpulseBuffer(context, sampleFrameLength) { | 294 function createStereoImpulseBuffer(context, sampleFrameLength) { |
289 var audioBuffer = context.createBuffer(2, sampleFrameLength, context.sampleR
ate); | 295 let audioBuffer = |
290 var n = audioBuffer.length; | 296 context.createBuffer(2, sampleFrameLength, context.sampleRate); |
291 var dataL = audioBuffer.getChannelData(0); | 297 let n = audioBuffer.length; |
292 var dataR = audioBuffer.getChannelData(1); | 298 let dataL = audioBuffer.getChannelData(0); |
| 299 let dataR = audioBuffer.getChannelData(1); |
293 | 300 |
294 for (var k = 0; k < n; ++k) { | 301 for (let k = 0; k < n; ++k) { |
295 dataL[k] = 0; | 302 dataL[k] = 0; |
296 dataR[k] = 0; | 303 dataR[k] = 0; |
297 } | 304 } |
298 dataL[0] = 1; | 305 dataL[0] = 1; |
299 dataR[0] = 1; | 306 dataR[0] = 1; |
300 | 307 |
301 return audioBuffer; | 308 return audioBuffer; |
302 } | 309 } |
303 | 310 |
304 // Convert time (in seconds) to sample frames. | 311 // Convert time (in seconds) to sample frames. |
305 function timeToSampleFrame(time, sampleRate) { | 312 function timeToSampleFrame(time, sampleRate) { |
306 return Math.floor(0.5 + time * sampleRate); | 313 return Math.floor(0.5 + time * sampleRate); |
307 } | 314 } |
308 | 315 |
309 // Compute the number of sample frames consumed by noteGrainOn with | 316 // Compute the number of sample frames consumed by noteGrainOn with |
310 // the specified |grainOffset|, |duration|, and |sampleRate|. | 317 // the specified |grainOffset|, |duration|, and |sampleRate|. |
311 function grainLengthInSampleFrames(grainOffset, duration, sampleRate) { | 318 function grainLengthInSampleFrames(grainOffset, duration, sampleRate) { |
312 var startFrame = timeToSampleFrame(grainOffset, sampleRate); | 319 let startFrame = timeToSampleFrame(grainOffset, sampleRate); |
313 var endFrame = timeToSampleFrame(grainOffset + duration, sampleRate); | 320 let endFrame = timeToSampleFrame(grainOffset + duration, sampleRate); |
314 | 321 |
315 return endFrame - startFrame; | 322 return endFrame - startFrame; |
316 } | 323 } |
317 | 324 |
318 // True if the number is not an infinity or NaN | 325 // True if the number is not an infinity or NaN |
319 function isValidNumber(x) { | 326 function isValidNumber(x) { |
320 return !isNaN(x) && (x != Infinity) && (x != -Infinity); | 327 return !isNaN(x) && (x != Infinity) && (x != -Infinity); |
321 } | 328 } |
322 | 329 |
323 // Compute the (linear) signal-to-noise ratio between |actual| and | 330 // Compute the (linear) signal-to-noise ratio between |actual| and |
324 // |expected|. The result is NOT in dB! If the |actual| and | 331 // |expected|. The result is NOT in dB! If the |actual| and |
325 // |expected| have different lengths, the shorter length is used. | 332 // |expected| have different lengths, the shorter length is used. |
326 function computeSNR(actual, expected) { | 333 function computeSNR(actual, expected) { |
327 var signalPower = 0; | 334 let signalPower = 0; |
328 var noisePower = 0; | 335 let noisePower = 0; |
329 | 336 |
330 var length = Math.min(actual.length, expected.length); | 337 let length = Math.min(actual.length, expected.length); |
331 | 338 |
332 for (var k = 0; k < length; ++k) { | 339 for (let k = 0; k < length; ++k) { |
333 var diff = actual[k] - expected[k]; | 340 let diff = actual[k] - expected[k]; |
334 signalPower += expected[k] * expected[k]; | 341 signalPower += expected[k] * expected[k]; |
335 noisePower += diff * diff; | 342 noisePower += diff * diff; |
336 } | 343 } |
337 | 344 |
338 return signalPower / noisePower; | 345 return signalPower / noisePower; |
339 } | 346 } |
OLD | NEW |