Chromium Code Reviews| 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 {name : "192khz-test-1", sampleRate : 192000, bigWave : 8192, smallWave : 2048, verifier : resultShouldBeNonZero}, | |
|
hongchan
2015/07/22 21:01:19
nit: JSON style. A space after/before the curly br
Raymond Toy
2015/07/23 15:33:09
Done.
| |
| 36 | |
| 37 // Test that we use at least 2049 Fourier coefficients at 192 kHz sample rate. | |
| 38 {name : "192khz-test-2", sampleRate : 192000, bigWave : 2049, smallWave : 2048, verifier : resultShouldBeNonZero}, | |
| 39 | |
| 40 // Test that we use all 8192 Fourier coefficients at 192 kHz sample rate . Ideally, we'd | |
| 41 // like to compare 8191 coefficients vs 8192 coefficients. However, due to single-precision | |
| 42 // arithmetic, the wave forms are identical in this case. Thus, use a s omewhat smaller | |
| 43 // value where the wave forms are actually different. | |
| 44 {name : "192khz-test-3", sampleRate : 192000, bigWave : 8192, smallWave : (8 - 1/256) * 1024, verifier : resultShouldBeNonZero}, | |
| 45 | |
| 46 // Tests for contexts at 48 kHz. | |
| 47 | |
| 48 // Test that we do not use more than 2048 Fourier coefficients at 48 kHz . This depends on | |
| 49 // the internal implementation where, for backward compatibility and spe ed, we only use 2048 | |
| 50 // coefficients at 48 kHz. (This is also true for rates below 88.2 kHz. ) Also tests that | |
| 51 // 8192 coefficients are allowed (but not all coefficients are used, of course). | |
| 52 {name : "48khz-test-1", sampleRate : 48000, bigWave : 8192, smallWave : 2048, verifier : resultShouldBeZero}, | |
| 53 | |
| 54 // Test that we do not use more than 2048 Fourier coefficients. | |
| 55 {name : "48khz-test-2", sampleRate : 48000, bigWave : 2049, smallWave : 2048, verifier : resultShouldBeZero}, | |
| 56 | |
| 57 // It's not immediately clear with single-preicison arithmetic that we c an distinguish | |
| 58 // between 2049 and 2048 coefficients, so do one more test with slightly more coefficients. | |
| 59 {name : "48khz-test-3", sampleRate : 48000, bigWave : (2 + 1/64) * 1024, smallWave : 2048, verifier : resultShouldBeZero}, | |
| 60 | |
| 61 // Test that we use at least 2048 Fourier coefficients at 48 kHz. Ideal ly we want to | |
| 62 // compare 2047 and 2048 coefficients, but single-precision arithmetic m akes the resulting | |
| 63 // waveforms the same. Hence use a smaller value that produces differen t waveforms. | |
| 64 {name : "48khz-test-4", sampleRate : 48000, bigWave : 2048, smallWave : 2046, verifier : resultShouldBeNonZero}, | |
| 65 | |
| 66 // Tests for contexts at 24 kHz. | |
| 67 | |
| 68 // Test that we do not use more than 1024 Fourier coefficients at 24 kHz . | |
| 69 {name : "24khz-test-1", sampleRate : 24000, bigWave : 8192, smallWave : 1024, verifier : resultShouldBeZero}, | |
| 70 | |
| 71 // Test that we do not use more than 1024 Fourier coefficients at 24 kHz . | |
| 72 {name : "24khz-test-2", sampleRate : 24000, bigWave : 1025, smallWave : 1024, verifier : resultShouldBeZero}, | |
| 73 | |
| 74 // Test that we use at least 1024 Fourier coefficients at 24 kHz. Again , 1023 and 1024 | |
| 75 // produce the same waveforms in single-precisiion so use a smaller wave table size. | |
| 76 {name : "24khz-test-3", sampleRate : 24000, bigWave : 1024, smallWave : 1022, verifier : resultShouldBeNonZero}, | |
| 77 ]; | |
| 78 | |
| 79 function prefixMessage (sampleRate, bigLength, smallLength) { | |
|
hongchan
2015/07/22 21:01:19
optional nit: Doesn't look like it's prefixing the
Raymond Toy
2015/07/23 15:33:09
Renamed to generatePrefix.
| |
| 80 return "At " + (sampleRate / 1000) + " kHz, PeriodicWave with " | |
| 81 + bigLength + " coefficients vs " | |
| 82 + smallLength + ": "; | |
| 83 } | |
| 84 | |
| 85 // Returns a function the verifies that the result is zero. The parameter s control what is | |
| 86 // printed in the messages. | |
| 87 function resultShouldBeZero(sampleRate, bigLength, smallLength) { | |
|
hongchan
2015/07/22 21:01:19
I am pretty sure you've already explored the optio
Raymond Toy
2015/07/22 22:17:48
I initially used Should.beConstantValueOf in resul
hongchan
2015/07/22 22:30:32
Yes, I agree this is good enough for now. However,
| |
| 88 return function (buffer) { | |
| 89 var prefix = prefixMessage(sampleRate, bigLength, smallLength); | |
| 90 if (isBufferZero(buffer)) | |
| 91 testPassed(prefix + "identical as expected."); | |
| 92 else | |
| 93 testFailed(prefix + "unexpectedly differ."); | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 // Returns a function the verifies that the result is non-zero. The param eters control what is | |
| 98 // printed in the messages. | |
| 99 function resultShouldBeNonZero(sampleRate, bigLength, smallLength) { | |
| 100 return function (buffer) { | |
| 101 var prefix = prefixMessage(sampleRate, bigLength, smallLength); | |
| 102 if (!isBufferZero(buffer)) | |
| 103 testPassed(prefix + "differ as expected."); | |
| 104 else | |
| 105 testFailed(prefix + "unexpectedly are identical."); | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 // Creates a function that is used to run an Audit test for a given sample rate, periodic wave | |
| 110 // sizes, and verifier. | |
| 111 function createAuditTestFunction(sampleRate, bigLength, smallLength, verif ier) { | |
| 112 return function (done) { | |
| 113 // Create the audio graph, render it, and then verify that the output is the expected | |
| 114 // result. | |
| 115 createAudioGraph(sampleRate, bigLength, smallLength); | |
| 116 | |
| 117 context.startRendering() | |
| 118 .then(verifier(sampleRate, bigLength, smallLength)) | |
| 119 .then(done); | |
| 120 } | |
| 121 } | |
| 122 | |
| 123 // Create the audio graph for the test. | |
| 124 function createAudioGraph(sampleRate, bigPeriodicWaveLength, smallPeriodic WaveLength) { | |
| 125 context = new OfflineAudioContext(1, renderLength * sampleRate, sampleR ate); | |
| 126 | |
| 127 // Two PeriodicWave objects are created with different sizes (small and big). The contents | |
| 128 // are the same except that the samll sized PeriodicWave has fewer coef ficients. | |
| 129 var smallWaveRealCoef = new Float32Array(smallPeriodicWaveLength); | |
| 130 var smallWaveImagCoef = new Float32Array(smallPeriodicWaveLength); | |
| 131 var bigWaveRealCoef = new Float32Array(bigPeriodicWaveLength); | |
| 132 var bigWaveImagCoef = new Float32Array(bigPeriodicWaveLength); | |
| 133 | |
| 134 // Set up the Fourier coefficients for a square wave. | |
| 135 for (var k = 0; k < bigPeriodicWaveLength; k += 2) { | |
| 136 bigWaveImagCoef[k] = 4 / Math.PI / k; | |
| 137 if (k < smallPeriodicWaveLength) | |
| 138 smallWaveImagCoef[k] = bigWaveImagCoef[k]; | |
| 139 } | |
| 140 | |
| 141 var smallPeriodicWave = context.createPeriodicWave(smallWaveRealCoef, s mallWaveImagCoef); | |
| 142 var bigPeriodicWave = context.createPeriodicWave(bigWaveRealCoef, bigWa veImagCoef); | |
| 143 | |
| 144 // Create oscillators using these PeriodicWave's. | |
| 145 var smallOscillator = context.createOscillator(); | |
| 146 var bigOscillator = context.createOscillator(); | |
| 147 | |
| 148 smallOscillator.setPeriodicWave(smallPeriodicWave); | |
| 149 bigOscillator.setPeriodicWave(bigPeriodicWave); | |
| 150 | |
| 151 // Use a frequency of 1 Hz to make the distinction easier. Can't tell from this test, but | |
| 152 // if you plot the signals from these oscillators, it's very clear that they are different. | |
| 153 smallOscillator.frequency.value = 1; | |
| 154 bigOscillator.frequency.value = 1; | |
| 155 | |
| 156 // The desired output is the difference between these oscillators. | |
| 157 var gain = context.createGain(); | |
| 158 gain.gain.value = -1; | |
| 159 smallOscillator.connect(gain); | |
| 160 | |
| 161 gain.connect(context.destination); | |
| 162 bigOscillator.connect(context.destination); | |
| 163 | |
| 164 // Start the oscillators. | |
| 165 smallOscillator.start(); | |
| 166 bigOscillator.start(); | |
| 167 } | |
| 168 | |
| 169 // Return true if the buffer is exactly zero. | |
| 170 function isBufferZero(buffer) { | |
|
hongchan
2015/07/22 21:01:19
This is identical to:
Should('myChannelData', f32a
Raymond Toy
2015/07/22 22:17:48
Exactly. In some cases all zeros is right but in o
hongchan
2015/07/22 22:30:32
Acknowledged.
| |
| 171 if (buffer.getChannelData(0).find(function (x) { return x != 0; })) | |
| 172 return false; | |
| 173 return true; | |
| 174 } | |
| 175 | |
| 176 // Ensure the actual Audit test name is unique by prepending an index to t he provided test | |
| 177 // name. | |
| 178 function actualTestName(name, index) { | |
| 179 return index + ":" + name; | |
| 180 } | |
| 181 | |
| 182 // Define the tasks based on the entries in testSet. | |
| 183 function defineAuditTests () { | |
| 184 for (var k = 0; k < testSet.length; ++k) { | |
| 185 var test = testSet[k]; | |
| 186 var actualName = actualTestName(test.name, k); | |
| 187 audit.defineTask(actualName, | |
| 188 createAuditTestFunction(test.sampleRate, test.bigWave, test.smallWav e, test.verifier)); | |
| 189 } | |
| 190 // Define the finish test last. | |
| 191 audit.defineTask(actualTestName("finish-tests", testSet.length), functio n (done) { | |
| 192 finishJSTest(); | |
| 193 done(); | |
| 194 }); | |
| 195 } | |
| 196 | |
| 197 // Run all of the tests defined in testSet. | |
| 198 function runAuditTests() { | |
| 199 var tests = testSet.map(function (value, index) { | |
| 200 return actualTestName(value.name, index); | |
| 201 }).concat(actualTestName("finish-tests", testSet.length)); | |
| 202 audit.runTasks.apply(audit, tests); | |
| 203 }; | |
| 204 | |
| 205 defineAuditTests(); | |
| 206 runAuditTests(); | |
| 207 | |
| 208 successfullyParsed = true; | |
| 209 </script> | |
| 210 </body> | |
| 211 </html> | |
| OLD | NEW |