| Index: third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html
|
| diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f5bbf22ae71f1356ee709b86a9b791eac0a50ebf
|
| --- /dev/null
|
| +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html
|
| @@ -0,0 +1,235 @@
|
| +<!doctype html>
|
| +<html>
|
| + <head>
|
| + <script src="../resources/js-test.js"></script>
|
| + <script src="resources/compatibility.js"></script>
|
| + <script src="resources/audio-testing.js"></script>
|
| + <script src="resources/audioparam-testing.js"></script>
|
| + <title>SetTarget Followed by Linear or Exponential Ramp Is Continuous</title>
|
| + </head>
|
| +
|
| + <body>
|
| + <script>
|
| + description("Test SetTarget Followed by Linear or Exponential Ramp");
|
| + window.jsTestIsAsync = true;
|
| +
|
| + var sampleRate = 48000;
|
| + var renderQuantum = 128;
|
| + // Test doesn't need to run for very long.
|
| + var renderDuration = 0.1;
|
| + // Where the ramp should end
|
| + var rampEndTime = renderDuration - .05;
|
| + var renderFrames = renderDuration * sampleRate;
|
| + var timeConstant = 0.01;
|
| +
|
| + var audit = Audit.createTaskRunner();
|
| +
|
| + // All of the tests start a SetTargetAtTime after one rendering quantum. The following tests
|
| + // handle various cases where a linear or exponential ramp is scheduled at or after
|
| + // SetTargetAtTime starts.
|
| +
|
| + audit.defineTask("linear ramp replace", function (done) {
|
| + // Schedule a linear ramp to start at the same time as SetTargetAtTime. This effectively
|
| + // replaces the SetTargetAtTime as if it never existed.
|
| + runTest("Linear ramp", {
|
| + automationFunction: function (audioparam, endValue, endTime) {
|
| + audioparam.linearRampToValueAtTime(endValue, endTime);
|
| + },
|
| + referenceFunction: linearResult,
|
| + automationTime: renderQuantum / sampleRate,
|
| + thresholdSetTarget: 0,
|
| + thresholdRamp: 1.26765e-6
|
| + }).then(done);
|
| + });
|
| +
|
| + audit.defineTask("delayed linear ramp", function (done) {
|
| + // Schedule a linear ramp to start after the SetTargetAtTime has already started rendering.
|
| + // This is the main test to verify that the linear ramp is continuous with the
|
| + // SetTargetAtTime curve.
|
| + runTest("Delayed linear ramp", {
|
| + automationFunction: function (audioparam, endValue, endTime) {
|
| + audioparam.linearRampToValueAtTime(endValue, endTime);
|
| + },
|
| + referenceFunction: linearResult,
|
| + automationTime: 4 * renderQuantum / sampleRate,
|
| + thresholdSetTarget: 2.19417e-7,
|
| + thresholdRamp: 1.07972e-6
|
| + }).then(done);
|
| + });
|
| +
|
| + audit.defineTask("expo ramp replace", function (done) {
|
| + // Like "linear ramp replace", but with an exponential ramp instead.
|
| + runTest("Exponential ramp", {
|
| + automationFunction: function (audioparam, endValue, endTime) {
|
| + audioparam.exponentialRampToValueAtTime(endValue, endTime);
|
| + },
|
| + referenceFunction: exponentialResult,
|
| + automationTime: renderQuantum / sampleRate,
|
| + thresholdSetTarget: 0,
|
| + thresholdRamp: 1.13249e-5
|
| + }).then(done);
|
| + });
|
| +
|
| + audit.defineTask("delayed expo ramp", function (done) {
|
| + // Like "delayed linear ramp", but with an exponential ramp instead.
|
| + runTest("Delayed exponential ramp", {
|
| + automationFunction: function (audioparam, endValue, endTime) {
|
| + audioparam.exponentialRampToValueAtTime(endValue, endTime);
|
| + },
|
| + referenceFunction: exponentialResult,
|
| + automationTime: 4 * renderQuantum / sampleRate,
|
| + thresholdSetTarget: 2.19417e-7,
|
| + thresholdRamp: 4.17233e-6
|
| + }).then(done);
|
| + });
|
| +
|
| + audit.defineTask("finish", function (done) {
|
| + finishJSTest();
|
| + done();
|
| + });
|
| +
|
| + audit.runTasks();
|
| +
|
| + function computeExpectedResult(automationTime, timeConstant, endValue, endTime, rampFunction) {
|
| + // The result is a constant value of 1 for one rendering quantum, then a SetTarget event
|
| + // lasting to |automationTime|, at which point a ramp starts which ends at |endValue|
|
| + // at |endTime|. Then the rest of curve should be held constant at |endValue|.
|
| + var initialPart = new Array(renderQuantum);
|
| + initialPart.fill(1);
|
| +
|
| + // Generate 1 extra frame so that we know where to start the linear ramp. The last sample
|
| + // of the array is where the ramp should start from.
|
| + var setTargetPart = createExponentialApproachArray(renderQuantum / sampleRate,
|
| + automationTime + 1 / sampleRate, 1, 0, sampleRate, timeConstant);
|
| + var setTargetLength = setTargetPart.length;
|
| +
|
| + // Generate the ramp starting at |automationTime| with a value from last value of the
|
| + // SetTarget curve above.
|
| + var rampPart = rampFunction(automationTime, endTime,
|
| + setTargetPart[setTargetLength - 1], endValue, sampleRate);
|
| +
|
| + // Finally finish out the rest with a constant value of |endValue|, if needed.
|
| + var finalPart = new Array(Math.floor((renderDuration - endTime) * sampleRate));
|
| + finalPart.fill(endValue);
|
| +
|
| + // Return the four parts separately for testing.
|
| + return {
|
| + initialPart: initialPart,
|
| + setTargetPart: setTargetPart.slice(0, setTargetLength - 1),
|
| + rampPart: rampPart,
|
| + tailPart: finalPart
|
| + };
|
| + }
|
| +
|
| + function linearResult(automationTime, timeConstant, endValue, endTime) {
|
| + return computeExpectedResult(automationTime, timeConstant, endValue, endTime, createLinearRampArray);
|
| + }
|
| +
|
| + function exponentialResult(automationTime, timeConstant, endValue, endTime) {
|
| + return computeExpectedResult(automationTime, timeConstant, endValue, endTime, createExponentialRampArray);
|
| + }
|
| +
|
| + // Run test to verify that a SetTarget followed by a ramp produces a continuous curve.
|
| + // |prefix| is a string to use as a prefix for the messages. |options| is a dictionary
|
| + // describing how the test is run:
|
| + //
|
| + // |options.automationFunction|
|
| + // The function to use to start the automation, which should be a linear or exponential
|
| + // ramp automation. This function has three arguments:
|
| + // audioparam - the AudioParam to be automated
|
| + // endValue - the end value of the ramp
|
| + // endTime - the end time fo the ramp.
|
| + // |options.referenceFunction|
|
| + // The function to generated the expected result. This function has four arguments:
|
| + // automationTime - the value of |options.automationTime|
|
| + // timeConstant - time constant used for SetTargetAtTime
|
| + // rampEndValue - end value for the ramp (same value used for automationFunction)
|
| + // rampEndTime - end time for the ramp (same value used for automationFunction)
|
| + // |options.automationTime|
|
| + // Time at which the |automationFunction| is called to start the automation.
|
| + // |options.thresholdSetTarget|
|
| + // Threshold to use for verifying that the initial (if any) SetTargetAtTime portion had
|
| + // the correct values.
|
| + // |options.thresholdRamp|
|
| + // Threshold to use for verifying that the ramp portion had the correct values.
|
| + function runTest(prefix, options) {
|
| + var automationFunction = options.automationFunction;
|
| + var referenceFunction = options.referenceFunction;
|
| + var automationTime = options.automationTime;
|
| + var thresholdSetTarget = options.thresholdSetTarget || 0;
|
| + var thresholdRamp = options.thresholdRamp || 0;
|
| +
|
| + // End value for the ramp. Fairly arbitrary, but should be distinctly different from the
|
| + // target value for SetTargetAtTime and the initial value of gain.gain.
|
| + var rampEndValue = 2;
|
| + var context = new OfflineAudioContext(1, renderFrames, sampleRate);
|
| +
|
| + // A constant source of amplitude 1.
|
| + var source = context.createBufferSource();
|
| + source.buffer = createConstantBuffer(context, 1, 1);
|
| + source.loop = true;
|
| +
|
| + var gain = context.createGain();
|
| +
|
| + // The SetTarget starts after one rendering quantum.
|
| + gain.gain.setTargetAtTime(0, renderQuantum / context.sampleRate, timeConstant);
|
| +
|
| + // Schedule the ramp at |automationTime|. If this time is past the first rendering quantum,
|
| + // the SetTarget event will run for a bit before running the ramp. Otherwise, the SetTarget
|
| + // should be completely replaced by the ramp.
|
| + context.suspend(automationTime)
|
| + .then(function () {
|
| + automationFunction(gain.gain, rampEndValue, rampEndTime);
|
| + context.resume();
|
| + });
|
| +
|
| + source.connect(gain);
|
| + gain.connect(context.destination);
|
| +
|
| + source.start();
|
| +
|
| + return context.startRendering().then(function (resultBuffer) {
|
| + var success = true;
|
| + var result = resultBuffer.getChannelData(0);
|
| + var expected = referenceFunction(automationTime, timeConstant, rampEndValue, rampEndTime);
|
| +
|
| + // Verify each part of the curve separately.
|
| + var startIndex = 0;
|
| + var length = expected.initialPart.length;
|
| +
|
| + // Verify that the initial part of the curve is constant.
|
| + success = Should(prefix + ": Initial part", result.slice(0, length))
|
| + .beCloseToArray(expected.initialPart, 0) && success;
|
| +
|
| + // Verify the SetTarget part of the curve, if the SetTarget did actually run.
|
| + startIndex += length;
|
| + length = expected.setTargetPart.length;
|
| + if (length) {
|
| + success = Should(prefix + ": SetTarget part", result.slice(startIndex, startIndex +
|
| + length))
|
| + .beCloseToArray(expected.setTargetPart, thresholdSetTarget) && success;
|
| + } else {
|
| + testPassed("SetTarget part was correctly replaced by the ramp");
|
| + }
|
| +
|
| + // Verify the ramp part of the curve
|
| + startIndex += length;
|
| + length = expected.rampPart.length;
|
| + success = Should(prefix, result.slice(startIndex, startIndex + length), {
|
| + verbose: true
|
| + }).beCloseToArray(expected.rampPart, thresholdRamp) && success;
|
| +
|
| + // Verify that the end of the curve after the ramp (if any) is a constant.
|
| + startIndex += length;
|
| + success = Should(prefix + ": Tail part", result.slice(startIndex))
|
| + .beCloseToArray(expected.tailPart, 0) && success;
|
| +
|
| + if (success)
|
| + testPassed(prefix + " preceded by SetTarget is continuous.\n");
|
| + else
|
| + testFailed(prefix + " preceded by SetTarget was not continuous.\n");
|
| + });
|
| + }
|
| + </script>
|
| + </body>
|
| +</html>
|
|
|