Commit b8f7147a authored by Raymond Toy's avatar Raymond Toy Committed by Commit Bot

Fix flaky k-rate-panner test

Change the testing scheme for k-rate panner to verify that the output
is piecewise constant for a constant source when the automation rate
is set to k-rate. Reduce the duration of the test as well; Just a few
render quanta is enough to verify that the output is piece-wise constant
and different from the a-rate output.

Also updated k-rate-constant-source.html to use the same doTest method
since the special case is supported.

Didn't actually figure out the underlying flakiness of the original
test.

Bug: 841856
Change-Id: I8e9807e530fc3b1452bae521a2660be3fbe104f9
Reviewed-on: https://chromium-review.googlesource.com/1076809Reviewed-by: default avatarHongchan Choi <hongchan@chromium.org>
Commit-Queue: Raymond Toy <rtoy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568100}
parent 95c0df9a
......@@ -2,6 +2,12 @@
//
// |options| describes how the testing of the AudioParam should be done:
//
// sourceNodeName: name of source node to use for testing; defaults to
// 'OscillatorNode'. If set to 'none', then no source node
// is created for testing and it is assumed that the AudioNode
// under test are sources and need to be started.
// verifyPieceWiseConstant: if true, verify that the k-rate output is
// piecewise constant for each render quantum.
// nodeName: name of the AudioNode to be tested
// nodeOptions: options to be used in the AudioNode constructor
//
......@@ -42,7 +48,14 @@ function doTest(context, should, options) {
context, {numberOfInputs: context.destination.numberOfChannels});
merger.connect(context.destination);
let src = new OscillatorNode(context);
let src = null;
// Skip creating a source to drive the graph if |sourceNodeName| is 'none'.
// If |sourceNodeName| is given, use that, else default to OscillatorNode.
if (options.sourceNodeName !== 'none') {
src = new window[options.sourceNodeName || 'OscillatorNode'](context);
}
let kRateNode = new window[options.nodeName](context, options.nodeOptions);
let aRateNode = new window[options.nodeName](context, options.nodeOptions);
let inverter = new GainNode(context, {gain: -1});
......@@ -81,16 +94,30 @@ function doTest(context, should, options) {
});
});
// Connect the source, if specified.
if (src) {
src.connect(kRateNode);
src.connect(aRateNode);
}
// The k-rate result is channel 0, and the a-rate result is channel 1.
src.connect(kRateNode).connect(merger, 0, 0);
src.connect(aRateNode).connect(merger, 0, 1);
kRateNode.connect(merger, 0, 0);
aRateNode.connect(merger, 0, 1);
// Compute the difference between the a-rate and k-rate results and send
// that to channel 2.
kRateNode.connect(merger, 0, 2);
aRateNode.connect(inverter).connect(merger, 0, 2);
src.start();
if (src) {
src.start();
} else {
// If there's no source, then assume the test nodes are sources and start
// them.
kRateNode.start();
aRateNode.start();
}
return context.startRendering().then(renderedBuffer => {
let kRateOutput = renderedBuffer.getChannelData(0);
let aRateOutput = renderedBuffer.getChannelData(1);
......@@ -113,5 +140,16 @@ function doTest(context, should, options) {
options.prefix
}: Difference between a-rate and k-rate ${options.nodeName}`)
.notBeConstantValueOf(0);
if (options.verifyPieceWiseConstant) {
// Verify that the output from the k-rate parameter is step-wise
// constant.
for (let k = 0; k < kRateOutput.length; k += 128) {
should(
kRateOutput.slice(k, k + 128),
`${options.prefix} k-rate output [${k}: ${k + 127}]`)
.beConstantValueOf(kRateOutput[k]);
}
}
});
}
......@@ -6,6 +6,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit-util.js"></script>
<script src="/webaudio/resources/audit.js"></script>
<script src="automation-rate-testing.js"></script>
</head>
<body>
......@@ -25,54 +26,22 @@
length: testDuration * sampleRate
});
let merger = new ChannelMergerNode(
context, {numberOfInputs: context.numberOfChannels});
merger.connect(context.destination);
let inverter = new GainNode(context, {gain: -1});
inverter.connect(merger, 0, 2);
let kRateNode = new ConstantSourceNode(context);
let aRateNode = new ConstantSourceNode(context);
kRateNode.connect(merger, 0, 0);
aRateNode.connect(merger, 0, 1);
kRateNode.connect(merger, 0, 2);
aRateNode.connect(inverter);
// Set the rate
kRateNode.offset.automationRate = 'k-rate';
// Automate the offset
kRateNode.offset.setValueAtTime(0, 0);
kRateNode.offset.linearRampToValueAtTime(10, testDuration);
aRateNode.offset.setValueAtTime(0, 0);
aRateNode.offset.linearRampToValueAtTime(10, testDuration);
kRateNode.start();
aRateNode.start();
context.startRendering()
.then(audioBuffer => {
let kRateOut = audioBuffer.getChannelData(0);
let aRateOut = audioBuffer.getChannelData(1);
let diff = audioBuffer.getChannelData(2);
// Verify that the outputs are different.
should(diff, 'Difference between a-rate and k-rate outputs')
.notBeConstantValueOf(0);
// Verify that the constant source node output is step-wise
// constant.
for (let k = 0; k < kRateOut.length; k += 128) {
should(
kRateOut.slice(k, k + 128),
`k-rate output [${k}: ${k + 127}]`)
.beConstantValueOf(kRateOut[k]);
doTest(context, should, {
sourceNodeName: 'none',
verifyPieceWiseConstant: true,
nodeName: 'ConstantSourceNode',
prefix: 'k-rate offset',
rateSettings: [{name: 'offset', value: 'k-rate'}],
automations: [{
name: 'offset',
methods: [
{name: 'setValueAtTime', options: [0, 0]}, {
name: 'linearRampToValueAtTime',
options: [10, testDuration]
}
})
.then(() => task.done());
]
}]
}).then(() => task.done());
});
audit.run();
......
......@@ -23,14 +23,14 @@
[{name: 'positionX', initial: 0, final: 1000},
{name: 'positionY', initial: 0, final: 1000},
{name: 'orientationX', initial: .1, final: 1000},
{name: 'orientationY', initial: .1, final: 1000},
{name: 'orientationZ', initial: .1, final: 1000},
{name: 'orientationX', initial: 1, final: 10},
{name: 'orientationY', initial: 1, final: 10},
{name: 'orientationZ', initial: 1, final: 10},
].forEach(paramProperty => {
audit.define('Panner k-rate ' + paramProperty.name, (task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
let testDuration = 1;
let testDuration = 5 * 128 / sampleRate;
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
......@@ -38,6 +38,8 @@
});
doTest(context, should, {
sourceNodeName: 'ConstantSourceNode',
verifyPieceWiseConstant: true,
nodeName: 'PannerNode',
// Make the source directional so orientation matters, and set some
// defaults for the position and orientation so that we're not on an
......@@ -46,11 +48,11 @@
nodeOptions: {
distanceModel: 'inverse',
coneOuterAngle: 360,
coneInnerAngle: 10,
positionX: 10,
positionY: 10,
positionZ: 10,
orientationX: 1,
coneInnerAngle: 0,
positionX: 1,
positionY: 1,
positionZ: 1,
orientationX: 0,
orientationY: 1,
orientationZ: 1
},
......
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