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(); |