blob: 1db0827937c829e0c525ad3b821e070fb6da8ea6 [file] [log] [blame]
<!doctype html>
<html>
<head>
<script src="../resources/js-test.js"></script>
<script src="resources/compatibility.js"></script>
<script src="resources/audio-testing.js"></script>
<script src="resources/audioparam-testing.js"></script>
<title>AudioParam Initial Events </title>
</head>
<body>
<script>
description("Test Automation Ramps without Initial Event");
window.jsTestIsAsync = true;
var sampleRate = 48000;
// Number of frames in a rendering quantum.
var quantumFrames = 128;
// Test doesn't need to run for very long.
var renderDuration = 0.2;
var renderFrames = renderDuration * sampleRate;
var automationEndTime = 0.1;
var audit = Audit.createTaskRunner();
// The following tests start a ramp automation without an initial event. This should cause an
// initial event to be added implicitly to give a starting point.
audit.defineTask("linear-ramp", function (done) {
runTest("Linear ramp", {
automationFunction: function (node, value, time) {
node.gain.linearRampToValueAtTime(value, time);
},
referenceFunction: linearRamp,
// Experimentally determined threshold
threshold: 6.0003e-8,
// The starting value of the gain node
v0: 0.5,
// The target value of the automation
v1: 0,
})
.then(done);
});
audit.defineTask("exponential-ramp", function (done) {
runTest("Exponential ramp", {
automationFunction: function (node, value, time) {
node.gain.exponentialRampToValueAtTime(value, time);
},
referenceFunction: exponentialRamp,
threshold: 2.3842e-6,
v0: 0.5,
v1: 2,
})
.then(done);
});
// Same tests as above, but we delay the call to the automation function. This is to verify that
// the we still do the right thing after the context has started.
audit.defineTask("delayed-linear-ramp", function (done) {
runTest("Delayed linear ramp", {
automationFunction: function (node, value, time) {
node.gain.linearRampToValueAtTime(value, time);
},
referenceFunction: linearRamp,
// Experimentally determined threshold
threshold: 9.87968e-8,
// The starting value of the gain node
v0: 0.5,
// The target value of the automation
v1: 0,
delay: quantumFrames / sampleRate
})
.then(done);
});
audit.defineTask("delayed-exponential-ramp", function (done) {
runTest("Delayed exponential ramp", {
automationFunction: function (node, value, time) {
node.gain.exponentialRampToValueAtTime(value, time);
},
referenceFunction: exponentialRamp,
// Experimentally determined threshold
threshold: 1.3948e-5,
// The starting value of the gain node
v0: 0.5,
// The target value of the automation
v1: 2,
delay: quantumFrames / sampleRate
})
.then(done);
});
audit.defineTask("finish", function (done) {
finishJSTest();
done();
});
audit.runTasks();
// Generate the expected waveform for a linear ramp starting from the value |v0|, ramping to
// |v1| at time |endTime|. The time of |v0| is assumed to be 0. |nFrames| is how many frames
// to generate.
function linearRamp(v0, v1, startTime, endTime, nFrames) {
var expected = createLinearRampArray(startTime, endTime, v0, v1, sampleRate);
var preFiller = new Array(Math.floor(startTime * sampleRate));
var postFiller = new Array(nFrames - Math.ceil(endTime * sampleRate));
preFiller.fill(v0);
return preFiller.concat(expected.concat(postFiller.fill(v1)));
}
// Generate the expected waveform for an exponential ramp starting from the value |v0|,
// ramping to |v1| at time |endTime|. The time of |v0| is assumed to be 0. |nFrames| is how
// many frames to generate.
function exponentialRamp(v0, v1, startTime, endTime, nFrames) {
var expected = createExponentialRampArray(startTime, endTime, v0, v1, sampleRate);
var preFiller = new Array(Math.floor(startTime * sampleRate));
preFiller.fill(v0);
var postFiller = new Array(nFrames - Math.ceil(endTime * sampleRate));
return preFiller.concat(expected.concat(postFiller.fill(v1)));
}
// Run an automation test. |message| is the message to use for printing the results. |options|
// is a property bag containing the configuration of the test including the following:
//
// automationFunction - automation function to use,
// referenceFunction - function generating the expected result
// threshold - comparison threshold
// v0 - starting value
// v1 - end value for automation
function runTest(message, options) {
var automationFunction = options.automationFunction;
var referenceFunction = options.referenceFunction;
var threshold = options.threshold;
var v0 = options.v0;
var v1 = options.v1;
var delay = options.delay;
var context = new OfflineAudioContext(1, renderFrames, sampleRate);
// A constant source of amplitude 1.
var source = context.createBufferSource();
source.buffer = createConstantBuffer(context, 1, 1);
source.loop = true;
// Automation is applied to a gain node
var gain = context.createGain();
gain.gain.value = v0;
// Delay start of automation, if requested
if (delay) {
context.suspend(options.delay).then(function () {
automationFunction(gain, v1, automationEndTime);
context.resume();
});
} else {
automationFunction(gain, v1, automationEndTime);
}
source.connect(gain);
gain.connect(context.destination);
source.start();
return context.startRendering()
.then(function (resultBuffer) {
var result = resultBuffer.getChannelData(0);
var expected = referenceFunction(v0, v1, delay ? delay : 0, automationEndTime, renderFrames);
Should(message, result).beCloseToArray(expected, threshold);
});
}
</script>
</body>
</html>