Chromium Code Reviews| 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..1c3d4365f52253934ac28f902a2cf4e347e324f4 |
| --- /dev/null |
| +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-setTargetAtTime-continuous.html |
| @@ -0,0 +1,199 @@ |
| +<!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(); |
| + |
| + audit.defineTask("linear ramp replace", function (done) { |
|
hongchan
2016/01/29 18:53:58
Can we have a brief description for each test task
Raymond Toy
2016/04/26 16:38:53
Done.
|
| + 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) { |
|
hongchan
2016/01/29 18:53:58
Ditto.
Raymond Toy
2016/04/26 16:38:53
Done.
|
| + 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", function (done) { |
|
hongchan
2016/01/29 18:53:58
Ditto.
Raymond Toy
2016/04/26 16:38:53
Done.
|
| + 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) { |
|
hongchan
2016/01/29 18:53:58
Ditto.
Raymond Toy
2016/04/26 16:38:53
Done.
|
| + 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. |
| + 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; |
| + |
| + 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)) |
| + .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> |