mirror of
https://github.com/servo/servo.git
synced 2025-07-13 10:23:40 +01:00
144 lines
5.2 KiB
HTML
144 lines
5.2 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<title>Adding Events</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="/webaudio/resources/audio-param.js"></script>
|
|
</head>
|
|
|
|
<body>
|
|
<script>
|
|
let audit = Audit.createTaskRunner();
|
|
|
|
// Arbitrary power of two to eliminate round-off in computing time from
|
|
// frame.
|
|
const sampleRate = 8192;
|
|
|
|
audit.define(
|
|
{
|
|
label: 'linearRamp',
|
|
description: 'Insert linearRamp after running for some time'
|
|
},
|
|
(task, should) => {
|
|
testInsertion(should, {
|
|
method: 'linearRampToValueAtTime',
|
|
prefix: 'linearRamp'
|
|
}).then(() => task.done());
|
|
});
|
|
|
|
audit.define(
|
|
{
|
|
label: 'expoRamp',
|
|
description: 'Insert expoRamp after running for some time'
|
|
},
|
|
(task, should) => {
|
|
testInsertion(should, {
|
|
method: 'exponentialRampToValueAtTime',
|
|
prefix: 'expoRamp'
|
|
}).then(() => task.done());
|
|
});
|
|
|
|
// Test insertion of an event in the middle of rendering.
|
|
//
|
|
// options dictionary:
|
|
// method - automation method to test
|
|
// prefix - string to use for prefixing messages
|
|
function testInsertion(should, options) {
|
|
let {method, prefix} = options;
|
|
|
|
// Channel 0 is the output for the test, and channel 1 is the
|
|
// reference output.
|
|
let context = new OfflineAudioContext(
|
|
{numberOfChannels: 2, length: sampleRate, sampleRate: sampleRate});
|
|
let merger = new ChannelMergerNode(
|
|
context, {numberOfChannels: context.destination.channelCount});
|
|
|
|
merger.connect(context.destination);
|
|
|
|
// Initial value and final values of the source node
|
|
let initialValue = 1;
|
|
let finalValue = 2;
|
|
|
|
// Set up the node for the automations under test
|
|
let src = new ConstantSourceNode(context, {offset: initialValue});
|
|
src.connect(merger, 0, 0);
|
|
|
|
// Set initial event to occur at this time. Keep it in the first
|
|
// render quantum.
|
|
const initialEventTime = 64 / context.sampleRate;
|
|
should(
|
|
() => src.offset.setValueAtTime(initialValue, initialEventTime),
|
|
`${prefix}: setValueAtTime(${initialValue}, ${initialEventTime})`)
|
|
.notThrow();
|
|
|
|
// Let time pass and then add a new event with time in the future.
|
|
let insertAtFrame = 512;
|
|
let insertTime = insertAtFrame / context.sampleRate;
|
|
let automationEndFrame = 1024 + 64;
|
|
let automationEndTime = automationEndFrame / context.sampleRate;
|
|
context.suspend(insertTime)
|
|
.then(() => {
|
|
should(
|
|
() => src.offset[method](finalValue, automationEndTime),
|
|
`${prefix}: At time ${insertTime} scheduling ${method}(${
|
|
finalValue}, ${automationEndTime})`)
|
|
.notThrow();
|
|
})
|
|
.then(() => context.resume());
|
|
|
|
// Set up graph for the reference result. Automate the source with
|
|
// the events scheduled from the beginning. Let the gain node
|
|
// simulate the insertion of the event above. This is done by
|
|
// setting the gain to 1 at the insertion time.
|
|
let srcRef = new ConstantSourceNode(context, {offset: 1});
|
|
let g = new GainNode(context, {gain: 0});
|
|
srcRef.connect(g).connect(merger, 0, 1);
|
|
srcRef.offset.setValueAtTime(initialValue, initialEventTime);
|
|
srcRef.offset[method](finalValue, automationEndTime);
|
|
|
|
// Allow everything through after |insertFrame| frames.
|
|
g.gain.setValueAtTime(1, insertTime);
|
|
|
|
// Go!
|
|
src.start();
|
|
srcRef.start();
|
|
|
|
return context.startRendering().then(audioBuffer => {
|
|
let actual = audioBuffer.getChannelData(0);
|
|
let expected = audioBuffer.getChannelData(1);
|
|
|
|
// Verify that the output is 1 until we reach
|
|
// insertAtFrame. Ignore the expected data because that always
|
|
// produces 1.
|
|
should(
|
|
actual.slice(0, insertAtFrame),
|
|
`${prefix}: output[0:${insertAtFrame - 1}]`)
|
|
.beConstantValueOf(initialValue);
|
|
|
|
// Verify ramp is correct by comparing it to the expected
|
|
// data.
|
|
should(
|
|
actual.slice(
|
|
insertAtFrame, automationEndFrame - insertAtFrame + 1),
|
|
`${prefix}: output[${insertAtFrame}:${
|
|
automationEndFrame - insertAtFrame}]`)
|
|
.beCloseToArray(
|
|
expected.slice(
|
|
insertAtFrame, automationEndFrame - insertAtFrame + 1),
|
|
{absoluteThreshold: 0, numberOfArrayElements: 0});
|
|
|
|
// Verify final output has the expected value
|
|
should(
|
|
actual.slice(automationEndFrame),
|
|
`${prefix}: output[${automationEndFrame}:]`)
|
|
.beConstantValueOf(finalValue);
|
|
})
|
|
}
|
|
|
|
audit.run();
|
|
</script>
|
|
</body>
|
|
</html>
|