Commit 9f2135a5 authored by rtoy's avatar rtoy Committed by Commit bot

Allow timeConstant=0 for setTargetAtTime

setTargetAtTime should allow a time constant of 0.  This means the
output value jumps instantaneously to the target value at the start
time.

Spec: https://webaudio.github.io/web-audio-api/#widl-AudioParam-setTargetAtTime-AudioParam-float-target-double-startTime-float-timeConstant

BUG=630869
TEST=audioparam-setTarget-timeConstant-0.html,
     audiparam-exceptional-values.html

Remove test for timeConstant=0.

Review-Url: https://codereview.chromium.org/2426893003
Cr-Commit-Position: refs/heads/master@{#437614}
parent 497fd7f2
...@@ -31,8 +31,7 @@ PASS gain.gain.setValueAtTime(1, NaN) threw exception TypeError: Failed to execu ...@@ -31,8 +31,7 @@ PASS gain.gain.setValueAtTime(1, NaN) threw exception TypeError: Failed to execu
PASS gain.gain.linearRampToValueAtTime(1, NaN) threw exception TypeError: Failed to execute 'linearRampToValueAtTime' on 'AudioParam': The provided double value is non-finite.. PASS gain.gain.linearRampToValueAtTime(1, NaN) threw exception TypeError: Failed to execute 'linearRampToValueAtTime' on 'AudioParam': The provided double value is non-finite..
PASS gain.gain.exponentialRampToValueAtTime(1, NaN) threw exception TypeError: Failed to execute 'exponentialRampToValueAtTime' on 'AudioParam': The provided double value is non-finite.. PASS gain.gain.exponentialRampToValueAtTime(1, NaN) threw exception TypeError: Failed to execute 'exponentialRampToValueAtTime' on 'AudioParam': The provided double value is non-finite..
PASS gain.gain.setTargetAtTime(1, NaN, 1) threw exception TypeError: Failed to execute 'setTargetAtTime' on 'AudioParam': The provided double value is non-finite.. PASS gain.gain.setTargetAtTime(1, NaN, 1) threw exception TypeError: Failed to execute 'setTargetAtTime' on 'AudioParam': The provided double value is non-finite..
PASS gain.gain.setTargetAtTime(1, 1, -1) threw exception InvalidAccessError: Failed to execute 'setTargetAtTime' on 'AudioParam': Time constant must be a finite positive number: -1. PASS gain.gain.setTargetAtTime(1, 1, -1) threw exception InvalidAccessError: Failed to execute 'setTargetAtTime' on 'AudioParam': Time constant must be a finite non-negative number: -1.
PASS gain.gain.setTargetAtTime(1, 1, 0) threw exception InvalidAccessError: Failed to execute 'setTargetAtTime' on 'AudioParam': Time constant must be a finite positive number: 0.
PASS gain.gain.setTargetAtTime(1, 1, Infinity) threw exception TypeError: Failed to execute 'setTargetAtTime' on 'AudioParam': The provided double value is non-finite.. PASS gain.gain.setTargetAtTime(1, 1, Infinity) threw exception TypeError: Failed to execute 'setTargetAtTime' on 'AudioParam': The provided double value is non-finite..
PASS gain.gain.setTargetAtTime(1, 1, -Infinity) threw exception TypeError: Failed to execute 'setTargetAtTime' on 'AudioParam': The provided double value is non-finite.. PASS gain.gain.setTargetAtTime(1, 1, -Infinity) threw exception TypeError: Failed to execute 'setTargetAtTime' on 'AudioParam': The provided double value is non-finite..
PASS gain.gain.setTargetAtTime(1, 1, NaN) threw exception TypeError: Failed to execute 'setTargetAtTime' on 'AudioParam': The provided double value is non-finite.. PASS gain.gain.setTargetAtTime(1, 1, NaN) threw exception TypeError: Failed to execute 'setTargetAtTime' on 'AudioParam': The provided double value is non-finite..
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
// For these timeConstant values for setTargetAtTime an error must be thrown because they are // For these timeConstant values for setTargetAtTime an error must be thrown because they are
// invalid. // invalid.
var timeConstantValues = [-1, 0, Infinity, -Infinity, NaN]; var timeConstantValues = [-1, Infinity, -Infinity, NaN];
// Just an array for use by setValueCurveAtTime. The length and contents of the array are not // Just an array for use by setValueCurveAtTime. The length and contents of the array are not
// important. // important.
......
<!doctype html>
<html>
<head>
<title>Test setTargetAtTime with timeConstant=0</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="resources/audio-testing.js"></script>
</head>
<body>
<script>
// Fairly arbitrary sample rate and number of frames, so choose a low
// sample rate, and short rendering length.
var sampleRate = 8000;
var renderFrames = 128;
// Array specifying parameters for setTargetAtTime. |frame| is the frame
// (not necessarily an integer) at which setTargetAtTime starts, and
// |value| is the target value. Non-integral values for |frame| tests
// that we started the setTargetAtTime at the right time.
var targetValueInfo = [{
frame: 10.1,
value: 0
}, {
frame: 20.3,
value: 0.5
}, {
frame: 100.5,
value: 1
}];
var audit = Audit.createTaskRunner();
audit.defineTask("timeconstant-0", function (taskDone) {
var context = new OfflineAudioContext(1, renderFrames, sampleRate);
// Simple constant source for testing.
var src = new ConstantSourceNode(context);
// We're going to automate the gain node to test setTargetAtTime.
var gain = new GainNode(context, {
gain: 1
});
src.connect(gain).connect(context.destination);
for (var k = 0; k < targetValueInfo.length; ++k) {
gain.gain.setTargetAtTime(
targetValueInfo[k].value,
targetValueInfo[k].frame / context.sampleRate,
0);
}
src.start();
context.startRendering().then(function (resultBuffer) {
var result = resultBuffer.getChannelData(0);
var success = true;
// Because the time constant is 0, the automation should instantly
// jump to the target value at the start time. Verify that the output
// has the expected value.
for (var k = 0; k < targetValueInfo.length; ++k) {
var startFrame = Math.ceil(targetValueInfo[k].frame);
var endFrame = k < targetValueInfo.length - 1 ?
Math.ceil(targetValueInfo[k + 1].frame) : renderFrames;
var value = targetValueInfo[k].value;
success = Should(
"Output for frame [" + startFrame + ", " + endFrame +
")",
result.slice(startFrame, endFrame))
.beConstantValueOf(value) && success;
}
Should("setTargetAtTime with timeConstant=0", success)
.summarize(
"handled correctly",
"handled incorrectly");
}).then(taskDone);
});
audit.runTasks();
</script>
</body>
</html>
...@@ -165,6 +165,10 @@ AudioParamTimeline::ParamEvent ...@@ -165,6 +165,10 @@ AudioParamTimeline::ParamEvent
AudioParamTimeline::ParamEvent::createSetTargetEvent(float value, AudioParamTimeline::ParamEvent::createSetTargetEvent(float value,
double time, double time,
double timeConstant) { double timeConstant) {
// The time line code does not expect a timeConstant of 0. (IT
// returns NaN or Infinity due to division by zero. The caller
// should have converted this to a SetValueEvent.
DCHECK_NE(timeConstant, 0);
return ParamEvent(ParamEvent::SetTarget, value, time, timeConstant, 0, return ParamEvent(ParamEvent::SetTarget, value, time, timeConstant, 0,
nullptr); nullptr);
} }
...@@ -237,11 +241,18 @@ void AudioParamTimeline::setTargetAtTime(float target, ...@@ -237,11 +241,18 @@ void AudioParamTimeline::setTargetAtTime(float target,
DCHECK(isMainThread()); DCHECK(isMainThread());
if (!isNonNegativeAudioParamTime(time, exceptionState) || if (!isNonNegativeAudioParamTime(time, exceptionState) ||
!isPositiveAudioParamTime(timeConstant, exceptionState, "Time constant")) !isNonNegativeAudioParamTime(timeConstant, exceptionState,
"Time constant"))
return; return;
insertEvent(ParamEvent::createSetTargetEvent(target, time, timeConstant), // If timeConstant = 0, we instantly jump to the target value, so
exceptionState); // insert a SetValueEvent instead of SetTargetEvent.
if (timeConstant == 0) {
insertEvent(ParamEvent::createSetValueEvent(target, time), exceptionState);
} else {
insertEvent(ParamEvent::createSetTargetEvent(target, time, timeConstant),
exceptionState);
}
} }
void AudioParamTimeline::setValueCurveAtTime(DOMFloat32Array* curve, void AudioParamTimeline::setValueCurveAtTime(DOMFloat32Array* curve,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment