Chromium Code Reviews| Index: LayoutTests/webaudio/periodicwave-lengths.html |
| diff --git a/LayoutTests/webaudio/periodicwave-lengths.html b/LayoutTests/webaudio/periodicwave-lengths.html |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ab97131b9b1338dbf736a66bb61dac81c97b9b0d |
| --- /dev/null |
| +++ b/LayoutTests/webaudio/periodicwave-lengths.html |
| @@ -0,0 +1,211 @@ |
| +<!doctype html> |
| +<html> |
| + <head> |
| + <title>Test Different PeriodicWave Lengths at Different Sample Rates</title> |
| + <script src="../resources/js-test.js"></script> |
| + <script src="resources/compatibility.js"></script> |
| + <script src="resources/audio-testing.js"></script> |
| + </head> |
| + |
| + <body> |
| + <script> |
| + description("Test Different PeriodicWave Lengths at Different Sample Rates"); |
| + window.jsTestIsAsync = true; |
| + |
| + // Test PeriodicWave objects with varying number of coefficients at different sample rates. |
| + // Basically, verify that the coefficients are used at the appropriate sample rates. This is |
| + // done by comparing the outputs of two periodic waves used in oscillators. The output should |
| + // either be exactly zero or not depending on whether the coefficients were used. |
| + |
| + var renderLength = 1; |
| + var context; |
| + |
| + var audit = Audit.createTaskRunner(); |
| + |
| + // The set of Audit tests to be run to verify that PeriodicWave is using the correct number of |
| + // coefficients. The name does not have to be unique; the index of the entry is appended to |
| + // the test. Every entry (except the last) needs sampleRate, bigWave, smallWave, and |
| + // verifier values. |
| + |
| + var testSet = [ |
| + // Tests for contexts at 192 kHz. |
| + |
| + // Test that we use more than 2048 Fourier coefficients at 192 kHz sample rate. Basically |
| + // verifies that 8192 is acceptable. |
| + {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.
|
| + |
| + // Test that we use at least 2049 Fourier coefficients at 192 kHz sample rate. |
| + {name : "192khz-test-2", sampleRate : 192000, bigWave : 2049, smallWave : 2048, verifier : resultShouldBeNonZero}, |
| + |
| + // Test that we use all 8192 Fourier coefficients at 192 kHz sample rate. Ideally, we'd |
| + // like to compare 8191 coefficients vs 8192 coefficients. However, due to single-precision |
| + // arithmetic, the wave forms are identical in this case. Thus, use a somewhat smaller |
| + // value where the wave forms are actually different. |
| + {name : "192khz-test-3", sampleRate : 192000, bigWave : 8192, smallWave : (8 - 1/256) * 1024, verifier : resultShouldBeNonZero}, |
| + |
| + // Tests for contexts at 48 kHz. |
| + |
| + // Test that we do not use more than 2048 Fourier coefficients at 48 kHz. This depends on |
| + // the internal implementation where, for backward compatibility and speed, we only use 2048 |
| + // coefficients at 48 kHz. (This is also true for rates below 88.2 kHz.) Also tests that |
| + // 8192 coefficients are allowed (but not all coefficients are used, of course). |
| + {name : "48khz-test-1", sampleRate : 48000, bigWave : 8192, smallWave : 2048, verifier : resultShouldBeZero}, |
| + |
| + // Test that we do not use more than 2048 Fourier coefficients. |
| + {name : "48khz-test-2", sampleRate : 48000, bigWave : 2049, smallWave : 2048, verifier : resultShouldBeZero}, |
| + |
| + // It's not immediately clear with single-preicison arithmetic that we can distinguish |
| + // between 2049 and 2048 coefficients, so do one more test with slightly more coefficients. |
| + {name : "48khz-test-3", sampleRate : 48000, bigWave : (2 + 1/64) * 1024, smallWave : 2048, verifier : resultShouldBeZero}, |
| + |
| + // Test that we use at least 2048 Fourier coefficients at 48 kHz. Ideally we want to |
| + // compare 2047 and 2048 coefficients, but single-precision arithmetic makes the resulting |
| + // waveforms the same. Hence use a smaller value that produces different waveforms. |
| + {name : "48khz-test-4", sampleRate : 48000, bigWave : 2048, smallWave : 2046, verifier : resultShouldBeNonZero}, |
| + |
| + // Tests for contexts at 24 kHz. |
| + |
| + // Test that we do not use more than 1024 Fourier coefficients at 24 kHz. |
| + {name : "24khz-test-1", sampleRate : 24000, bigWave : 8192, smallWave : 1024, verifier : resultShouldBeZero}, |
| + |
| + // Test that we do not use more than 1024 Fourier coefficients at 24 kHz. |
| + {name : "24khz-test-2", sampleRate : 24000, bigWave : 1025, smallWave : 1024, verifier : resultShouldBeZero}, |
| + |
| + // Test that we use at least 1024 Fourier coefficients at 24 kHz. Again, 1023 and 1024 |
| + // produce the same waveforms in single-precisiion so use a smaller wave table size. |
| + {name : "24khz-test-3", sampleRate : 24000, bigWave : 1024, smallWave : 1022, verifier : resultShouldBeNonZero}, |
| + ]; |
| + |
| + 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.
|
| + return "At " + (sampleRate / 1000) + " kHz, PeriodicWave with " |
| + + bigLength + " coefficients vs " |
| + + smallLength + ": "; |
| + } |
| + |
| + // Returns a function the verifies that the result is zero. The parameters control what is |
| + // printed in the messages. |
| + 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,
|
| + return function (buffer) { |
| + var prefix = prefixMessage(sampleRate, bigLength, smallLength); |
| + if (isBufferZero(buffer)) |
| + testPassed(prefix + "identical as expected."); |
| + else |
| + testFailed(prefix + "unexpectedly differ."); |
| + } |
| + } |
| + |
| + // Returns a function the verifies that the result is non-zero. The parameters control what is |
| + // printed in the messages. |
| + function resultShouldBeNonZero(sampleRate, bigLength, smallLength) { |
| + return function (buffer) { |
| + var prefix = prefixMessage(sampleRate, bigLength, smallLength); |
| + if (!isBufferZero(buffer)) |
| + testPassed(prefix + "differ as expected."); |
| + else |
| + testFailed(prefix + "unexpectedly are identical."); |
| + } |
| + } |
| + |
| + // Creates a function that is used to run an Audit test for a given sample rate, periodic wave |
| + // sizes, and verifier. |
| + function createAuditTestFunction(sampleRate, bigLength, smallLength, verifier) { |
| + return function (done) { |
| + // Create the audio graph, render it, and then verify that the output is the expected |
| + // result. |
| + createAudioGraph(sampleRate, bigLength, smallLength); |
| + |
| + context.startRendering() |
| + .then(verifier(sampleRate, bigLength, smallLength)) |
| + .then(done); |
| + } |
| + } |
| + |
| + // Create the audio graph for the test. |
| + function createAudioGraph(sampleRate, bigPeriodicWaveLength, smallPeriodicWaveLength) { |
| + context = new OfflineAudioContext(1, renderLength * sampleRate, sampleRate); |
| + |
| + // Two PeriodicWave objects are created with different sizes (small and big). The contents |
| + // are the same except that the samll sized PeriodicWave has fewer coefficients. |
| + var smallWaveRealCoef = new Float32Array(smallPeriodicWaveLength); |
| + var smallWaveImagCoef = new Float32Array(smallPeriodicWaveLength); |
| + var bigWaveRealCoef = new Float32Array(bigPeriodicWaveLength); |
| + var bigWaveImagCoef = new Float32Array(bigPeriodicWaveLength); |
| + |
| + // Set up the Fourier coefficients for a square wave. |
| + for (var k = 0; k < bigPeriodicWaveLength; k += 2) { |
| + bigWaveImagCoef[k] = 4 / Math.PI / k; |
| + if (k < smallPeriodicWaveLength) |
| + smallWaveImagCoef[k] = bigWaveImagCoef[k]; |
| + } |
| + |
| + var smallPeriodicWave = context.createPeriodicWave(smallWaveRealCoef, smallWaveImagCoef); |
| + var bigPeriodicWave = context.createPeriodicWave(bigWaveRealCoef, bigWaveImagCoef); |
| + |
| + // Create oscillators using these PeriodicWave's. |
| + var smallOscillator = context.createOscillator(); |
| + var bigOscillator = context.createOscillator(); |
| + |
| + smallOscillator.setPeriodicWave(smallPeriodicWave); |
| + bigOscillator.setPeriodicWave(bigPeriodicWave); |
| + |
| + // Use a frequency of 1 Hz to make the distinction easier. Can't tell from this test, but |
| + // if you plot the signals from these oscillators, it's very clear that they are different. |
| + smallOscillator.frequency.value = 1; |
| + bigOscillator.frequency.value = 1; |
| + |
| + // The desired output is the difference between these oscillators. |
| + var gain = context.createGain(); |
| + gain.gain.value = -1; |
| + smallOscillator.connect(gain); |
| + |
| + gain.connect(context.destination); |
| + bigOscillator.connect(context.destination); |
| + |
| + // Start the oscillators. |
| + smallOscillator.start(); |
| + bigOscillator.start(); |
| + } |
| + |
| + // Return true if the buffer is exactly zero. |
| + 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.
|
| + if (buffer.getChannelData(0).find(function (x) { return x != 0; })) |
| + return false; |
| + return true; |
| + } |
| + |
| + // Ensure the actual Audit test name is unique by prepending an index to the provided test |
| + // name. |
| + function actualTestName(name, index) { |
| + return index + ":" + name; |
| + } |
| + |
| + // Define the tasks based on the entries in testSet. |
| + function defineAuditTests () { |
| + for (var k = 0; k < testSet.length; ++k) { |
| + var test = testSet[k]; |
| + var actualName = actualTestName(test.name, k); |
| + audit.defineTask(actualName, |
| + createAuditTestFunction(test.sampleRate, test.bigWave, test.smallWave, test.verifier)); |
| + } |
| + // Define the finish test last. |
| + audit.defineTask(actualTestName("finish-tests", testSet.length), function (done) { |
| + finishJSTest(); |
| + done(); |
| + }); |
| + } |
| + |
| + // Run all of the tests defined in testSet. |
| + function runAuditTests() { |
| + var tests = testSet.map(function (value, index) { |
| + return actualTestName(value.name, index); |
| + }).concat(actualTestName("finish-tests", testSet.length)); |
| + audit.runTasks.apply(audit, tests); |
| + }; |
| + |
| + defineAuditTests(); |
| + runAuditTests(); |
| + |
| + successfullyParsed = true; |
| + </script> |
| + </body> |
| +</html> |