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