| Index: LayoutTests/webaudio/osc-sine-sweep-snr.html
 | 
| diff --git a/LayoutTests/webaudio/osc-sine-sweep-snr.html b/LayoutTests/webaudio/osc-sine-sweep-snr.html
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..80799f119bf66ac7c1e44b093b9eb3d0cdcf005c
 | 
| --- /dev/null
 | 
| +++ b/LayoutTests/webaudio/osc-sine-sweep-snr.html
 | 
| @@ -0,0 +1,131 @@
 | 
| +<!doctype html>
 | 
| +<html>
 | 
| +  <head>
 | 
| +    <title>Test Oscillator Node: sine</title>
 | 
| +    <script src="resources/compatibility.js"></script>
 | 
| +    <script src="resources/buffer-loader.js"></script>
 | 
| +    <script src="../resources/js-test.js"></script>
 | 
| +    <script src="resources/oscillator-testing.js"></script>
 | 
| +  </head>
 | 
| +
 | 
| +  <body>
 | 
| +    <script>
 | 
| +        // See oscillator-sine.html for more info on the actual wave shape.
 | 
| +        //
 | 
| +        // This test is a partial duplicate of oscillator-sine but is designed to be less sensitive
 | 
| +        // to the actual output versus the reference. Instead of requiring an exact match, we check
 | 
| +        // several criteria to pass the test. The SNR between the actual and expected signals must
 | 
| +        // be large enough.  The maximum difference must be below a threshold, and the actual number
 | 
| +        // of points that are different must be below a threshold.
 | 
| +
 | 
| +        var sampleRate = 44100.0;
 | 
| +        var nyquist = 0.5 * sampleRate;
 | 
| +        var lengthInSeconds = 4;
 | 
| +        var lowFrequency = 10;
 | 
| +        var highFrequency = nyquist + 2000; // go slightly higher than nyquist to make sure we generate silence there
 | 
| +        var context = 0;
 | 
| +        var reference = 0;
 | 
| +        var renderedData = 0;
 | 
| +        var signalPower = 0;
 | 
| +        var noisePower = 0;
 | 
| +
 | 
| +        // Scaling factor for converting the 16-bit WAV data to float (and vice-versa).
 | 
| +        var waveScaleFactor = 32768;
 | 
| +
 | 
| +        // Thresholds for verifying the test passes.  The thresholds are experimentally determined.
 | 
| +      
 | 
| +        // SNR must be greater than this to pass the test.
 | 
| +        // Q: Why is the SNR threshold not infinity?
 | 
| +        // A: The reference result is a 16-bit WAV file, so it won't compare exactly with the
 | 
| +        //    floating point result.
 | 
| +        var thresholdSNR = 86.58;
 | 
| +
 | 
| +        // Max diff must be less than this to pass the test.
 | 
| +        var thresholdDiff = 2.9 / waveScaleFactor;
 | 
| +
 | 
| +        // Count the number of differences between the expected and actual result. The tests passes
 | 
| +        // if the count is less than this threshold.
 | 
| +        var thresholdDiffCount = 5850;
 | 
| +
 | 
| +        function db(sPower, nPower)
 | 
| +        {
 | 
| +            if (nPower == 0 && sPower > 0) {
 | 
| +                return 1000;
 | 
| +            }
 | 
| +            return 10 * Math.log10(sPower / nPower);
 | 
| +        }
 | 
| +
 | 
| +        function checkResult (event) {
 | 
| +            renderedData = event.renderedBuffer.getChannelData(0);
 | 
| +            // Compute signal to noise ratio between the result and the reference. Also keep track
 | 
| +            // of the max difference (and position).
 | 
| +
 | 
| +            var maxError = -1;
 | 
| +            var errorPosition = -1;
 | 
| +            var diffCount = 0;
 | 
| +
 | 
| +            for (var k = 0; k < renderedData.length; ++k) {
 | 
| +                var diff = renderedData[k] - reference[k];
 | 
| +                noisePower += diff * diff;
 | 
| +                signalPower += reference[k] * reference[k];
 | 
| +                if (Math.abs(diff) > maxError) {
 | 
| +                    maxError = Math.abs(diff);
 | 
| +                    errorPosition = k;
 | 
| +                }
 | 
| +                // The reference file is a 16-bit WAV file, so we will never get an exact match
 | 
| +                // between it and the actual floating-point result.
 | 
| +                if (diff > 1/waveScaleFactor) {
 | 
| +                    diffCount++;
 | 
| +                }
 | 
| +            }
 | 
| +
 | 
| +            var snr = db(signalPower, noisePower);
 | 
| +            if (snr < thresholdSNR) {
 | 
| +                testFailed("Expected SNR of " + thresholdSNR + " dB, but actual SNR is " + snr + " dB");
 | 
| +            } else {
 | 
| +                testPassed("Exceeded SNR threshold of " + thresholdSNR + " dB");
 | 
| +            }
 | 
| +
 | 
| +            if (maxError > thresholdDiff) {
 | 
| +                testFailed("Maximum difference of " + (maxError * waveScaleFactor) + " at "
 | 
| +                    + errorPosition + " exceeded threshold of " + (thresholdDiff * waveScaleFactor)
 | 
| +                    + " ulp (16-bits)");
 | 
| +            } else {
 | 
| +                testPassed("Maximum difference below threshold of "
 | 
| +                    + (thresholdDiff * waveScaleFactor) + " ulp (16-bits)");
 | 
| +            }
 | 
| +            if (diffCount > thresholdDiffCount) {
 | 
| +                testFailed(diffCount + " differences found but expected no more than " + thresholdDiffCount);
 | 
| +            } else {
 | 
| +                testPassed("Number of differences between actual and expected result is less than " + thresholdDiffCount);
 | 
| +            }
 | 
| +
 | 
| +            finishJSTest();
 | 
| +        }
 | 
| +
 | 
| +        function finishedLoading(bufferList) {
 | 
| +            reference = bufferList[0].getChannelData(0);
 | 
| +            generateExponentialOscillatorSweep(context, "sine");
 | 
| +            context.oncomplete = checkResult;
 | 
| +            context.startRendering();    
 | 
| +        }
 | 
| +
 | 
| +        function runTest () {
 | 
| +            window.jsTestIsAsync = true;
 | 
| +
 | 
| +            // Create offline audio context.
 | 
| +            context = new OfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRate);
 | 
| +
 | 
| +            bufferLoader = new BufferLoader(
 | 
| +                context,
 | 
| +                [ "oscillator-sine-expected.wav" ],
 | 
| +                finishedLoading);
 | 
| +
 | 
| +            bufferLoader.load();
 | 
| +        }
 | 
| +
 | 
| +        runTest();
 | 
| +        successfullyParsed = true;
 | 
| +    </script>
 | 
| +  </body>
 | 
| +</html>
 | 
| 
 |