| Index: third_party/WebKit/LayoutTests/webaudio/audioparam-update-value-attribute.html
|
| diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-update-value-attribute.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-update-value-attribute.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8cb4eab2f82d831e832ba07606836972ba27f2e5
|
| --- /dev/null
|
| +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-update-value-attribute.html
|
| @@ -0,0 +1,172 @@
|
| +<!doctype html>
|
| +<html>
|
| + <head>
|
| + <script src="resources/compatibility.js"></script>
|
| + <script src="resources/audio-testing.js"></script>
|
| + <script src="resources/audio-param.js"></script>
|
| + <script src="../resources/js-test.js"></script>
|
| + <title>Updating of Value Attribute from Timeline</title>
|
| + </head>
|
| +
|
| + <body>
|
| + <script>
|
| + description("Test Updating of Value Attribute from Timeline");
|
| + window.jsTestIsAsync = true;
|
| +
|
| + // This should be a power of two so that all time computations have no round-off errors.
|
| + var sampleRate = 32768;
|
| + var renderQuantumSize = 128;
|
| + // How many tests to run.
|
| + var renderLoops = 20;
|
| + var renderFrames = renderLoops * renderQuantumSize;
|
| + var renderDuration = renderFrames / sampleRate;
|
| +
|
| + var audit = Audit.createTaskRunner();
|
| +
|
| + audit.defineTask("linear", function (done) {
|
| + // Test the value attribute from a linearRamp event
|
| + runTest(function (g, v0, t0, v1, t1) {
|
| + g.gain.linearRampToValueAtTime(v1, t1);
|
| + return {
|
| + expectedValue: function (testTime) {
|
| + return audioParamLinearRamp(testTime, v0, t0, v1, t1);
|
| + },
|
| + message: "linearRamp(" + v1 + ", " + t1 + ")",
|
| + errorThreshold: 1.1650e-6
|
| + };
|
| + }).then(done);
|
| + });
|
| +
|
| + audit.defineTask("exponential", function (done) {
|
| + // Test the value attribute from an exponentialRamp event
|
| + runTest(function (g, v0, t0, v1, t1) {
|
| + g.gain.exponentialRampToValueAtTime(v1, t1);
|
| + return {
|
| + expectedValue: function (testTime) {
|
| + return audioParamExponentialRamp(testTime, v0, t0, v1, t1);
|
| + },
|
| + message: "exponentialRamp(" + v1 + ", " + t1 + ")",
|
| + errorThreshold: 7.4601e-7
|
| + };
|
| + }).then(done);
|
| + });
|
| +
|
| + audit.defineTask("setTarget", function (done) {
|
| + // Test the value attribute from a setTargetAtTime event
|
| + runTest(function (g, v0, t0, v1, t1) {
|
| + var timeConstant = 0.1;
|
| + var vFinal = 0;
|
| + g.gain.setTargetAtTime(vFinal, t0, timeConstant);
|
| + return {
|
| + expectedValue: function (testTime) {
|
| + return audioParamSetTarget(testTime, v0, t0, vFinal, timeConstant);
|
| + },
|
| + message: "setTargetAtTime(" + vFinal + ", " + t0 + ", " + timeConstant + ")",
|
| + errorThreshold: 1.2869e-6
|
| + };
|
| + }).then(done);
|
| + });
|
| +
|
| + audit.defineTask("setValueCurve", function (done) {
|
| + // Test the value attribute from a setValueCurve event
|
| + runTest(function (g, v0, t0, v1, t1) {
|
| + var curve = [1, 1.5, 4];
|
| + var duration = t1 - t0;
|
| + g.gain.setValueCurveAtTime(Float32Array.from(curve), t0, duration);
|
| + return {
|
| + expectedValue: function (testTime) {
|
| + return audioParamSetValueCurve(testTime, curve, t0, duration);
|
| + },
|
| + message: "setValueCurveAtTime([" + curve + "], " + t0 + ", " + duration + ")",
|
| + errorThreshold: 7.9577e-8
|
| + };
|
| + }).then(done);
|
| + });
|
| +
|
| + audit.defineTask("finish", function (done) {
|
| + finishJSTest();
|
| + done();
|
| + });
|
| +
|
| + audit.runTasks();
|
| +
|
| + // Test that the .value getter has the correct value when a timeline is running.
|
| + // The |testFunction| is the underlying test to be run.
|
| + function runTest(testFunction) {
|
| + // Create a simple graph consisting of a constant source and a gain node where the
|
| + // automations are run. A setValueAtTime event starts things off.
|
| + var context = new OfflineAudioContext(1, renderFrames, sampleRate);
|
| + var source = context.createBufferSource();
|
| + source.buffer = createConstantBuffer(context, 1, 1);
|
| + source.loop = true;
|
| + var gain = context.createGain();
|
| +
|
| + source.connect(gain);
|
| + gain.connect(context.destination);
|
| +
|
| + // Start the timeline with setValueAtTime(v0, t0).
|
| + var v0 = 0.25;
|
| + var t0 = 0;
|
| + // End value and time, for those that need it. The end time is less than the rendering
|
| + // duration so we can test that the final values of the automation (if any) are also
|
| + // correct.
|
| + var v1 = 100;
|
| + var t1 = renderDuration - 5 * renderQuantumSize / sampleRate;
|
| +
|
| + gain.gain.setValueAtTime(v0, t0);
|
| +
|
| + // Run the desired automation test. The test function returns a dictionary consisting of
|
| + // the following properties:
|
| + //
|
| + // |message| an informative message about the automation being tested.
|
| + // |errorThreshold| error threshold to determine if the test passes or not.
|
| + // |expectedValue| a function that compute the expected value at time |t|.
|
| + var test = testFunction(gain, v0, t0, v1, t1);
|
| +
|
| + // Print an informative message about the test being run.
|
| + testPassed("Initialize " + test.message + " with setValueAtTime(" + v0 + ", " + t0 + ").");
|
| +
|
| + var success = true;
|
| +
|
| + // Max relative error found for this test. This is printed if the test fails so that setting
|
| + // the thresholds is easier.
|
| + var maxError = 0;
|
| +
|
| + // For every rendering quantum (except the first), suspend the context so the we can inspect
|
| + // the value attribute and compare it with the expected value.
|
| + for (var k = 1; k < renderLoops; ++k) {
|
| + var time = k * renderQuantumSize / sampleRate;
|
| + context.suspend(time).then(function () {
|
| + // The context is supsended at time |time|, which is just before the rendering quantum
|
| + // starts. Thus, the value of the attribute is actually 1 frame before the current
|
| + // context time.
|
| + var sampleTime = context.currentTime - 1 / sampleRate;
|
| +
|
| + // Compute the max relative error
|
| + var expected = test.expectedValue(sampleTime);
|
| + var relError = Math.abs(expected - gain.gain.value) / Math.abs(expected);
|
| + maxError = Math.max(relError, maxError);
|
| +
|
| + success = Should(test.message + " at frame " + (sampleRate * sampleTime),
|
| + gain.gain.value, {
|
| + precision: 7
|
| + })
|
| + .beCloseTo(expected, test.errorThreshold || 0) && success;
|
| + }).then(context.resume.bind(context));
|
| + }
|
| +
|
| + source.start();
|
| +
|
| + return context.startRendering().then(function (resultBuffer) {
|
| + // Just print a final pass (or fail) message.
|
| + if (success)
|
| + testPassed("Gain .value attribute correctly updated during automation.\n");
|
| + else
|
| + testFailed(
|
| + "Gain .value attribute not correctly updated during automation; max error = " +
|
| + maxError + ".\n");
|
| + });
|
| + }
|
| + </script>
|
| + </body>
|
| +</html>
|
|
|