blob: 5ede1750bd718eaad2df5d5fb4ff91358acb2551 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<title>
Test Automation Following setValueCurveAtTime Automations
</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../resources/audit-util.js"></script>
<script src="../resources/audit.js"></script>
<script src="../resources/audio-param.js"></script>
</head>
<body>
<script id="layout-test-code">
let sampleRate = 12800;
// Some short duration because we don't need to run the test for very
// long.
let testDurationFrames = 256;
let testDurationSec = testDurationFrames / sampleRate;
let curveDuration = testDurationSec / 2;
let audit = Audit.createTaskRunner();
// Configuration for each test.
//
// Required options:
// automation - Name of automation method to test
// time - Time for the automation method.
// Optional options:
// extraDuration - extra time for the duration of the setValueCurve
// duration. Default is 0. This should not be on a
// sample frame boundary. This is for testing that
// curves that don't end on a frame boundary are handled
// correctly.
// threshold - Error threshold for the test; default is 0.
let testConfigs = [
{
automation: 'linearRampToValueAtTime',
time: testDurationSec,
threshold: 3.9737e-8
},
{
automation: 'linearRampToValueAtTime',
time: testDurationSec,
extraDuration: 0.5 / sampleRate,
threshold: 1.8141e-8
},
{
automation: 'exponentialRampToValueAtTime',
time: testDurationSec,
threshold: 3.9737e-8
},
{
automation: 'exponentialRampToValueAtTime',
time: testDurationSec,
extraDuration: 0.5 / sampleRate,
threshold: 7.8294e-8
},
{
automation: 'setTargetAtTime',
time: curveDuration,
threshold: 1.5895e-7
},
{
automation: 'setTargetAtTime',
time: curveDuration + 0.5 / sampleRate,
extraDuration: 0.5 / sampleRate,
threshold: 1.3278e-7
}
];
// Define tests from the configs
for (k in testConfigs) {
audit.define(k + ': ' + testConfigs[k].automation, (function(config) {
return (task, should) => {
runTest(should, config).then(() => task.done());
};
})(testConfigs[k]));
}
audit.run();
function runTest(should, options) {
// For the test, use a gain node with a constant input to test the
// automations.
let context =
new OfflineAudioContext(1, testDurationFrames, sampleRate);
let source = context.createBufferSource();
source.buffer = createConstantBuffer(context, 1, 1);
source.loop = true;
let gain = context.createGain();
// Any valid curve is ok. We only use the last value for testing.
let curve = [0, 2, 0.3];
let actualDuration = curveDuration + (options.extraDuration || 0);
gain.gain.setValueCurveAtTime(
Float32Array.from(curve), 0, actualDuration);
// Run the desired test automation. The extra parameter (0.01) is only
// used for setTargetAtTime tests; it's ignored for other tests.
let automationValue = 2;
gain.gain[options.automation](automationValue, options.time, 0.01);
source.connect(gain);
gain.connect(context.destination);
source.start();
return context.startRendering().then(function(resultBuffer) {
let result = resultBuffer.getChannelData(0);
// Only need to verify that the ramp started at the right
// value. Figure the nearest sample frame to the end curve.
let curveEndFrame = Math.ceil(actualDuration * sampleRate);
let expectedResult = curve[curve.length - 1];
// Determine the expected value after the end of the setValueCurve
// event.
if (options.automation == 'linearRampToValueAtTime') {
expectedResult = audioParamLinearRamp(
curveEndFrame / sampleRate, curve[curve.length - 1],
actualDuration, automationValue, testDurationSec);
} else if (options.automation == 'exponentialRampToValueAtTime') {
expectedResult = audioParamExponentialRamp(
curveEndFrame / sampleRate, curve[curve.length - 1],
actualDuration, automationValue, testDurationSec);
} else if (options.automation == 'setTargetAtTime') {
expectedResult = audioParamSetTarget(
curveEndFrame / sampleRate, curve[curve.length - 1],
actualDuration, automationValue, 0.01);
}
let message = 'setValueCurve(..., ' + 0 + ', ' + actualDuration +
').' + options.automation + '(2, ' + testDurationSec;
if (options.automation == 'setTargetAtTime')
message += ', 0.01';
message += ')';
should(
result[curveEndFrame],
message + ': value at time ' + curveEndFrame / sampleRate)
.beCloseTo(expectedResult, {threshold: options.threshold || 0});
});
}
function linearRampValue(t, t0, v0, t1, v1) {
return v0 + (v1 - v0) * (t - t0) / (t1 - t0);
}
function exponentialRampValue(t, t0, v0, t1, v1) {
return v0 * Math.pow(v1 / v0, (t - t0) / (t1 - t0));
}
function setTargetValue(t, t0, v0, v1, timeConstant) {
return v1 + (v0 - v1) * Math.exp(-(t - t0) / timeConstant)
}
</script>
</body>
</html>