| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 |
| 6 /** |
| 7 * @fileOverview This file includes legacy utility functions for the layout |
| 8 * test. |
| 9 */ |
| 10 |
| 11 |
| 12 function writeString(s, a, offset) { |
| 13 for (var i = 0; i < s.length; ++i) { |
| 14 a[offset + i] = s.charCodeAt(i); |
| 15 } |
| 16 } |
| 17 |
| 18 function writeInt16(n, a, offset) { |
| 19 n = Math.floor(n); |
| 20 |
| 21 var b1 = n & 255; |
| 22 var b2 = (n >> 8) & 255; |
| 23 |
| 24 a[offset + 0] = b1; |
| 25 a[offset + 1] = b2; |
| 26 } |
| 27 |
| 28 function writeInt32(n, a, offset) { |
| 29 n = Math.floor(n); |
| 30 var b1 = n & 255; |
| 31 var b2 = (n >> 8) & 255; |
| 32 var b3 = (n >> 16) & 255; |
| 33 var b4 = (n >> 24) & 255; |
| 34 |
| 35 a[offset + 0] = b1; |
| 36 a[offset + 1] = b2; |
| 37 a[offset + 2] = b3; |
| 38 a[offset + 3] = b4; |
| 39 } |
| 40 |
| 41 function writeAudioBuffer(audioBuffer, a, offset) { |
| 42 var n = audioBuffer.length; |
| 43 var channels = audioBuffer.numberOfChannels; |
| 44 |
| 45 for (var i = 0; i < n; ++i) { |
| 46 for (var k = 0; k < channels; ++k) { |
| 47 var buffer = audioBuffer.getChannelData(k); |
| 48 var sample = buffer[i] * 32768.0; |
| 49 |
| 50 // Clip samples to the limitations of 16-bit. |
| 51 // If we don't do this then we'll get nasty wrap-around distortion. |
| 52 if (sample < -32768) |
| 53 sample = -32768; |
| 54 if (sample > 32767) |
| 55 sample = 32767; |
| 56 |
| 57 writeInt16(sample, a, offset); |
| 58 offset += 2; |
| 59 } |
| 60 } |
| 61 } |
| 62 |
| 63 function createWaveFileData(audioBuffer) { |
| 64 var frameLength = audioBuffer.length; |
| 65 var numberOfChannels = audioBuffer.numberOfChannels; |
| 66 var sampleRate = audioBuffer.sampleRate; |
| 67 var bitsPerSample = 16; |
| 68 var byteRate = sampleRate * numberOfChannels * bitsPerSample/8; |
| 69 var blockAlign = numberOfChannels * bitsPerSample/8; |
| 70 var wavDataByteLength = frameLength * numberOfChannels * 2; // 16-bit audio |
| 71 var headerByteLength = 44; |
| 72 var totalLength = headerByteLength + wavDataByteLength; |
| 73 |
| 74 var waveFileData = new Uint8Array(totalLength); |
| 75 |
| 76 var subChunk1Size = 16; // for linear PCM |
| 77 var subChunk2Size = wavDataByteLength; |
| 78 var chunkSize = 4 + (8 + subChunk1Size) + (8 + subChunk2Size); |
| 79 |
| 80 writeString("RIFF", waveFileData, 0); |
| 81 writeInt32(chunkSize, waveFileData, 4); |
| 82 writeString("WAVE", waveFileData, 8); |
| 83 writeString("fmt ", waveFileData, 12); |
| 84 |
| 85 writeInt32(subChunk1Size, waveFileData, 16); // SubChunk1Size (4) |
| 86 writeInt16(1, waveFileData, 20); // AudioFormat (2) |
| 87 writeInt16(numberOfChannels, waveFileData, 22); // NumChannels (2) |
| 88 writeInt32(sampleRate, waveFileData, 24); // SampleRate (4) |
| 89 writeInt32(byteRate, waveFileData, 28); // ByteRate (4) |
| 90 writeInt16(blockAlign, waveFileData, 32); // BlockAlign (2) |
| 91 writeInt32(bitsPerSample, waveFileData, 34); // BitsPerSample (4) |
| 92 |
| 93 writeString("data", waveFileData, 36); |
| 94 writeInt32(subChunk2Size, waveFileData, 40); // SubChunk2Size (4) |
| 95 |
| 96 // Write actual audio data starting at offset 44. |
| 97 writeAudioBuffer(audioBuffer, waveFileData, 44); |
| 98 |
| 99 return waveFileData; |
| 100 } |
| 101 |
| 102 function createAudioData(audioBuffer) { |
| 103 return createWaveFileData(audioBuffer); |
| 104 } |
| 105 |
| 106 function finishAudioTest(event) { |
| 107 var audioData = createAudioData(event.renderedBuffer); |
| 108 testRunner.setAudioData(audioData); |
| 109 testRunner.notifyDone(); |
| 110 } |
| 111 |
| 112 // Compare two arrays (commonly extracted from buffer.getChannelData()) with |
| 113 // constraints: |
| 114 // options.thresholdSNR: Minimum allowed SNR between the actual and expected |
| 115 // signal. The default value is 10000. |
| 116 // options.thresholdDiffULP: Maximum allowed difference between the actual |
| 117 // and expected signal in ULP(Unit in the last place). The default is 0. |
| 118 // options.thresholdDiffCount: Maximum allowed number of sample differences |
| 119 // which exceeds the threshold. The default is 0. |
| 120 // options.bitDepth: The expected result is assumed to come from an audio |
| 121 // file with this number of bits of precision. The default is 16. |
| 122 function compareBuffersWithConstraints(actual, expected, options) { |
| 123 if (!options) |
| 124 options = {}; |
| 125 |
| 126 if (actual.length !== expected.length) |
| 127 testFailed('Buffer length mismatches.'); |
| 128 |
| 129 var maxError = -1; |
| 130 var diffCount = 0; |
| 131 var errorPosition = -1; |
| 132 var thresholdSNR = (options.thresholdSNR || 10000); |
| 133 |
| 134 var thresholdDiffULP = (options.thresholdDiffULP || 0); |
| 135 var thresholdDiffCount = (options.thresholdDiffCount || 0); |
| 136 |
| 137 // By default, the bit depth is 16. |
| 138 var bitDepth = (options.bitDepth || 16); |
| 139 var scaleFactor = Math.pow(2, bitDepth - 1); |
| 140 |
| 141 var noisePower = 0, signalPower = 0; |
| 142 |
| 143 for (var i = 0; i < actual.length; i++) { |
| 144 var diff = actual[i] - expected[i]; |
| 145 noisePower += diff * diff; |
| 146 signalPower += expected[i] * expected[i]; |
| 147 |
| 148 if (Math.abs(diff) > maxError) { |
| 149 maxError = Math.abs(diff); |
| 150 errorPosition = i; |
| 151 } |
| 152 |
| 153 // The reference file is a 16-bit WAV file, so we will almost never get |
| 154 // an exact match between it and the actual floating-point result. |
| 155 if (Math.abs(diff) > scaleFactor) |
| 156 diffCount++; |
| 157 } |
| 158 |
| 159 var snr = 10 * Math.log10(signalPower / noisePower); |
| 160 var maxErrorULP = maxError * scaleFactor; |
| 161 |
| 162 if (snr >= thresholdSNR) { |
| 163 testPassed('Exceeded SNR threshold of ' + thresholdSNR + ' dB.'); |
| 164 } else { |
| 165 testFailed('Expected SNR of ' + thresholdSNR + ' dB, but actual SNR is '
+ |
| 166 snr + ' dB.'); |
| 167 } |
| 168 |
| 169 if (maxErrorULP <= thresholdDiffULP) { |
| 170 testPassed('Maximum difference below threshold of ' + |
| 171 thresholdDiffULP + ' ulp (' + bitDepth + '-bits).'); |
| 172 } else { |
| 173 testFailed('Maximum difference of ' + maxErrorULP + |
| 174 ' at the index ' + errorPosition + ' exceeded threshold of ' + |
| 175 thresholdDiffULP + ' ulp (' + bitDepth + '-bits).'); |
| 176 } |
| 177 |
| 178 if (diffCount <= thresholdDiffCount) { |
| 179 testPassed('Number of differences between results is ' + |
| 180 diffCount + ' out of ' + actual.length + '.'); |
| 181 } else { |
| 182 testFailed(diffCount + ' differences found but expected no more than ' + |
| 183 diffCount + ' out of ' + actual.length + '.'); |
| 184 } |
| 185 } |
| 186 |
| 187 // Create an impulse in a buffer of length sampleFrameLength |
| 188 function createImpulseBuffer(context, sampleFrameLength) { |
| 189 var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleR
ate); |
| 190 var n = audioBuffer.length; |
| 191 var dataL = audioBuffer.getChannelData(0); |
| 192 |
| 193 for (var k = 0; k < n; ++k) { |
| 194 dataL[k] = 0; |
| 195 } |
| 196 dataL[0] = 1; |
| 197 |
| 198 return audioBuffer; |
| 199 } |
| 200 |
| 201 // Create a buffer of the given length with a linear ramp having values 0 <= x <
1. |
| 202 function createLinearRampBuffer(context, sampleFrameLength) { |
| 203 var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleR
ate); |
| 204 var n = audioBuffer.length; |
| 205 var dataL = audioBuffer.getChannelData(0); |
| 206 |
| 207 for (var i = 0; i < n; ++i) |
| 208 dataL[i] = i / n; |
| 209 |
| 210 return audioBuffer; |
| 211 } |
| 212 |
| 213 // Create an AudioBuffer of length |sampleFrameLength| having a constant value |
constantValue|. If |
| 214 // |constantValue| is a number, the buffer has one channel filled with that valu
e. If |
| 215 // |constantValue| is an array, the buffer is created wit a number of channels e
qual to the length |
| 216 // of the array, and channel k is filled with the k'th element of the |constantV
alue| array. |
| 217 function createConstantBuffer(context, sampleFrameLength, constantValue) { |
| 218 var channels; |
| 219 var values; |
| 220 |
| 221 if (typeof constantValue === "number") { |
| 222 channels = 1; |
| 223 values = [constantValue]; |
| 224 } else { |
| 225 channels = constantValue.length; |
| 226 values = constantValue; |
| 227 } |
| 228 |
| 229 var audioBuffer = context.createBuffer(channels, sampleFrameLength, context.
sampleRate); |
| 230 var n = audioBuffer.length; |
| 231 |
| 232 for (var c = 0; c < channels; ++c) { |
| 233 var data = audioBuffer.getChannelData(c); |
| 234 for (var i = 0; i < n; ++i) |
| 235 data[i] = values[c]; |
| 236 } |
| 237 |
| 238 return audioBuffer; |
| 239 } |
| 240 |
| 241 // Create a stereo impulse in a buffer of length sampleFrameLength |
| 242 function createStereoImpulseBuffer(context, sampleFrameLength) { |
| 243 var audioBuffer = context.createBuffer(2, sampleFrameLength, context.sampleR
ate); |
| 244 var n = audioBuffer.length; |
| 245 var dataL = audioBuffer.getChannelData(0); |
| 246 var dataR = audioBuffer.getChannelData(1); |
| 247 |
| 248 for (var k = 0; k < n; ++k) { |
| 249 dataL[k] = 0; |
| 250 dataR[k] = 0; |
| 251 } |
| 252 dataL[0] = 1; |
| 253 dataR[0] = 1; |
| 254 |
| 255 return audioBuffer; |
| 256 } |
| 257 |
| 258 // Convert time (in seconds) to sample frames. |
| 259 function timeToSampleFrame(time, sampleRate) { |
| 260 return Math.floor(0.5 + time * sampleRate); |
| 261 } |
| 262 |
| 263 // Compute the number of sample frames consumed by noteGrainOn with |
| 264 // the specified |grainOffset|, |duration|, and |sampleRate|. |
| 265 function grainLengthInSampleFrames(grainOffset, duration, sampleRate) { |
| 266 var startFrame = timeToSampleFrame(grainOffset, sampleRate); |
| 267 var endFrame = timeToSampleFrame(grainOffset + duration, sampleRate); |
| 268 |
| 269 return endFrame - startFrame; |
| 270 } |
| 271 |
| 272 // True if the number is not an infinity or NaN |
| 273 function isValidNumber(x) { |
| 274 return !isNaN(x) && (x != Infinity) && (x != -Infinity); |
| 275 } |
| OLD | NEW |