Bug 1438319 [wpt PR 9524] - Fix timeouts in WPT AudioParam tests, a=testonly

Automatic update from web-platform-testsFix timeouts in WPT AudioParam tests

Replace the tests that are using ScriptProcessor and online contexts
with an offline context and verify all the output values instead of
just one.

This change exposed a couple of issues:
  - setTargetAtTime wasn't actually testing setTargetAtTime because a
    linearRampToValueAtTime event was called at the same time,
    effectively replacing the setTargetAtTime event
  - linearRampToValue and exponentialRampToValue tests expose bugs in
    Chrome's implementation of these when the event is scheduled in
    the past, and there is no preceding event.

Bug: 812285, 626703
Change-Id: Iad3f54dd4373411431c019de44d4c3bad07587ff
Reviewed-on: https://chromium-review.googlesource.com/919151
Commit-Queue: Raymond Toy <rtoy@chromium.org>
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537311}

wpt-commits: 81ada4212ece1e2f5c6cc560d6b2f45593679e93
wpt-pr: 9524
wpt-commits: 81ada4212ece1e2f5c6cc560d6b2f45593679e93
wpt-pr: 9524
This commit is contained in:
Raymond Toy 2018-03-26 12:22:47 +00:00 коммит произвёл James Graham
Родитель c5582233ef
Коммит 04f728145f
7 изменённых файлов: 356 добавлений и 213 удалений

Просмотреть файл

@ -293336,6 +293336,11 @@
{}
]
],
"webaudio/the-audio-api/the-audioparam-interface/retrospective-test.js": [
[
{}
]
],
"webaudio/the-audio-api/the-audioprocessingevent-interface/.gitkeep": [
[
{}
@ -596445,25 +596450,29 @@
"testharness"
],
"webaudio/the-audio-api/the-audioparam-interface/retrospective-exponentialRampToValueAtTime.html": [
"53a2c031fd3c51cd401c1d192b09b745dd6b9260",
"12e1f35dca3f0b28d421ab39bdb2a98dc18abb3d",
"testharness"
],
"webaudio/the-audio-api/the-audioparam-interface/retrospective-linearRampToValueAtTime.html": [
"ebd5ea3d866634ff0958eb2fda96bf58cbbea6ad",
"30b41f51caaf643c1acd746be3a7ce19d2498ca1",
"testharness"
],
"webaudio/the-audio-api/the-audioparam-interface/retrospective-setTargetAtTime.html": [
"2fc8054f87b7d622b4cb5801e9f3a2083dbc23a4",
"2a012bfbd59445aa14789d80b94f514726e819f0",
"testharness"
],
"webaudio/the-audio-api/the-audioparam-interface/retrospective-setValueAtTime.html": [
"30bcf53f72c13690f606b1c27584e9bb937017ef",
"7558fec8601a9aa3a6fc8fc93c7e978a6bf50a9e",
"testharness"
],
"webaudio/the-audio-api/the-audioparam-interface/retrospective-setValueCurveAtTime.html": [
"fd40dc7cc8aca8ab829852dbabda3b00bcec5817",
"db939616369e2ce66b717d47512141e6f28e4c14",
"testharness"
],
"webaudio/the-audio-api/the-audioparam-interface/retrospective-test.js": [
"aeb2213183f2fd26848c507e030de3e5f7f01fee",
"support"
],
"webaudio/the-audio-api/the-audioparam-interface/setTargetAtTime-after-event-within-block.html": [
"3e54f9a98e7488223e6c40929268ddec3c8b5961",
"testharness"

Просмотреть файл

@ -1,51 +1,70 @@
<!doctype html>
<meta charset=utf-8>
<title>Test exponentialRampToValue with end time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
<html>
<head>
<title>Test exponentialRampToValue with end time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/webaudio/resources/audit-util.js"></script>
<script src="/webaudio/resources/audit.js"></script>
<script src="retrospective-test.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
var test = context.createGain();
test.gain.exponentialRampToValueAtTime(0.1, 0.5*context.currentTime);
test.gain.exponentialRampToValueAtTime(0.9, 2.0);
audit.define(
{
label: 'test',
description: 'Test exponentialRampToValue with end time in the past'
},
(task, should) => {
let {context, source, test, reference} = setupRetrospectiveGraph();
var reference = context.createGain();
reference.gain.exponentialRampToValueAtTime(0.1, context.currentTime);
reference.gain.exponentialRampToValueAtTime(0.9, 2.0);
// Suspend the context at this frame so we can synchronously set up
// automations.
const suspendFrame = 128;
source.connect(test);
source.connect(reference);
context.suspend(suspendFrame / context.sampleRate)
.then(() => {
// Call setTargetAtTime with a time in the past
test.gain.exponentialRampToValueAtTime(
0.1, 0.5 * context.currentTime);
test.gain.exponentialRampToValueAtTime(0.9, 1.0);
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
reference.gain.exponentialRampToValueAtTime(
0.1, context.currentTime);
reference.gain.exponentialRampToValueAtTime(0.9, 1.0);
})
.then(() => context.resume());
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
source.start();
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
context.startRendering()
.then(resultBuffer => {
let testValue = resultBuffer.getChannelData(0);
let referenceValue = resultBuffer.getChannelData(1);
assert_equals(testValue, referenceValue,
"value matches expected");
});
}
// Until the suspendFrame, both should be exactly equal to 1.
should(
testValue.slice(0, suspendFrame),
`Test[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
should(
referenceValue.slice(0, suspendFrame),
`Reference[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>
// After the suspendFrame, both should be equal (and not
// constant)
should(
testValue.slice(suspendFrame), `Test[${suspendFrame}:]`)
.beEqualToArray(referenceValue.slice(suspendFrame));
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -1,51 +1,70 @@
<!doctype html>
<meta charset=utf-8>
<title>Test linearRampToValue with end time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
<html>
<head>
<title>Test linearRampToValue with end time in the past</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit-util.js"></script>
<script src="/webaudio/resources/audit.js"></script>
<script src="retrospective-test.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
var test = context.createGain();
test.gain.linearRampToValueAtTime(0.1, 0.5*context.currentTime);
test.gain.linearRampToValueAtTime(0.9, 2.0);
audit.define(
{
label: 'test',
description: 'Test linearRampToValue with end time in the past'
},
(task, should) => {
let {context, source, test, reference} = setupRetrospectiveGraph();
var reference = context.createGain();
reference.gain.linearRampToValueAtTime(0.1, context.currentTime);
reference.gain.linearRampToValueAtTime(0.9, 2.0);
// Suspend the context at this frame so we can synchronously set up
// automations.
const suspendFrame = 128;
source.connect(test);
source.connect(reference);
context.suspend(suspendFrame / context.sampleRate)
.then(() => {
// Call setTargetAtTime with a time in the past
test.gain.linearRampToValueAtTime(
0.1, 0.5 * context.currentTime);
test.gain.linearRampToValueAtTime(0.9, 1.0);
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
reference.gain.linearRampToValueAtTime(
0.1, context.currentTime);
reference.gain.linearRampToValueAtTime(0.9, 1.0);
})
.then(() => context.resume());
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
source.start();
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
context.startRendering()
.then(resultBuffer => {
let testValue = resultBuffer.getChannelData(0);
let referenceValue = resultBuffer.getChannelData(1);
assert_equals(testValue, referenceValue,
"value matches expected");
});
}
// Until the suspendFrame, both should be exactly equal to 1.
should(
testValue.slice(0, suspendFrame),
`Test[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
should(
referenceValue.slice(0, suspendFrame),
`Reference[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>
// After the suspendFrame, both should be equal (and not
// constant)
should(
testValue.slice(suspendFrame), `Test[${suspendFrame}:]`)
.beEqualToArray(referenceValue.slice(suspendFrame));
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -1,51 +1,80 @@
<!doctype html>
<meta charset=utf-8>
<title>Test setTargetAtTime with start time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
<html>
<head>
<title>Test setTargetAtTime with start time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/webaudio/resources/audit-util.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
var test = context.createGain();
test.gain.setTargetAtTime(0.1, 0.5*context.currentTime, 0.1);
test.gain.linearRampToValueAtTime(0.9, 2.0);
audit.define(
{
label: 'test',
description: 'Test setTargetAtTime with start time in the past'
},
(task, should) => {
// Use a sample rate that is a power of two to eliminate round-off
// in computing the currentTime.
let context = new OfflineAudioContext(2, 16384, 16384);
let source = new ConstantSourceNode(context);
var reference = context.createGain();
reference.gain.setTargetAtTime(0.1, context.currentTime, 0.1);
reference.gain.linearRampToValueAtTime(0.9, 2.0);
// Suspend the context at this frame so we can synchronously set up
// automations.
const suspendFrame = 128;
source.connect(test);
source.connect(reference);
let test = new GainNode(context);
let reference = new GainNode(context);
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
source.connect(test);
source.connect(reference);
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
let merger = new ChannelMergerNode(
context, {numberOfInputs: context.destination.channelCount});
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
merger.connect(context.destination);
assert_equals(testValue, referenceValue,
"value matches expected");
});
}
context.suspend(suspendFrame / context.sampleRate)
.then(() => {
// Call setTargetAtTime with a time in the past
test.gain.setTargetAtTime(0.1, 0.5*context.currentTime, 0.1);
reference.gain.setTargetAtTime(0.1, context.currentTime, 0.1);
})
.then(() => context.resume());
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>
source.start();
context.startRendering()
.then(resultBuffer => {
let testValue = resultBuffer.getChannelData(0);
let referenceValue = resultBuffer.getChannelData(1);
// Until the suspendFrame, both should be exactly equal to 1.
should(
testValue.slice(0, suspendFrame),
`Test[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
should(
referenceValue.slice(0, suspendFrame),
`Reference[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
// After the suspendFrame, both should be equal (and not
// constant)
should(
testValue.slice(suspendFrame), `Test[${suspendFrame}:]`)
.beEqualToArray(referenceValue.slice(suspendFrame));
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -1,54 +1,74 @@
<!DOCTYPE html>
<title>Test setValueAtTime with startTime in the past</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
<html>
<head>
<title>Test setValueAtTime with startTime in the past</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit-util.js"></script>
<script src="/webaudio/resources/audit.js"></script>
<script src="retrospective-test.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
// Use a ramp of slope 1/sample to measure time.
// The end value is the extent of exact precision in single precision float.
const rampEnd = Math.pow(2, 24);
const rampEndSeconds = rampEnd / context.sampleRate;
var test = context.createGain();
test.gain.setValueAtTime(0.0, 0.5*context.currentTime);
test.gain.linearRampToValueAtTime(rampEnd, rampEndSeconds);
audit.define(
{
label: 'test',
description: 'Test setValueAtTime with startTime in the past'
},
(task, should) => {
let {context, source, test, reference} = setupRetrospectiveGraph();
var reference = context.createGain();
reference.gain.setValueAtTime(0.0, context.currentTime);
reference.gain.linearRampToValueAtTime(rampEnd, rampEndSeconds);
// Suspend the context at this frame so we can synchronously set up
// automations.
const suspendFrame = 128;
source.connect(test);
source.connect(reference);
// Use a ramp of slope 1 per frame to measure time.
// The end value is the extent of exact precision in single
// precision float.
const rampEnd = context.length - suspendFrame;
const rampEndSeconds = context.length / context.sampleRate;
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
context.suspend(suspendFrame / context.sampleRate)
.then(() => {
// Call setValueAtTime with a time in the past
test.gain.setValueAtTime(0.0, 0.5 * context.currentTime);
test.gain.linearRampToValueAtTime(rampEnd, rampEndSeconds);
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
reference.gain.setValueAtTime(0.0, context.currentTime);
reference.gain.linearRampToValueAtTime(
rampEnd, rampEndSeconds);
})
.then(() => context.resume());
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
source.start();
assert_equals(testValue, referenceValue,
"ramp value matches expected");
});
}
context.startRendering()
.then(resultBuffer => {
let testValue = resultBuffer.getChannelData(0);
let referenceValue = resultBuffer.getChannelData(1);
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>
// Until the suspendFrame, both should be exactly equal to 1.
should(
testValue.slice(0, suspendFrame),
`Test[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
should(
referenceValue.slice(0, suspendFrame),
`Reference[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
// After the suspendFrame, both should be equal (and not
// constant)
should(
testValue.slice(suspendFrame), `Test[${suspendFrame}:]`)
.beEqualToArray(referenceValue.slice(suspendFrame));
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -1,49 +1,67 @@
<!doctype html>
<meta charset=utf-8>
<title>Test SetValueCurve with start time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function do_test(t, context) {
var source = context.createConstantSource();
source.start();
<html>
<head>
<title>Test SetValueCurve with start time in the past</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="/webaudio/resources/audit-util.js"></script>
<script src="/webaudio/resources/audit.js"></script>
<script src="retrospective-test.js"></script>
</head>
</body>
<script>
let audit = Audit.createTaskRunner();
var test = context.createGain();
test.gain.setValueCurveAtTime(new Float32Array([1.0, 0.1]), 0.0, 1.0);
audit.define(
{
label: 'test',
description: 'Test SetValueCurve with start time in the past'
},
(task, should) => {
let {context, source, test, reference} = setupRetrospectiveGraph();
var reference = context.createGain();
reference.gain.setValueCurveAtTime(new Float32Array([1.0, 0.1]), 0.5*context.currentTime, 1.0);
// Suspend the context at this frame so we can synchronously set up
// automations.
const suspendFrame = 128;
source.connect(test);
source.connect(reference);
context.suspend(suspendFrame / context.sampleRate)
.then(() => {
// Call setValueAtTime with a time in the past
test.gain.setValueCurveAtTime(
new Float32Array([1.0, 0.1]), 0.5 * context.currentTime,
1.0);
reference.gain.setValueCurveAtTime(
new Float32Array([1.0, 0.1]), context.currentTime, 1.0);
})
.then(() => context.resume());
var merger = context.createChannelMerger();
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
source.start();
var processor = context.createScriptProcessor(0, 2, 0);
merger.connect(processor);
processor.onaudioprocess =
t.step_func_done((e) => {
source.stop();
processor.onaudioprocess = null;
context.startRendering()
.then(resultBuffer => {
let testValue = resultBuffer.getChannelData(0);
let referenceValue = resultBuffer.getChannelData(1);
var testValue = e.inputBuffer.getChannelData(0)[0];
var referenceValue = e.inputBuffer.getChannelData(1)[0];
// Until the suspendFrame, both should be exactly equal to 1.
should(
testValue.slice(0, suspendFrame),
`Test[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
should(
referenceValue.slice(0, suspendFrame),
`Reference[0:${suspendFrame - 1}]`)
.beConstantValueOf(1);
assert_equals(testValue, referenceValue,
"value matches expected");
});
}
// After the suspendFrame, both should be equal (and not
// constant)
should(
testValue.slice(suspendFrame), `Test[${suspendFrame}:]`)
.beEqualToArray(referenceValue.slice(suspendFrame));
})
.then(() => task.done());
});
async_test(function(t) {
var context = new AudioContext;
(function waitForTimeAdvance() {
if (context.currentTime == 0) {
t.step_timeout(waitForTimeAdvance, 0);
} else {
do_test(t, context);
}
})();
});
</script>
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,29 @@
// Create an audio graph on an offline context that consists of a
// constant source and two gain nodes. One of the nodes is the node te
// be tested and the other is the reference node. The output from the
// test node is in channel 0 of the offline context; the reference
// node is in channel 1.
//
// Returns a dictionary with the context, source node, the test node,
// and the reference node.
function setupRetrospectiveGraph() {
// Use a sample rate that is a power of two to eliminate round-off
// in computing the currentTime.
let context = new OfflineAudioContext(2, 16384, 16384);
let source = new ConstantSourceNode(context);
let test = new GainNode(context);
let reference = new GainNode(context);
source.connect(test);
source.connect(reference);
let merger = new ChannelMergerNode(
context, {numberOfInputs: context.destination.channelCount});
test.connect(merger, 0, 0);
reference.connect(merger, 0, 1);
merger.connect(context.destination);
return {context: context, source: source, test: test, reference: reference};
}