Update web-platform-tests to revision 5084587f6b05bf99ad09e7844be66dcc61070cdf

This commit is contained in:
WPT Sync Bot 2018-04-25 21:10:30 -04:00 committed by Anthony Ramine
parent 6d42d2f1e8
commit 7d1071a6a4
408 changed files with 8968 additions and 2608 deletions

View file

@ -0,0 +1,117 @@
// Test k-rate vs a-rate AudioParams.
//
// |options| describes how the testing of the AudioParam should be done:
//
// nodeName: name of the AudioNode to be tested
// nodeOptions: options to be used in the AudioNode constructor
//
// prefix: Prefix for all output messages (to make them unique for
// testharness)
//
// rateSettings: A vector of dictionaries specifying how to set the automation
// rate(s):
// name: Name of the AudioParam
// value: The automation rate for the AudioParam given by |name|.
//
// automations: A vector of dictionaries specifying how to automate each
// AudioParam:
// name: Name of the AudioParam
//
// methods: A vector of dictionaries specifying the automation methods to
// be used for testing:
// name: Automation method to call
// options: Arguments for the automation method
//
// Testing is somewhat rudimentary. We create two nodes of the same type. One
// node uses the default automation rates for each AudioParam (expecting them to
// be a-rate). The second node sets the automation rate of AudioParams to
// "k-rate". The set is speciified by |options.rateSettings|.
//
// For both of these nodes, the same set of automation methods (given by
// |options.automations|) is applied. A simple oscillator is connected to each
// node which in turn are connected to different channels of an offline context.
// Channel 0 is the k-rate node output; channel 1, the a-rate output; and
// channel 3, the difference between the outputs.
//
// Success is declared if the difference signal is not exactly zero. This means
// the the automations did different things, as expected.
//
// The promise from |startRendering| is returned.
function doTest(context, should, options) {
let merger = new ChannelMergerNode(
context, {numberOfInputs: context.destination.numberOfChannels});
merger.connect(context.destination);
let src = new 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});
// Set kRateNode filter to use k-rate params.
options.rateSettings.forEach(setting => {
kRateNode[setting.name].automationRate = setting.value;
// Mostly for documentation in the output. These should always
// pass.
should(
kRateNode[setting.name].automationRate,
`${options.prefix}: Setting ${
setting.name
}.automationRate to "${setting.value}"`)
.beEqualTo(setting.value);
});
// Run through all automations for each node separately. (Mostly to keep
// output of automations together.)
options.automations.forEach(param => {
param.methods.forEach(method => {
// Most for documentation in the output. These should never throw.
let message = `${param.name}.${method.name}(${method.options})`
should(() => {
kRateNode[param.name][method.name](...method.options);
}, options.prefix + ': k-rate node: ' + message).notThrow();
});
});
options.automations.forEach(param => {
param.methods.forEach(method => {
// Most for documentation in the output. These should never throw.
let message = `${param.name}.${method.name}(${method.options})`
should(() => {
aRateNode[param.name][method.name](...method.options);
}, options.prefix + ': a-rate node:' + message).notThrow();
});
});
// 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);
// 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();
return context.startRendering().then(renderedBuffer => {
let kRateOutput = renderedBuffer.getChannelData(0);
let aRateOutput = renderedBuffer.getChannelData(1);
let diff = renderedBuffer.getChannelData(2);
// Some informative messages to print out values of the k-rate and
// a-rate outputs. These should always pass.
should(
kRateOutput, `${options.prefix}: Output of k-rate ${options.nodeName}`)
.beEqualToArray(kRateOutput);
should(
aRateOutput, `${options.prefix}: Output of a-rate ${options.nodeName}`)
.beEqualToArray(aRateOutput);
// The real test. If k-rate AudioParam is working correctly, the
// k-rate result MUST differ from the a-rate result.
should(
diff,
`${
options.prefix
}: Difference between a-rate and k-rate ${options.nodeName}`)
.notBeConstantValueOf(0);
});
}

View file

@ -0,0 +1,167 @@
<!doctype html>
<html>
<head>
<title>AudioParam.automationRate tests</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>
</head>
<body>
<script>
// For each node that has an AudioParam, verify that the default
// |automationRate| has the expected value and that we can change it or
// throw an error if it can't be changed.
// Any valid sample rate is fine; we don't actually render anything in the
// tests.
let sampleRate = 8000;
let audit = Audit.createTaskRunner();
// Array of tests. Each test is a dictonary consisting of the name of the
// node and an array specifying the AudioParam's of the node. This array
// in turn gives the name of the AudioParam, the default value for the
// |automationRate|, and whether it is fixed (isFixed).
const tests = [
{
nodeName: 'AudioBufferSourceNode',
audioParams: [
{name: 'detune', defaultRate: 'k-rate', isFixed: true},
{name: 'playbackRate', defaultRate: 'k-rate', isFixed: true}
]
},
{
nodeName: 'BiquadFilterNode',
audioParams: [
{name: 'frequency', defaultRate: 'a-rate', isFixed: false},
{name: 'detune', defaultRate: 'a-rate', isFixed: false},
{name: 'Q', defaultRate: 'a-rate', isFixed: false},
{name: 'gain', defaultRate: 'a-rate', isFixed: false},
]
},
{
nodeName: 'ConstantSourceNode',
audioParams: [{name: 'offset', defaultRate: 'a-rate', isFixed: false}]
},
{
nodeName: 'DelayNode',
audioParams:
[{name: 'delayTime', defaultRate: 'a-rate', isFixed: false}]
},
{
nodeName: 'DynamicsCompressorNode',
audioParams: [
{name: 'threshold', defaultRate: 'k-rate', isFixed: true},
{name: 'knee', defaultRate: 'k-rate', isFixed: true},
{name: 'ratio', defaultRate: 'k-rate', isFixed: true},
{name: 'attack', defaultRate: 'k-rate', isFixed: true},
{name: 'release', defaultRate: 'k-rate', isFixed: true}
]
},
{
nodeName: 'GainNode',
audioParams: [{name: 'gain', defaultRate: 'a-rate', isFixed: false}]
},
{
nodeName: 'OscillatorNode',
audioParams: [
{name: 'frequency', defaultRate: 'a-rate', isFixed: false},
{name: 'detune', defaultRate: 'a-rate', isFixed: false}
]
},
{
nodeName: 'PannerNode',
audioParams: [
{name: 'positionX', defaultRate: 'a-rate', isFixed: false},
{name: 'positionY', defaultRate: 'a-rate', isFixed: false},
{name: 'positionZ', defaultRate: 'a-rate', isFixed: false},
{name: 'orientationX', defaultRate: 'a-rate', isFixed: false},
{name: 'orientationY', defaultRate: 'a-rate', isFixed: false},
{name: 'orientationZ', defaultRate: 'a-rate', isFixed: false},
]
},
{
nodeName: 'StereoPannerNode',
audioParams: [{name: 'pan', defaultRate: 'a-rate', isFixed: false}]
},
];
tests.forEach(test => {
// Define a separate test for each test entry.
audit.define(test.nodeName, (task, should) => {
let context = new OfflineAudioContext(
{length: sampleRate, sampleRate: sampleRate});
// Construct the node and test each AudioParam of the node.
let node = new window[test.nodeName](context);
test.audioParams.forEach(param => {
testAudioParam(
should, {nodeName: test.nodeName, node: node, param: param});
});
task.done();
});
});
// AudioListener needs it's own special test since it's not a node.
audit.define('AudioListener', (task, should) => {
let context = new OfflineAudioContext(
{length: sampleRate, sampleRate: sampleRate});
[{name: 'positionX', defaultRate: 'a-rate', isFixed: false},
{name: 'positionY', defaultRate: 'a-rate', isFixed: false},
{name: 'positionZ', defaultRate: 'a-rate', isFixed: false},
{name: 'forwardX', defaultRate: 'a-rate', isFixed: false},
{name: 'forwardY', defaultRate: 'a-rate', isFixed: false},
{name: 'forwardZ', defaultRate: 'a-rate', isFixed: false},
{name: 'upX', defaultRate: 'a-rate', isFixed: false},
{name: 'upY', defaultRate: 'a-rate', isFixed: false},
{name: 'upZ', defaultRate: 'a-rate', isFixed: false},
].forEach(param => {
testAudioParam(should, {
nodeName: 'AudioListener',
node: context.listener,
param: param
});
});
task.done();
});
audit.run();
function testAudioParam(should, options) {
let param = options.param;
let audioParam = options.node[param.name];
let defaultRate = param.defaultRate;
// Verify that the default value is correct.
should(
audioParam.automationRate,
`Default ${options.nodeName}.${param.name}.automationRate`)
.beEqualTo(defaultRate);
// Try setting the rate to a different rate. If the |automationRate|
// is fixed, expect an error. Otherwise, expect no error and expect
// the value is changed to the new value.
let newRate = defaultRate === 'a-rate' ? 'k-rate' : 'a-rate';
let setMessage = `Set ${
options.nodeName
}.${param.name}.automationRate to "${newRate}"`
if (param.isFixed) {
should(() => audioParam.automationRate = newRate, setMessage)
.throw('InvalidStateError');
}
else {
should(() => audioParam.automationRate = newRate, setMessage)
.notThrow();
should(
audioParam.automationRate,
`${options.nodeName}.${param.name}.automationRate`)
.beEqualTo(newRate);
}
}
</script>
</body>
</html>

View file

@ -0,0 +1,79 @@
<!doctype html>
<html>
<head>
<title>Test k-rate AudioParam of AudioWorkletNode</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>
</head>
<body>
<script>
const audit = Audit.createTaskRunner();
// Use the worklet gain node to test k-rate parameters.
const filePath =
'../the-audioworklet-interface/processors/gain-processor.js';
// Context for testing
let context;
audit.define('Create Test Worklet', (task, should) => {
// Arbitrary sample rate and duration.
const sampleRate = 8000;
// Only new a few render quanta to verify things are working.
const testDuration = 4 * 128 / sampleRate;
context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
length: testDuration * sampleRate
});
should(
context.audioWorklet.addModule(filePath),
'Construction of AudioWorklet')
.beResolved()
.then(() => task.done());
});
audit.define('AudioWorklet k-rate AudioParam', (task, should) => {
let src = new ConstantSourceNode(context);
let kRateNode = new AudioWorkletNode(context, 'gain');
src.connect(kRateNode).connect(context.destination);
let kRateParam = kRateNode.parameters.get('gain');
kRateParam.automationRate = 'k-rate';
// Automate the gain
kRateParam.setValueAtTime(0, 0);
kRateParam.linearRampToValueAtTime(
10, context.length / context.sampleRate);
src.start();
context.startRendering()
.then(audioBuffer => {
let output = audioBuffer.getChannelData(0);
// Verify that the output from the worklet is step-wise
// constant.
for (let k = 0; k < output.length; k += 128) {
should(
output.slice(k, k + 128),
` k-rate output [${k}: ${k + 127}]`)
.beConstantValueOf(output[k]);
}
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>

View file

@ -0,0 +1,111 @@
<!doctype html>
<html>
<head>
<title>Test k-rate AudioParams of BiquadFilterNode</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="automation-rate-testing.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
audit.define(
{task: 'BiquadFilter-0', label: 'Biquad k-rate AudioParams (all)'},
(task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
let testDuration = 1;
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
length: testDuration * sampleRate
});
doTest(context, should, {
nodeName: 'BiquadFilterNode',
nodeOptions: {type: 'lowpass'},
prefix: 'All k-rate params',
// Set all AudioParams to k-rate
rateSettings: [
{name: 'Q', value: 'k-rate'},
{name: 'detune', value: 'k-rate'},
{name: 'frequency', value: 'k-rate'},
{name: 'gain', value: 'k-rate'},
],
// Automate just the frequency
automations: [{
name: 'frequency',
methods: [
{name: 'setValueAtTime', options: [350, 0]}, {
name: 'linearRampToValueAtTime',
options: [0, testDuration]
}
]
}]
}).then(() => task.done());
});
// Define a test where we verify that a k-rate audio param produces
// different results from an a-rate audio param for each of the audio
// params of a biquad.
//
// Each entry gives the name of the AudioParam, an initial value to be
// used with setValueAtTime, and a final value to be used with
// linearRampToValueAtTime. (See |doTest| for details as well.)
[{name: 'Q',
initial: 1,
final: 10
},
{name: 'detune',
initial: 0,
final: 1200
},
{name: 'frequency',
initial: 350,
final: 0
},
{name: 'gain',
initial: 10,
final: 0
}].forEach(paramProperty => {
audit.define('Biquad k-rate ' + paramProperty.name, (task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
let testDuration = 1;
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
length: testDuration * sampleRate
});
doTest(context, should, {
nodeName: 'BiquadFilterNode',
nodeOptions: {type: 'peaking', Q: 1, gain: 10},
prefix: `k-rate ${paramProperty.name}`,
// Just set the frequency to k-rate
rateSettings: [
{name: paramProperty.name, value: 'k-rate'},
],
// Automate just the given AudioParam
automations: [{
name: paramProperty.name,
methods: [
{name: 'setValueAtTime', options: [paramProperty.initial, 0]}, {
name: 'linearRampToValueAtTime',
options: [paramProperty.final, testDuration]
}
]
}]
}).then(() => task.done());
});
});
audit.run();
</script>
</body>
</html>

View file

@ -0,0 +1,81 @@
<!doctype html>
<html>
<head>
<title>Test k-rate AudioParam of ConstantSourceNode</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>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
audit.define('ConstantSource k-rate offset', (task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
// Only new a few render quanta to verify things are working.
let testDuration = 4 * 128 / sampleRate;
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
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]);
}
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>

View file

@ -0,0 +1,49 @@
<!doctype html>
<html>
<head>
<title>Test k-rate AudioParam of DelayNode</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="automation-rate-testing.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
audit.define('Test k-rate DelayNode', (task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
let testDuration = 1;
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
length: testDuration * sampleRate
});
doTest(context, should, {
nodeName: 'DelayNode',
nodeOptions: null,
prefix: 'DelayNode',
// Set all AudioParams to k-rate
rateSettings: [{name: 'delayTime', value: 'k-rate'}],
// Automate just the frequency
automations: [{
name: 'delayTime',
methods: [
{name: 'setValueAtTime', options: [0, 0]}, {
name: 'linearRampToValueAtTime',
options: [.5, testDuration]
}
]
}]
}).then(() => task.done());
});
audit.run();
</script>
</body>
</html>

View file

@ -0,0 +1,47 @@
<!doctype html>
<html>
<head>
<title>Test k-rate AudioParam of GainNode</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="automation-rate-testing.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
audit.define('Test k-rate GainNode', (task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
let testDuration = 1;
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
length: testDuration * sampleRate
});
doTest(context, should, {
nodeName: 'GainNode',
nodeOptions: null,
prefix: 'GainNode',
// Set AudioParam to k-rate
rateSettings: [{name: 'gain', value: 'k-rate'}],
// Automate
automations: [{
name: 'gain',
methods: [
{name: 'setValueAtTime', options: [1, 0]},
{name: 'linearRampToValueAtTime', options: [0, testDuration]}
]
}]
}).then(() => task.done());
});
audit.run();
</script>
</body>
</html>

View file

@ -0,0 +1,88 @@
<!doctype html>
<html>
<head>
<title>Test k-rate AudioParams of OscillatorNode</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>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
// Arbitrary sample rate and duration.
let sampleRate = 8000;
// Only new a few render quanta to verify things are working.
let testDuration = 4 * 128 / sampleRate;
[{name: 'detune', initial: 0, final: 1200}, {
name: 'frequency',
initial: 440,
final: sampleRate / 2
}].forEach(paramProperty => {
audit.define(
'Oscillator k-rate ' + paramProperty.name, (task, should) => {
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
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 OscillatorNode(context);
let aRateNode = new OscillatorNode(context);
kRateNode.connect(merger, 0, 0);
aRateNode.connect(merger, 0, 1);
kRateNode.connect(merger, 0, 2);
aRateNode.connect(inverter);
// Set the rate
kRateNode[paramProperty.name].automationRate = 'k-rate';
// Automate the offset
kRateNode[paramProperty.name].setValueAtTime(
paramProperty.initial, 0);
kRateNode[paramProperty.name].linearRampToValueAtTime(
paramProperty.final, testDuration);
aRateNode[paramProperty.name].setValueAtTime(
paramProperty.initial, 0);
aRateNode[paramProperty.name].linearRampToValueAtTime(
paramProperty.final, 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,
'k-rate ' + paramProperty.name +
': Difference between a-rate and k-rate outputs')
.notBeConstantValueOf(0);
})
.then(() => task.done());
});
});
audit.run();
</script>
</body>
</html>

View file

@ -0,0 +1,172 @@
<!doctype html>
<html>
<head>
<title>Test k-rate AudioParams of PannerNode</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="automation-rate-testing.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
// Define a test where we verify that a k-rate audio param produces
// different results from an a-rate audio param for each of the audio
// params of a biquad.
//
// Each entry gives the name of the AudioParam, an initial value to be
// used with setValueAtTime, and a final value to be used with
// linearRampToValueAtTime. (See |doTest| for details as well.)
[{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},
].forEach(paramProperty => {
audit.define('Panner k-rate ' + paramProperty.name, (task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
let testDuration = 1;
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
length: testDuration * sampleRate
});
doTest(context, should, {
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
// axis where the azimuth and elevation might be constant when
// moving one of the AudioParams.
nodeOptions: {
distanceModel: 'inverse',
coneOuterAngle: 360,
coneInnerAngle: 10,
positionX: 10,
positionY: 10,
positionZ: 10,
orientationX: 1,
orientationY: 1,
orientationZ: 1
},
prefix: `k-rate ${paramProperty.name}`,
// Just set the frequency to k-rate
rateSettings: [
{name: paramProperty.name, value: 'k-rate'},
],
// Automate just the given AudioParam
automations: [{
name: paramProperty.name,
methods: [
{name: 'setValueAtTime', options: [paramProperty.initial, 0]}, {
name: 'linearRampToValueAtTime',
options: [paramProperty.final, testDuration]
}
]
}]
}).then(() => task.done());
});
});
// Test k-rate automation of the listener. The intial and final
// automation values are pretty arbitrary, except that they should be such
// that the panner and listener produces non-constant output.
[{name: 'positionX', initial: [1, 0], final: [1000, 1]},
{name: 'positionY', initial: [1, 0], final: [1000, 1]},
{name: 'positionZ', initial: [1, 0], final: [1000, 1]},
{name: 'forwardX', initial: [-1, 0], final: [1, 1]},
{name: 'forwardY', initial: [-1, 0], final: [1, 1]},
{name: 'forwardZ', initial: [-1, 0], final: [1, 1]},
{name: 'upX', initial: [-1, 0], final: [1000, 1]},
{name: 'upY', initial: [-1, 0], final: [1000, 1]},
{name: 'upZ', initial: [-1, 0], final: [1000, 1]},
].forEach(paramProperty => {
audit.define(
'Listener k-rate ' + paramProperty.name, (task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
let testDuration = 5 * 128 / sampleRate;
let context = new OfflineAudioContext({
numberOfChannels: 1,
sampleRate: sampleRate,
length: testDuration * sampleRate
});
doListenerTest(context, should, {
param: paramProperty.name,
initial: paramProperty.initial,
final: paramProperty.final
}).then(() => task.done());
});
});
audit.run();
function doListenerTest(context, should, options) {
let src = new ConstantSourceNode(context);
let panner = new PannerNode(context, {
distanceModel: 'inverse',
coneOuterAngle: 360,
coneInnerAngle: 10,
positionX: 10,
positionY: 10,
positionZ: 10,
orientationX: 1,
orientationY: 1,
orientationZ: 1
});
src.connect(panner).connect(context.destination);
src.start();
let listener = context.listener;
// Set listener properties to "random" values so that motion on one of
// the attributes actually changes things relative to the panner
// location.
listener.positionX.value = -1;
listener.positionY.value = 1;
listener.positionZ.value = -1;
listener.forwardX.value = -1;
listener.forwardY.value = 1;
listener.forwardZ.value = -1;
listener.upX.value = 1;
listener.upY.value = 1;
listener.upZ.value = 1;
let audioParam = listener[options.param];
audioParam.automationRate = 'k-rate';
let prefix = `Listener ${options.param}`;
should(audioParam.automationRate, prefix + '.automationRate')
.beEqualTo('k-rate');
should(() => {
audioParam.setValueAtTime(...options.initial);
}, prefix + `.setValueAtTime(${options.initial})`).notThrow();
should(() => {
audioParam.linearRampToValueAtTime(...options.final);
}, prefix + `.linearRampToValueAtTime(${options.final})`).notThrow();
return context.startRendering().then(renderedBuffer => {
let prefix = `Listener k-rate ${options.param}: `;
let output = renderedBuffer.getChannelData(0);
// Sanity check that the output isn't constant.
should(output, prefix + `Output`).notBeConstantValueOf(output[0]);
// Verify that the output is constant over each render quantum
for (let k = 0; k < output.length; k += 128) {
should(
output.slice(k, k + 128), prefix + `Output [${k}, ${k + 127}]`)
.beConstantValueOf(output[k]);
}
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,48 @@
<!doctype html>
<html>
<head>
<title>Test k-rate AudioParam of StereoPannerNode</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="automation-rate-testing.js"></script>
</head>
<body>
<script>
let audit = Audit.createTaskRunner();
audit.define('Test k-rate StereoPannerNode', (task, should) => {
// Arbitrary sample rate and duration.
let sampleRate = 8000;
let testDuration = 1;
let context = new OfflineAudioContext({
numberOfChannels: 3,
sampleRate: sampleRate,
length: testDuration * sampleRate
});
doTest(context, should, {
nodeName: 'StereoPannerNode',
nodeOptions: null,
prefix: 'StereoPannerNode',
// Set all AudioParams to k-rate.
rateSettings: [{name: 'pan', value: 'k-rate'}],
// Automate just the frequency.
automations: [{
name: 'pan',
methods: [
{name: 'setValueAtTime', options: [0, 0]}, {
name: 'linearRampToValueAtTime',
options: [.5, testDuration]
}
]
}]
}).then(() => task.done());
});
audit.run();
</script>
</body>
</html>