| Index: third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-setValueCurveAtTime-interpolation.html
|
| diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-setValueCurveAtTime-interpolation.html b/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-setValueCurveAtTime-interpolation.html
|
| index 7b80a388413997bb09d8914eb5ab4d149a637c9a..f15a3fc6a6e6637971eba6b4029bc1b2ade549c6 100644
|
| --- a/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-setValueCurveAtTime-interpolation.html
|
| +++ b/third_party/WebKit/LayoutTests/webaudio/AudioParam/audioparam-setValueCurveAtTime-interpolation.html
|
| @@ -1,150 +1,168 @@
|
| -<!doctype html>
|
| +<!DOCTYPE html>
|
| <html>
|
| <head>
|
| - <title>Test Interpolation for AudioParam.setValueCurveAtTime</title>
|
| + <title>
|
| + Test Interpolation for AudioParam.setValueCurveAtTime
|
| + </title>
|
| <script src="../../resources/testharness.js"></script>
|
| - <script src="../../resources/testharnessreport.js"></script>
|
| + <script src="../../resources/testharnessreport.js"></script>
|
| <script src="../resources/audit-util.js"></script>
|
| <script src="../resources/audit.js"></script>
|
| - <title>Test Interpolation for AudioParam.setValueCurveAtTime</title>
|
| + <title>
|
| + Test Interpolation for AudioParam.setValueCurveAtTime
|
| + </title>
|
| </head>
|
| -
|
| <body>
|
| - <script>
|
| -
|
| - // Play a constant signal through a gain node that is automated using setValueCurveAtTime with
|
| - // a 2-element curve. The output should be a linear change.
|
| -
|
| - // Choose a sample rate that is a multiple of 128, the rendering quantum size. This makes the
|
| - // math work out to be nice numbers.
|
| - var sampleRate = 25600;
|
| - var testDurationSec = 1;
|
| - var testDurationFrames = testDurationSec * sampleRate;
|
| -
|
| - // Where the curve starts and its duration. This MUST be less than the total rendering time.
|
| - var curveStartTime = 256 / sampleRate;
|
| - var curveDuration = 300 / sampleRate;;
|
| - var curveValue = 0.75;
|
| -
|
| - // At this time, the gain node goes to gain 1. This is used to make sure the value curve is
|
| - // propagated correctly until the next event.
|
| - var fullGainTime = 0.75;
|
| -
|
| - // Thresholds use to determine if the test passes; these are experimentally determined. The
|
| - // SNR between the actual and expected result should be at least |snrThreshold|. The maximum
|
| - // difference betwen them should not exceed |maxErrorThreshold|.
|
| - var snrThreshold = 10000;
|
| - var maxErrorThreshold = 0;
|
| -
|
| - var context;
|
| - var actualResult;
|
| - var expectedResult;
|
| -
|
| - var audit = Audit.createTaskRunner();
|
| -
|
| - // Array of test configs. Each config must specify curveStartTime, curveDuration,
|
| - // curveLength, fullGainTime, maxErrorThreshold, and snrThreshold.
|
| - var testConfigs = [{
|
| - // The main test
|
| - curveStartTime: 256 / sampleRate,
|
| - curveDuration: 300 / sampleRate,
|
| - curveLength: 2,
|
| - fullGainTime: 0.75,
|
| - maxErrorThreshold: 5.9605e-8,
|
| - snrThreshold: 171.206
|
| - }, {
|
| - // Increase the curve length
|
| - curveStartTime: 256 / sampleRate,
|
| - curveDuration: 300 / sampleRate,
|
| - curveLength: 3,
|
| - fullGainTime: 0.75,
|
| - maxErrorThreshold: 5.9605e-8,
|
| - snrThreshold: 171.206
|
| - }, {
|
| - // Increase the curve length
|
| - curveStartTime: 256 / sampleRate,
|
| - curveDuration: 300 / sampleRate,
|
| - curveLength: 16,
|
| - fullGainTime: 0.75,
|
| - maxErrorThreshold: 5.9605e-8,
|
| - snrThreshold: 170.892
|
| - }, {
|
| - // Increase the curve length
|
| - curveStartTime: 256 / sampleRate,
|
| - curveDuration: 300 / sampleRate,
|
| - curveLength: 100,
|
| - fullGainTime: 0.75,
|
| - maxErrorThreshold: 1.1921e-7,
|
| - snrThreshold: 168.712
|
| - }, {
|
| - // Corner case with duration less than a frame!
|
| - curveStartTime: 256 / sampleRate,
|
| - curveDuration: 0.25 / sampleRate,
|
| - curveLength: 2,
|
| - fullGainTime: 0.75,
|
| - maxErrorThreshold: 0,
|
| - snrThreshold: 10000
|
| - }, {
|
| - // Short duration test
|
| - curveStartTime: 256 / sampleRate,
|
| - curveDuration: 2 / sampleRate,
|
| - curveLength: 2,
|
| - fullGainTime: 0.75,
|
| - maxErrorThreshold: 0,
|
| - snrThreshold: 10000
|
| - }, {
|
| - // Short duration test with many points.
|
| - curveStartTime: 256 / sampleRate,
|
| - curveDuration: 2 / sampleRate,
|
| - curveLength: 8,
|
| - fullGainTime: 0.75,
|
| - maxErrorThreshold: 0,
|
| - snrThreshold: 10000
|
| - }, {
|
| - // Long duration, big curve
|
| - curveStartTime: 256 / sampleRate,
|
| - curveDuration: .5,
|
| - curveLength: 1000,
|
| - fullGainTime: 0.75,
|
| - maxErrorThreshold: 5.9605e-8,
|
| - snrThreshold: 152.784
|
| - }];
|
| -
|
| - // Creates a function based on the test config that is suitable for use by defineTask().
|
| + <script id="layout-test-code">
|
| + // Play a constant signal through a gain node that is automated using
|
| + // setValueCurveAtTime with a 2-element curve. The output should be a
|
| + // linear change.
|
| +
|
| + // Choose a sample rate that is a multiple of 128, the rendering quantum
|
| + // size. This makes the math work out to be nice numbers.
|
| + let sampleRate = 25600;
|
| + let testDurationSec = 1;
|
| + let testDurationFrames = testDurationSec * sampleRate;
|
| +
|
| + // Where the curve starts and its duration. This MUST be less than the
|
| + // total rendering time.
|
| + let curveStartTime = 256 / sampleRate;
|
| + let curveDuration = 300 / sampleRate;
|
| + ;
|
| + let curveValue = 0.75;
|
| +
|
| + // At this time, the gain node goes to gain 1. This is used to make sure
|
| + // the value curve is propagated correctly until the next event.
|
| + let fullGainTime = 0.75;
|
| +
|
| + // Thresholds use to determine if the test passes; these are
|
| + // experimentally determined. The SNR between the actual and expected
|
| + // result should be at least |snrThreshold|. The maximum difference
|
| + // betwen them should not exceed |maxErrorThreshold|.
|
| + let snrThreshold = 10000;
|
| + let maxErrorThreshold = 0;
|
| +
|
| + let context;
|
| + let actualResult;
|
| + let expectedResult;
|
| +
|
| + let audit = Audit.createTaskRunner();
|
| +
|
| + // Array of test configs. Each config must specify curveStartTime,
|
| + // curveDuration, curveLength, fullGainTime, maxErrorThreshold, and
|
| + // snrThreshold.
|
| + let testConfigs = [
|
| + {
|
| + // The main test
|
| + curveStartTime: 256 / sampleRate,
|
| + curveDuration: 300 / sampleRate,
|
| + curveLength: 2,
|
| + fullGainTime: 0.75,
|
| + maxErrorThreshold: 5.9605e-8,
|
| + snrThreshold: 171.206
|
| + },
|
| + {
|
| + // Increase the curve length
|
| + curveStartTime: 256 / sampleRate,
|
| + curveDuration: 300 / sampleRate,
|
| + curveLength: 3,
|
| + fullGainTime: 0.75,
|
| + maxErrorThreshold: 5.9605e-8,
|
| + snrThreshold: 171.206
|
| + },
|
| + {
|
| + // Increase the curve length
|
| + curveStartTime: 256 / sampleRate,
|
| + curveDuration: 300 / sampleRate,
|
| + curveLength: 16,
|
| + fullGainTime: 0.75,
|
| + maxErrorThreshold: 5.9605e-8,
|
| + snrThreshold: 170.892
|
| + },
|
| + {
|
| + // Increase the curve length
|
| + curveStartTime: 256 / sampleRate,
|
| + curveDuration: 300 / sampleRate,
|
| + curveLength: 100,
|
| + fullGainTime: 0.75,
|
| + maxErrorThreshold: 1.1921e-7,
|
| + snrThreshold: 168.712
|
| + },
|
| + {
|
| + // Corner case with duration less than a frame!
|
| + curveStartTime: 256 / sampleRate,
|
| + curveDuration: 0.25 / sampleRate,
|
| + curveLength: 2,
|
| + fullGainTime: 0.75,
|
| + maxErrorThreshold: 0,
|
| + snrThreshold: 10000
|
| + },
|
| + {
|
| + // Short duration test
|
| + curveStartTime: 256 / sampleRate,
|
| + curveDuration: 2 / sampleRate,
|
| + curveLength: 2,
|
| + fullGainTime: 0.75,
|
| + maxErrorThreshold: 0,
|
| + snrThreshold: 10000
|
| + },
|
| + {
|
| + // Short duration test with many points.
|
| + curveStartTime: 256 / sampleRate,
|
| + curveDuration: 2 / sampleRate,
|
| + curveLength: 8,
|
| + fullGainTime: 0.75,
|
| + maxErrorThreshold: 0,
|
| + snrThreshold: 10000
|
| + },
|
| + {
|
| + // Long duration, big curve
|
| + curveStartTime: 256 / sampleRate,
|
| + curveDuration: .5,
|
| + curveLength: 1000,
|
| + fullGainTime: 0.75,
|
| + maxErrorThreshold: 5.9605e-8,
|
| + snrThreshold: 152.784
|
| + }
|
| + ];
|
| +
|
| + // Creates a function based on the test config that is suitable for use by
|
| + // defineTask().
|
| function createTaskFunction(config) {
|
| - return function (task, should) {
|
| + return function(task, should) {
|
| runTest(should, config).then(() => task.done());
|
| };
|
| }
|
|
|
| // Define a task for each config, in the order listed in testConfigs.
|
| - for (var k = 0; k < testConfigs.length; ++k) {
|
| - var config = testConfigs[k];
|
| - var name = k + ":curve=" + config.curveLength + ",duration=" + (config.curveDuration * sampleRate);
|
| + for (let k = 0; k < testConfigs.length; ++k) {
|
| + let config = testConfigs[k];
|
| + let name = k + ':curve=' + config.curveLength +
|
| + ',duration=' + (config.curveDuration * sampleRate);
|
| audit.define(name, createTaskFunction(config));
|
| }
|
|
|
| - // Simple test from crbug.com/441471. Makes sure the end points and the middle point are
|
| - // interpolated correctly.
|
| - audit.define("crbug-441471", (task, should) => {
|
| - // Any sample rate should work; we pick something small such that the time end points are on
|
| - // a sampling point.
|
| - var context = new OfflineAudioContext(1, 5000, 5000)
|
| + // Simple test from crbug.com/441471. Makes sure the end points and the
|
| + // middle point are interpolated correctly.
|
| + audit.define('crbug-441471', (task, should) => {
|
| + // Any sample rate should work; we pick something small such that the
|
| + // time end points are on a sampling point.
|
| + let context = new OfflineAudioContext(1, 5000, 5000)
|
|
|
| - // A constant source
|
| - var source = context.createBufferSource();
|
| + // A constant source
|
| + let source = context.createBufferSource();
|
| source.buffer = createConstantBuffer(context, 1, 1);
|
| source.loop = true;
|
|
|
| - var gain = context.createGain();
|
| + let gain = context.createGain();
|
| +
|
| + let startTime = 0.7;
|
| + let duration = 0.2;
|
|
|
| - var startTime = 0.7;
|
| - var duration = 0.2;
|
| -
|
| - // Create the curve. The interpolated result should be just a straight line from -1 to 1
|
| - // from time startTime to startTime + duration.
|
| + // Create the curve. The interpolated result should be just a straight
|
| + // line from -1 to 1 from time startTime to startTime + duration.
|
|
|
| - var c = new Float32Array(3);
|
| + let c = new Float32Array(3);
|
| c[0] = -1;
|
| c[1] = 0;
|
| c[2] = 1;
|
| @@ -153,45 +171,52 @@
|
| gain.connect(context.destination);
|
| source.start();
|
|
|
| - context.startRendering().then(function (renderedBuffer) {
|
| - var data = renderedBuffer.getChannelData(0);
|
| - var endTime = startTime + duration;
|
| - var midPoint = (startTime + endTime) / 2;
|
| -
|
| - should(data[timeToSampleFrame(startTime, context.sampleRate)],
|
| - "Curve value at time " + startTime)
|
| - .beEqualTo(c[0]);
|
| - // Due to round-off, the value at the midpoint is not exactly zero on arm64. See
|
| - // crbug.com/558563. The current value is experimentally determined.
|
| - should(data[timeToSampleFrame(midPoint, context.sampleRate)],
|
| - "Curve value at time " + midPoint)
|
| - .beCloseTo(0, {threshold: Math.pow(2, -51)});
|
| - should(data[timeToSampleFrame(endTime, context.sampleRate)],
|
| - "Curve value at time " + endTime)
|
| - .beEqualTo(c[2]);
|
| - }).then(() => task.done());
|
| + context.startRendering()
|
| + .then(function(renderedBuffer) {
|
| + let data = renderedBuffer.getChannelData(0);
|
| + let endTime = startTime + duration;
|
| + let midPoint = (startTime + endTime) / 2;
|
| +
|
| + should(
|
| + data[timeToSampleFrame(startTime, context.sampleRate)],
|
| + 'Curve value at time ' + startTime)
|
| + .beEqualTo(c[0]);
|
| + // Due to round-off, the value at the midpoint is not exactly zero
|
| + // on arm64. See crbug.com/558563. The current value is
|
| + // experimentally determined.
|
| + should(
|
| + data[timeToSampleFrame(midPoint, context.sampleRate)],
|
| + 'Curve value at time ' + midPoint)
|
| + .beCloseTo(0, {threshold: Math.pow(2, -51)});
|
| + should(
|
| + data[timeToSampleFrame(endTime, context.sampleRate)],
|
| + 'Curve value at time ' + endTime)
|
| + .beEqualTo(c[2]);
|
| + })
|
| + .then(() => task.done());
|
| });
|
|
|
| function runTest(should, config) {
|
| context = new OfflineAudioContext(1, testDurationFrames, sampleRate);
|
|
|
| // A constant audio source of value 1.
|
| - var source = context.createBufferSource();
|
| + let source = context.createBufferSource();
|
| source.buffer = createConstantBuffer(context, 1, 1);
|
| source.loop = true;
|
|
|
| - // The value curve for testing. Just to make things easy for testing, make the curve a
|
| - // simple ramp up to curveValue.
|
| + // The value curve for testing. Just to make things easy for testing,
|
| + // make the curve a simple ramp up to curveValue.
|
| // TODO(rtoy): Maybe allow more complicated curves?
|
| - var curve = new Float32Array(config.curveLength);
|
| - for (var k = 0; k < config.curveLength; ++k) {
|
| + let curve = new Float32Array(config.curveLength);
|
| + for (let k = 0; k < config.curveLength; ++k) {
|
| curve[k] = curveValue / (config.curveLength - 1) * k;
|
| }
|
|
|
| // A gain node that is to be automated using setValueCurveAtTime.
|
| - var gain = context.createGain();
|
| + let gain = context.createGain();
|
| gain.gain.value = 0;
|
| - gain.gain.setValueCurveAtTime(curve, config.curveStartTime, config.curveDuration);
|
| + gain.gain.setValueCurveAtTime(
|
| + curve, config.curveStartTime, config.curveDuration);
|
| // This is to verify that setValueCurveAtTime ends appropriately.
|
| gain.gain.setValueAtTime(1, config.fullGainTime);
|
|
|
| @@ -200,83 +225,90 @@
|
| source.start();
|
|
|
| // Some consistency checks on the test parameters
|
| - let prefix = "Length " + config.curveLength + ", duration " + config.curveDuration;
|
| - should(config.curveStartTime + config.curveDuration,
|
| - prefix + ": Check: Curve end time")
|
| - .beLessThanOrEqualTo(testDurationSec);
|
| - should(config.fullGainTime, prefix + ": Check: Full gain start time")
|
| - .beLessThanOrEqualTo(testDurationSec);
|
| - should(config.fullGainTime,
|
| - prefix + ": Check: Full gain start time")
|
| - .beGreaterThanOrEqualTo(config.curveStartTime + config.curveDuration);
|
| + let prefix = 'Length ' + config.curveLength + ', duration ' +
|
| + config.curveDuration;
|
| + should(
|
| + config.curveStartTime + config.curveDuration,
|
| + prefix + ': Check: Curve end time')
|
| + .beLessThanOrEqualTo(testDurationSec);
|
| + should(config.fullGainTime, prefix + ': Check: Full gain start time')
|
| + .beLessThanOrEqualTo(testDurationSec);
|
| + should(config.fullGainTime, prefix + ': Check: Full gain start time')
|
| + .beGreaterThanOrEqualTo(
|
| + config.curveStartTime + config.curveDuration);
|
|
|
| // Rock and roll!
|
| return context.startRendering().then(checkResult(should, config));
|
| }
|
|
|
| - // Return a function to check that the rendered result matches the expected result.
|
| + // Return a function to check that the rendered result matches the
|
| + // expected result.
|
| function checkResult(should, config) {
|
| - return function (renderedBuffer) {
|
| - var success = true;
|
| + return function(renderedBuffer) {
|
| + let success = true;
|
|
|
| actualResult = renderedBuffer.getChannelData(0);
|
| expectedResult = computeExpectedResult(config);
|
|
|
| - // Compute the SNR and max absolute difference between the actual and expected result.
|
| - var SNR = 10*Math.log10(computeSNR(actualResult, expectedResult));
|
| - var maxDiff = -1;
|
| - var posn = -1;
|
| + // Compute the SNR and max absolute difference between the actual and
|
| + // expected result.
|
| + let SNR = 10 * Math.log10(computeSNR(actualResult, expectedResult));
|
| + let maxDiff = -1;
|
| + let posn = -1;
|
|
|
| - for (var k = 0; k < actualResult.length; ++k) {
|
| - var diff = Math.abs(actualResult[k] - expectedResult[k]);
|
| + for (let k = 0; k < actualResult.length; ++k) {
|
| + let diff = Math.abs(actualResult[k] - expectedResult[k]);
|
| if (maxDiff < diff) {
|
| maxDiff = diff;
|
| posn = k;
|
| }
|
| }
|
|
|
| - let prefix = "Curve length " + config.curveLength + ", duration " + config.curveDuration;
|
| - should(SNR, prefix + ": SNR")
|
| - .beGreaterThanOrEqualTo(config.snrThreshold);
|
| + let prefix = 'Curve length ' + config.curveLength + ', duration ' +
|
| + config.curveDuration;
|
| + should(SNR, prefix + ': SNR')
|
| + .beGreaterThanOrEqualTo(config.snrThreshold);
|
|
|
| - should(maxDiff, prefix + ": Max difference")
|
| - .beLessThanOrEqualTo(config.maxErrorThreshold);
|
| + should(maxDiff, prefix + ': Max difference')
|
| + .beLessThanOrEqualTo(config.maxErrorThreshold);
|
| }
|
| }
|
|
|
| // Compute the expected result based on the config settings.
|
| function computeExpectedResult(config) {
|
| - // The automation curve starts at |curveStartTime| and has duration |curveDuration|. So,
|
| - // the output should be zero until curveStartTime, linearly ramp up from there to
|
| - // |curveValue|, and then be constant 1 from then to the end of the buffer.
|
| + // The automation curve starts at |curveStartTime| and has duration
|
| + // |curveDuration|. So, the output should be zero until curveStartTime,
|
| + // linearly ramp up from there to |curveValue|, and then be constant 1
|
| + // from then to the end of the buffer.
|
|
|
| - var expected = new Float32Array(testDurationFrames);
|
| + let expected = new Float32Array(testDurationFrames);
|
|
|
| - var curveStartFrame = config.curveStartTime * sampleRate;
|
| - var curveEndFrame = (config.curveStartTime + config.curveDuration) * sampleRate;
|
| - var fullGainFrame = config.fullGainTime * sampleRate;
|
| + let curveStartFrame = config.curveStartTime * sampleRate;
|
| + let curveEndFrame =
|
| + (config.curveStartTime + config.curveDuration) * sampleRate;
|
| + let fullGainFrame = config.fullGainTime * sampleRate;
|
|
|
| - var k;
|
| + let k;
|
|
|
| - // Zero out the start.
|
| - for (k = 0; k < curveStartFrame; ++k)
|
| - expected[k] = 0;
|
| + // Zero out the start.
|
| + for (k = 0; k < curveStartFrame; ++k)
|
| + expected[k] = 0;
|
|
|
| - // Linearly ramp now. This assumes that the actual curve used is a linear ramp, even if
|
| - // there are many curve points.
|
| - var stepSize = curveValue / (config.curveDuration * sampleRate);
|
| - for (; k < curveEndFrame; ++k)
|
| - expected[k] = stepSize * (k - curveStartFrame);
|
| + // Linearly ramp now. This assumes that the actual curve used is a
|
| + // linear ramp, even if there are many curve points.
|
| + let stepSize = curveValue / (config.curveDuration * sampleRate);
|
| + for (; k < curveEndFrame; ++k)
|
| + expected[k] = stepSize * (k - curveStartFrame);
|
|
|
| - // Hold it constant until the next event
|
| - for (; k < fullGainFrame; ++k)
|
| - expected[k] = curveValue;
|
| + // Hold it constant until the next event
|
| + for (; k < fullGainFrame; ++k)
|
| + expected[k] = curveValue;
|
|
|
| - // Amplitude is one for the rest of the test.
|
| - for (; k < testDurationFrames; ++k)
|
| - expected[k] = 1;
|
| + // Amplitude is one for the rest of the test.
|
| + for (; k < testDurationFrames; ++k)
|
| + expected[k] = 1;
|
|
|
| - return expected;
|
| + return expected;
|
| }
|
|
|
| audit.run();
|
|
|