| OLD | NEW |
| (Empty) |
| 1 <!doctype html> | |
| 2 <html> | |
| 3 <head> | |
| 4 <title>Test Different PeriodicWave Lengths at Different Sample Rates</title> | |
| 5 <script src="../resources/js-test.js"></script> | |
| 6 <script src="resources/compatibility.js"></script> | |
| 7 <script src="resources/audit-util.js"></script> | |
| 8 <script src="resources/audio-testing.js"></script> | |
| 9 </head> | |
| 10 | |
| 11 <body> | |
| 12 <script> | |
| 13 description("Test Different PeriodicWave Lengths at Different Sample Rates
"); | |
| 14 window.jsTestIsAsync = true; | |
| 15 | |
| 16 // Test PeriodicWave objects with varying number of coefficients at differ
ent sample rates. | |
| 17 // Basically, verify that the coefficients are used at the appropriate sam
ple rates. This is | |
| 18 // done by comparing the outputs of two periodic waves used in oscillators
. The output should | |
| 19 // either be exactly zero or not depending on whether the coefficients wer
e used. | |
| 20 | |
| 21 var renderLength = 1; | |
| 22 var context; | |
| 23 | |
| 24 var audit = Audit.createTaskRunner(); | |
| 25 | |
| 26 // The set of Audit tests to be run to verify that PeriodicWave is using t
he correct number of | |
| 27 // coefficients. The name does not have to be unique; the index of the en
try is appended to | |
| 28 // the test. Every entry (except the last) needs sampleRate, bigWave, sma
llWave, and | |
| 29 // verifier values. | |
| 30 | |
| 31 var testSet = [ | |
| 32 // Tests for contexts at 192 kHz. | |
| 33 | |
| 34 // Test that we use more than 2048 Fourier coefficients at 192 kHz sampl
e rate. Basically | |
| 35 // verifies that 8192 is acceptable. | |
| 36 { | |
| 37 name: "192khz-test-1", | |
| 38 sampleRate: 192000, | |
| 39 bigWave: 8192, | |
| 40 smallWave: 2048, | |
| 41 verifier: resultShouldBeNonZero | |
| 42 }, | |
| 43 | |
| 44 // Test that we use at least 2049 Fourier coefficients at 192 kHz sample
rate. | |
| 45 { | |
| 46 name: "192khz-test-2", | |
| 47 sampleRate: 192000, | |
| 48 bigWave: 2049, | |
| 49 smallWave: 2048, | |
| 50 verifier: resultShouldBeNonZero | |
| 51 }, | |
| 52 | |
| 53 // Test that we use all 8192 Fourier coefficients at 192 kHz sample rate
. Ideally, we'd | |
| 54 // like to compare 8191 coefficients vs 8192 coefficients. However, due
to single-precision | |
| 55 // arithmetic, the wave forms are identical in this case. Thus, use a s
omewhat smaller | |
| 56 // value where the wave forms are actually different. | |
| 57 { | |
| 58 name: "192khz-test-3", | |
| 59 sampleRate: 192000, | |
| 60 bigWave: 8192, | |
| 61 smallWave: (8 - 1 / 256) * 1024, | |
| 62 verifier: resultShouldBeNonZero | |
| 63 }, | |
| 64 | |
| 65 // Tests for contexts at 48 kHz. | |
| 66 | |
| 67 // Test that we do not use more than 2048 Fourier coefficients at 48 kHz
. This depends on | |
| 68 // the internal implementation where, for backward compatibility and spe
ed, we only use 2048 | |
| 69 // coefficients at 48 kHz. (This is also true for rates below 88.2 kHz.
) Also tests that | |
| 70 // 8192 coefficients are allowed (but not all coefficients are used, of
course). | |
| 71 { | |
| 72 name: "48khz-test-1", | |
| 73 sampleRate: 48000, | |
| 74 bigWave: 8192, | |
| 75 smallWave: 2048, | |
| 76 verifier: resultShouldBeZero | |
| 77 }, | |
| 78 | |
| 79 // Test that we do not use more than 2048 Fourier coefficients. | |
| 80 { | |
| 81 name: "48khz-test-2", | |
| 82 sampleRate: 48000, | |
| 83 bigWave: 2049, | |
| 84 smallWave: 2048, | |
| 85 verifier: resultShouldBeZero | |
| 86 }, | |
| 87 | |
| 88 // It's not immediately clear with single-preicison arithmetic that we c
an distinguish | |
| 89 // between 2049 and 2048 coefficients, so do one more test with slightly
more coefficients. | |
| 90 { | |
| 91 name: "48khz-test-3", | |
| 92 sampleRate: 48000, | |
| 93 bigWave: (2 + 1 / 64) * 1024, | |
| 94 smallWave: 2048, | |
| 95 verifier: resultShouldBeZero | |
| 96 }, | |
| 97 | |
| 98 // Test that we use at least 2048 Fourier coefficients at 48 kHz. Ideal
ly we want to | |
| 99 // compare 2047 and 2048 coefficients, but single-precision arithmetic m
akes the resulting | |
| 100 // waveforms the same. Hence use a smaller value that produces differen
t waveforms. | |
| 101 { | |
| 102 name: "48khz-test-4", | |
| 103 sampleRate: 48000, | |
| 104 bigWave: 2048, | |
| 105 smallWave: 2046, | |
| 106 verifier: resultShouldBeNonZero | |
| 107 }, | |
| 108 | |
| 109 // Tests for contexts at 24 kHz. | |
| 110 | |
| 111 // Test that we do not use more than 1024 Fourier coefficients at 24 kHz
. | |
| 112 { | |
| 113 name: "24khz-test-1", | |
| 114 sampleRate: 24000, | |
| 115 bigWave: 8192, | |
| 116 smallWave: 1024, | |
| 117 verifier: resultShouldBeZero | |
| 118 }, | |
| 119 | |
| 120 // Test that we do not use more than 1024 Fourier coefficients at 24 kHz
. | |
| 121 { | |
| 122 name: "24khz-test-2", | |
| 123 sampleRate: 24000, | |
| 124 bigWave: 1025, | |
| 125 smallWave: 1024, | |
| 126 verifier: resultShouldBeZero | |
| 127 }, | |
| 128 | |
| 129 // Test that we use at least 1024 Fourier coefficients at 24 kHz. Again
, 1023 and 1024 | |
| 130 // produce the same waveforms in single-precisiion so use a smaller wave
table size. | |
| 131 { | |
| 132 name: "24khz-test-3", | |
| 133 sampleRate: 24000, | |
| 134 bigWave: 1024, | |
| 135 smallWave: 1022, | |
| 136 verifier: resultShouldBeNonZero | |
| 137 }, | |
| 138 ]; | |
| 139 | |
| 140 function generatePrefix (sampleRate, bigLength, smallLength) { | |
| 141 return "At " + (sampleRate / 1000) + " kHz, PeriodicWave with " | |
| 142 + bigLength + " coefficients vs " | |
| 143 + smallLength + ": "; | |
| 144 } | |
| 145 | |
| 146 // Returns a function the verifies that the result is zero. The parameter
s control what is | |
| 147 // printed in the messages. | |
| 148 function resultShouldBeZero(sampleRate, bigLength, smallLength) { | |
| 149 return function (buffer) { | |
| 150 var prefix = generatePrefix(sampleRate, bigLength, smallLength); | |
| 151 if (isBufferZero(buffer)) | |
| 152 testPassed(prefix + "identical as expected."); | |
| 153 else | |
| 154 testFailed(prefix + "unexpectedly differ."); | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 // Returns a function the verifies that the result is non-zero. The param
eters control what is | |
| 159 // printed in the messages. | |
| 160 function resultShouldBeNonZero(sampleRate, bigLength, smallLength) { | |
| 161 return function (buffer) { | |
| 162 var prefix = generatePrefix(sampleRate, bigLength, smallLength); | |
| 163 if (!isBufferZero(buffer)) | |
| 164 testPassed(prefix + "differ as expected."); | |
| 165 else | |
| 166 testFailed(prefix + "unexpectedly are identical."); | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 // Creates a function that is used to run an Audit test for a given sample
rate, periodic wave | |
| 171 // sizes, and verifier. | |
| 172 function createAuditTestFunction(sampleRate, bigLength, smallLength, verif
ier) { | |
| 173 return function (done) { | |
| 174 // Create the audio graph, render it, and then verify that the output
is the expected | |
| 175 // result. | |
| 176 createAudioGraph(sampleRate, bigLength, smallLength); | |
| 177 | |
| 178 context.startRendering() | |
| 179 .then(verifier(sampleRate, bigLength, smallLength)) | |
| 180 .then(done); | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 // Create the audio graph for the test. | |
| 185 function createAudioGraph(sampleRate, bigPeriodicWaveLength, smallPeriodic
WaveLength) { | |
| 186 context = new OfflineAudioContext(1, renderLength * sampleRate, sampleR
ate); | |
| 187 | |
| 188 // Two PeriodicWave objects are created with different sizes (small and
big). The contents | |
| 189 // are the same except that the samll sized PeriodicWave has fewer coef
ficients. | |
| 190 var smallWaveRealCoef = new Float32Array(smallPeriodicWaveLength); | |
| 191 var smallWaveImagCoef = new Float32Array(smallPeriodicWaveLength); | |
| 192 var bigWaveRealCoef = new Float32Array(bigPeriodicWaveLength); | |
| 193 var bigWaveImagCoef = new Float32Array(bigPeriodicWaveLength); | |
| 194 | |
| 195 // Set up the Fourier coefficients for a square wave. | |
| 196 for (var k = 0; k < bigPeriodicWaveLength; k += 2) { | |
| 197 bigWaveImagCoef[k] = 4 / Math.PI / k; | |
| 198 if (k < smallPeriodicWaveLength) | |
| 199 smallWaveImagCoef[k] = bigWaveImagCoef[k]; | |
| 200 } | |
| 201 | |
| 202 var smallPeriodicWave = context.createPeriodicWave(smallWaveRealCoef, s
mallWaveImagCoef); | |
| 203 var bigPeriodicWave = context.createPeriodicWave(bigWaveRealCoef, bigWa
veImagCoef); | |
| 204 | |
| 205 // Create oscillators using these PeriodicWave's. | |
| 206 var smallOscillator = context.createOscillator(); | |
| 207 var bigOscillator = context.createOscillator(); | |
| 208 | |
| 209 smallOscillator.setPeriodicWave(smallPeriodicWave); | |
| 210 bigOscillator.setPeriodicWave(bigPeriodicWave); | |
| 211 | |
| 212 // Use a frequency of 1 Hz to make the distinction easier. Can't tell
from this test, but | |
| 213 // if you plot the signals from these oscillators, it's very clear that
they are different. | |
| 214 smallOscillator.frequency.value = 1; | |
| 215 bigOscillator.frequency.value = 1; | |
| 216 | |
| 217 // The desired output is the difference between these oscillators. | |
| 218 var gain = context.createGain(); | |
| 219 gain.gain.value = -1; | |
| 220 smallOscillator.connect(gain); | |
| 221 | |
| 222 gain.connect(context.destination); | |
| 223 bigOscillator.connect(context.destination); | |
| 224 | |
| 225 // Start the oscillators. | |
| 226 smallOscillator.start(); | |
| 227 bigOscillator.start(); | |
| 228 } | |
| 229 | |
| 230 // Return true if the buffer is exactly zero. | |
| 231 function isBufferZero(buffer) { | |
| 232 if (buffer.getChannelData(0).find(function (x) { return x != 0; })) | |
| 233 return false; | |
| 234 return true; | |
| 235 } | |
| 236 | |
| 237 // Ensure the actual Audit test name is unique by prepending an index to t
he provided test | |
| 238 // name. | |
| 239 function actualTestName(name, index) { | |
| 240 return index + ":" + name; | |
| 241 } | |
| 242 | |
| 243 // Define the tasks based on the entries in testSet. | |
| 244 function defineAuditTests () { | |
| 245 for (var k = 0; k < testSet.length; ++k) { | |
| 246 var test = testSet[k]; | |
| 247 var actualName = actualTestName(test.name, k); | |
| 248 audit.defineTask(actualName, | |
| 249 createAuditTestFunction(test.sampleRate, test.bigWave, test.smallWav
e, test.verifier)); | |
| 250 } | |
| 251 // Define the finish test last. | |
| 252 audit.defineTask(actualTestName("finish-tests", testSet.length), functio
n (done) { | |
| 253 finishJSTest(); | |
| 254 done(); | |
| 255 }); | |
| 256 } | |
| 257 | |
| 258 defineAuditTests(); | |
| 259 audit.runTasks(); | |
| 260 | |
| 261 successfullyParsed = true; | |
| 262 </script> | |
| 263 </body> | |
| 264 </html> | |
| OLD | NEW |