Bug 1443628 [wpt PR 9883] - Upstream AudioWorklet tests to WPT suite, a=testonly

Automatic update from web-platform-testsUpstream AudioWorklet tests to WPT suite

1. Tests moved:
 From - src/third_party/WebKit/LayoutTests/http/tests/webaudio/audio-worklet/
 to - src/third_party/WebKit/LayoutTests/external/wpt/webaudio/
2. All tests were renamed because of the SecureContext requirement.
3. Updated the script paths.
4. Used a variable for the processor script path.

Bug: 817869
Test: All existing tests are passing after updating paths.
Change-Id: I7bd6c91c365730e453205f2241cb45986e2c7d3b
Reviewed-on: https://chromium-review.googlesource.com/944847
Reviewed-by: Raymond Toy <rtoy@chromium.org>
Reviewed-by: Kent Tamura <tkent@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#541281}

wpt-commits: a075d92a0c9a272c4140ab66a94db93aa630e355
wpt-pr: 9883
wpt-commits: a075d92a0c9a272c4140ab66a94db93aa630e355
wpt-pr: 9883
This commit is contained in:
Hongchan Choi 2018-03-26 15:17:43 +00:00 коммит произвёл James Graham
Родитель 43da93bc8b
Коммит 1fd3eec3ea
19 изменённых файлов: 1129 добавлений и 0 удалений

Просмотреть файл

@ -294373,6 +294373,41 @@
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/dummy-processor.js": [
[
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/error-processor.js": [
[
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/gain-processor.js": [
[
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/one-pole-processor.js": [
[
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/option-test-processor.js": [
[
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/port-processor.js": [
[
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/timing-info-processor.js": [
[
{}
]
],
"webaudio/the-audio-api/the-biquadfilternode-interface/.gitkeep": [
[
{}
@ -363480,6 +363515,72 @@
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworklet-addmodule-resolution.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-addmodule-resolution.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworklet-audioparam.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-audioparam.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworklet-messageport.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-messageport.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletglobalscope-sample-rate.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworkletglobalscope-sample-rate.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletglobalscope-timing-info.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworkletglobalscope-timing-info.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-channel-count.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-channel-count.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-construction.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-construction.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-constructor-options.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-constructor-options.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-onerror.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-onerror.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-options.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-options.https.html",
{}
]
],
"webaudio/the-audio-api/the-audioworklet-interface/baseaudiocontext-audioworklet.https.html": [
[
"/webaudio/the-audio-api/the-audioworklet-interface/baseaudiocontext-audioworklet.https.html",
{}
]
],
"webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic.html": [
[
"/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic.html",
@ -599253,6 +599354,78 @@
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworklet-addmodule-resolution.https.html": [
"d8f2e2d2f6592718f329c1727b63d69035965973",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworklet-audioparam.https.html": [
"de9ecb9c7d9a65052a7a795b0f13c73ed31dbe7b",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworklet-messageport.https.html": [
"e14996a4d8cd2765d9b78b7ec6d4350dc54bb8da",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletglobalscope-sample-rate.https.html": [
"8228071abd6c36908a8b31372185dc0f2dfcdd0a",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletglobalscope-timing-info.https.html": [
"ef7c004225bbb5e6d289a990191b22e2faeabcf3",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-channel-count.https.html": [
"b6701142fd660a6a29fbfc68cb530b70817b3a44",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-construction.https.html": [
"b2513b4b5f37b906250b4e1f78eaec80bdc41ef6",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-constructor-options.https.html": [
"99284ab790c09dd7a23a6fa5022e8b08b9e3947d",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-onerror.https.html": [
"a1cd969fe32a5aca7cd90d0d0955132fd1660b9c",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-options.https.html": [
"b70c4e78f5b816a5af789660285ceb91f5dddbfa",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/baseaudiocontext-audioworklet.https.html": [
"526bcd8fd99ea61564432ca3026a2b6a0b7315b9",
"testharness"
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/dummy-processor.js": [
"6c985b8281cc9aa25eb61fdb436e6cc36f48bb5b",
"support"
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/error-processor.js": [
"0859e9f7bbaf00853f85bbb0e2d6eb4db85578b3",
"support"
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/gain-processor.js": [
"1561b9eede1ee15126fdd9674a6d9d63194b66c2",
"support"
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/one-pole-processor.js": [
"80b817db4e8d3f49e4f5fe6e97f8e687d16f3159",
"support"
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/option-test-processor.js": [
"c2f028c2be836cad2c38a71f96246f84c04323a5",
"support"
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/port-processor.js": [
"47092e4372a196e47612388602b6a3876deb653a",
"support"
],
"webaudio/the-audio-api/the-audioworklet-interface/processors/timing-info-processor.js": [
"c93a76f097b441aaec052516256cc922089b4b75",
"support"
],
"webaudio/the-audio-api/the-biquadfilternode-interface/.gitkeep": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"

Просмотреть файл

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test the invocation order of AudioWorklet.addModule() and BaseAudioContext
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let sampleRate = 48000;
let realtimeContext = new AudioContext();
let offlineContext = new OfflineAudioContext(1, sampleRate, sampleRate);
let filePath = 'processors/dummy-processor.js';
// Test if the browser does not crash upon addModule() call after the
// realtime context construction.
audit.define(
{label: 'module-loading-after-realtime-context-creation'},
(task, should) => {
let dummyWorkletNode =
new AudioWorkletNode(realtimeContext, 'dummy');
dummyWorkletNode.connect(realtimeContext.destination);
should(dummyWorkletNode instanceof AudioWorkletNode,
'"dummyWorkletNode" is an instance of AudioWorkletNode ' +
'from realtime context')
.beTrue();
task.done();
});
// Test if the browser does not crash upon addModule() call after the
// offline context construction.
audit.define(
{label: 'module-loading-after-offline-context-creation'},
(task, should) => {
let dummyWorkletNode =
new AudioWorkletNode(offlineContext, 'dummy');
dummyWorkletNode.connect(offlineContext.destination);
should(dummyWorkletNode instanceof AudioWorkletNode,
'"dummyWorkletNode" is an instance of AudioWorkletNode ' +
'from offline context')
.beTrue();
task.done();
});
Promise.all([
realtimeContext.audioWorklet.addModule(filePath),
offlineContext.audioWorklet.addModule(filePath)
]).then(() => {
audit.run();
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test AudioWorkletNode's basic AudioParam features
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let sampleRate = 48000;
let renderLength = 48000 * 0.6;
let context;
let filePath = 'processors/gain-processor.js';
// Sets up AudioWorklet and OfflineAudioContext.
audit.define('Initializing AudioWorklet and Context', (task, should) => {
context = new OfflineAudioContext(1, renderLength, sampleRate);
context.audioWorklet.addModule(filePath).then(() => {
task.done();
});
});
// Verifies the functionality of AudioParam in AudioWorkletNode by
// comparing (canceling out) values from GainNode and AudioWorkletNode
// with simple gain computation code by AudioParam.
audit.define(
'Verifying AudioParam in AudioWorkletNode',
(task, should) => {
let constantSourceNode = new ConstantSourceNode(context);
let gainNode = new GainNode(context);
let inverterNode = new GainNode(context, {gain: -1});
let gainWorkletNode = new AudioWorkletNode(context, 'gain');
let gainWorkletParam = gainWorkletNode.parameters.get('gain');
// Test default value and setter/getter functionality.
should(gainWorkletParam.value,
'Default gain value of gainWorkletNode')
.beEqualTo(Math.fround(0.707));
gainWorkletParam.value = 0.1;
should(gainWorkletParam.value,
'Value of gainWorkletParam after setter = 0.1')
.beEqualTo(Math.fround(0.1));
constantSourceNode.connect(gainNode)
.connect(inverterNode)
.connect(context.destination);
constantSourceNode.connect(gainWorkletNode)
.connect(context.destination);
// With arbitrary times and values, test all possible AudioParam
// automations.
[gainNode.gain, gainWorkletParam].forEach((param) => {
param.setValueAtTime(0, 0);
param.linearRampToValueAtTime(1, 0.1);
param.exponentialRampToValueAtTime(0.5, 0.2);
param.setValueCurveAtTime([0, 2, 0.3], 0.2, 0.1);
param.setTargetAtTime(0.01, 0.4, 0.5);
});
// Test if the setter works correctly in the middle of rendering.
context.suspend(0.5).then(() => {
gainNode.gain.value = 1.5;
gainWorkletParam.value = 1.5;
context.resume();
});
constantSourceNode.start();
context.startRendering().then((renderedBuffer) => {
should(renderedBuffer.getChannelData(0),
'The rendered buffer')
.beConstantValueOf(0);
task.done();
});
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test MessagePort in AudioWorkletNode and AudioWorkletProcessor
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let context = new AudioContext();
let filePath = 'processors/port-processor.js';
// Creates an AudioWorkletNode and sets an EventHandler on MessagePort
// object. The associated PortProcessor will post a message upon its
// construction. Test if the message is received correctly.
audit.define(
'Test postMessage from AudioWorkletProcessor to AudioWorkletNode',
(task, should) => {
let porterWorkletNode =
new AudioWorkletNode(context, 'port-processor');
// Upon the creation of PortProcessor, it will post a message to the
// node with 'created' status.
porterWorkletNode.port.onmessage = (event) => {
should(event.data.state,
'The initial message from PortProcessor')
.beEqualTo('created');
task.done();
};
});
// PortProcessor is supposed to echo the message back to the
// AudioWorkletNode.
audit.define(
'Test postMessage from AudioWorkletNode to AudioWorkletProcessor',
(task, should) => {
let porterWorkletNode =
new AudioWorkletNode(context, 'port-processor');
porterWorkletNode.port.onmessage = (event) => {
// Ignore if the delivered message has |state|. This is already
// tested in the previous task.
if (event.data.state)
return;
should(event.data.message,
'The response from PortProcessor')
.beEqualTo('hello');
task.done();
};
porterWorkletNode.port.postMessage('hello');
});
context.audioWorklet.addModule(filePath).then(() => {
audit.run();
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test sampleRate in AudioWorkletGlobalScope
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let sampleRate = 48000;
let renderLength = 512;
let context = new OfflineAudioContext(1, renderLength, sampleRate);
let filePath = 'processors/one-pole-processor.js';
// Without rendering the context, attempt to access |sampleRate| in the
// global scope as soon as it is created.
audit.define(
'Query |sampleRate| upon AudioWorkletGlobalScope construction',
(task, should) => {
let onePoleFilterNode =
new AudioWorkletNode(context, 'one-pole-filter');
let frequencyParam = onePoleFilterNode.parameters.get('frequency');
should(frequencyParam.maxValue,
'frequencyParam.maxValue')
.beEqualTo(0.5 * context.sampleRate);
task.done();
});
context.audioWorklet.addModule(filePath).then(() => {
audit.run();
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test currentTime and currentFrame in AudioWorkletGlobalScope
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let sampleRate = 48000;
let renderLength = 512;
let context = new OfflineAudioContext(1, renderLength, sampleRate);
let filePath = 'processors/timing-info-processor.js';
audit.define(
'Check the timing information from AudioWorkletProcessor',
(task, should) => {
let portWorkletNode =
new AudioWorkletNode(context, 'timing-info-processor');
portWorkletNode.connect(context.destination);
// Suspend at render quantum boundary and check the timing
// information between the main thread and the rendering thread.
[0, 128, 256, 384].map((suspendFrame) => {
context.suspend(suspendFrame/sampleRate).then(() => {
portWorkletNode.port.onmessage = (event) => {
should(event.data.currentFrame,
'currentFrame from the processor at ' + suspendFrame)
.beEqualTo(suspendFrame);
should(event.data.currentTime,
'currentTime from the processor at '
+ context.currentTime)
.beEqualTo(context.currentTime);
context.resume();
};
portWorkletNode.port.postMessage('query-timing-info');
});
});
context.startRendering().then(() => {
task.done();
});
});
context.audioWorklet.addModule(filePath).then(() => {
audit.run();
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test AudioWorkletNode's dynamic channel count feature
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
<script src="/webaudio/resources/audit-util.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
// Arbitrary numbers used to align the test with render quantum boundary.
let sampleRate = RENDER_QUANTUM_FRAMES * 100;
let renderLength = RENDER_QUANTUM_FRAMES * 2;
let context;
let filePath = 'processors/gain-processor.js';
let testChannelValues = [1, 2, 3];
// Creates a 3-channel buffer and play with BufferSourceNode. The source
// goes through a bypass AudioWorkletNode (gain value of 1).
audit.define('setup-buffer-and-worklet', (task, should) => {
context = new OfflineAudioContext(testChannelValues.length,
renderLength,
sampleRate);
// Explicitly sets the destination channelCountMode and
// channelInterpretation to make sure the result does no mixing.
context.channeCountMode = 'explicit';
context.channelInterpretation = 'discrete';
context.audioWorklet.addModule(filePath).then(() => {
let testBuffer = createConstantBuffer(context, 1, testChannelValues);
let sourceNode = new AudioBufferSourceNode(context);
let gainWorkletNode = new AudioWorkletNode(context, 'gain');
gainWorkletNode.parameters.get('gain').value = 1.0;
sourceNode.connect(gainWorkletNode).connect(context.destination);
// Suspend the context at 128 sample frames and play the source with
// the assigned buffer.
context.suspend(RENDER_QUANTUM_FRAMES/sampleRate).then(() => {
sourceNode.buffer = testBuffer;
sourceNode.loop = true;
sourceNode.start();
context.resume();
});
task.done();
});
});
// Verifies if the rendered buffer has all zero for the first half (before
// 128 samples) and the expected values for the second half.
audit.define('verify-rendered-buffer', (task, should) => {
context.startRendering().then(renderedBuffer => {
testChannelValues.forEach((value, index) => {
let channelData = renderedBuffer.getChannelData(index);
should(channelData.subarray(0, RENDER_QUANTUM_FRAMES),
'First half of Channel #' + index)
.beConstantValueOf(0);
should(channelData.subarray(RENDER_QUANTUM_FRAMES, renderLength),
'Second half of Channel #' + index)
.beConstantValueOf(value);
});
task.done();
});
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test the construction of AudioWorkletNode with real-time context
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let realtimeContext = new AudioContext();
let filePath = 'processors/dummy-processor.js';
// Test if an exception is thrown correctly when AWN constructor is
// invoked before resolving |.addModule()| promise.
audit.define(
{label: 'construction-before-module-loading'},
(task, should) => {
should(() => new AudioWorkletNode(realtimeContext, 'dummy'),
'Creating a node before loading a module should throw.')
.throw('InvalidStateError');
task.done();
});
// Test the construction of AudioWorkletNode after the resolution of
// |.addModule()|. Also the constructor must throw an exception when
// a unregistered node name was given.
audit.define(
{label: 'construction-after-module-loading'},
(task, should) => {
realtimeContext.audioWorklet.addModule(filePath).then(() => {
let dummyWorkletNode =
new AudioWorkletNode(realtimeContext, 'dummy');
should(dummyWorkletNode instanceof AudioWorkletNode,
'"dummyWorkletNode" is an instance of AudioWorkletNode')
.beTrue();
should(() => new AudioWorkletNode(realtimeContext, 'foobar'),
'Unregistered name "foobar" must throw an exception.')
.throw();
task.done();
});
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,149 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test of AudioWorkletNodeOptions
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
const sampleRate = 48000;
const audit = Audit.createTaskRunner();
let context;
let filePath = 'processors/dummy-processor.js';
// Load script file and create a OfflineAudiocontext.
audit.define('setup', (task, should) => {
context = new OfflineAudioContext(1, 1, sampleRate);
context.audioWorklet.addModule(filePath).then(() => {
task.done();
});
});
// Test AudioWorkletNode construction without AudioWorkletNodeOptions.
audit.define('without-audio-node-options', (task, should) => {
let testNode;
should(
() => testNode = new AudioWorkletNode(context, 'dummy'),
'Creating AudioWOrkletNode without options')
.notThrow();
should(testNode instanceof AudioWorkletNode,
'testNode is instance of AudioWorkletNode').beEqualTo(true);
should(testNode.numberOfInputs,
'testNode.numberOfInputs (default)').beEqualTo(1);
should(testNode.numberOfOutputs,
'testNode.numberOfOutputs (default)').beEqualTo(1);
should(testNode.channelCount,
'testNode.channelCount (default)').beEqualTo(2);
should(testNode.channelCountMode,
'testNode.channelCountMode (default)').beEqualTo('max');
should(testNode.channelInterpretation,
'testNode.channelInterpretation (default)')
.beEqualTo('speakers');
task.done();
});
// Test AudioWorkletNode constructor with AudioNodeOptions.
audit.define('audio-node-options', (task, should) => {
const options = {
numberOfInputs: 7,
numberOfOutputs: 18,
channelCount: 4,
channelCountMode: 'clamped-max',
channelInterpretation: 'discrete'
};
const optionsString = JSON.stringify(options);
let testNode;
should(
() => testNode = new AudioWorkletNode(context, 'dummy', options),
'Creating AudioWOrkletNode with options: ' + optionsString)
.notThrow();
should(testNode.numberOfInputs,
'testNode.numberOfInputs').beEqualTo(options.numberOfInputs);
should(testNode.numberOfOutputs,
'testNode.numberOfOutputs').beEqualTo(options.numberOfOutputs);
should(testNode.channelCount,
'testNode.channelCount').beEqualTo(options.channelCount);
should(testNode.channelCountMode,
'testNode.channelCountMode').beEqualTo(options.channelCountMode);
should(testNode.channelInterpretation,
'testNode.channelInterpretation')
.beEqualTo(options.channelInterpretation);
task.done();
});
// Test AudioWorkletNode.channelCount.
audit.define('channel-count', (task, should) => {
const options1 = {channelCount: 17};
let testNode = new AudioWorkletNode(context, 'dummy', options1);
should(testNode.channelCount, 'testNode.channelCount')
.beEqualTo(options1.channelCount);
const options2 = {channelCount: 0};
should(
() => new AudioWorkletNode(context, 'dummy', options2),
'Creating AudioWorkletNode with channelCount 0')
.throw('NotSupportedError');
const options3 = {channelCount: 33};
should(
() => new AudioWorkletNode(context, 'dummy', options3),
'Creating AudioWorkletNode with channelCount 33')
.throw('NotSupportedError');
task.done();
});
// Test AudioWorkletNode.channelCountMode.
audit.define('channel-count-mode', (task, should) => {
const channelCountModes = ['max', 'clamped-max', 'explicit'];
channelCountModes.forEach((mode) => {
const options = {channelCountMode: mode};
let testNode = new AudioWorkletNode(context, 'dummy', options);
should(testNode.channelCountMode,
'testNode.channelCountMode (set via options.' + mode + ')')
.beEqualTo(options.channelCountMode);
});
const options1 = {channelCountMode: 'foobar'};
should(
() => new AudioWorkletNode(context, 'dummy', options1),
'Creating AudioWorkletNode with channelCountMode "foobar"')
.throw('TypeError');
task.done();
});
// Test AudioWorkletNode.channelInterpretation.
audit.define('channel-interpretation', (task, should) => {
const channelInterpretations = ['speakers', 'discrete'];
channelInterpretations.forEach((interpretation) => {
const options = {channelInterpretation: interpretation};
let testNode = new AudioWorkletNode(context, 'dummy', options);
should(
testNode.channelInterpretation,
'testNode.channelInterpretation (set via options.' +
interpretation + ')')
.beEqualTo(options.channelInterpretation);
});
const options1 = {channelInterpretation: 'foobar'};
should(
() => new AudioWorkletNode(context, 'dummy', options1),
'Creating AudioWorkletNode with channelCountMode "foobar"')
.throw('TypeError');
task.done();
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test onprocessorerror handler in AudioWorkletNode
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
const sampleRate = 48000;
const renderLength = sampleRate * 0.1;
let context = new OfflineAudioContext(1, renderLength, sampleRate);
let filePath = 'processors/error-processor.js';
// Test |onprocessorerror| called upon failure of processor constructor.
audit.define('constructor-error',
(task, should) => {
let constructorErrorWorkletNode =
new AudioWorkletNode(context, 'constructor-error');
constructorErrorWorkletNode.onprocessorerror = () => {
// Without 'processorerror' event callback, this test will be
// timed out.
task.done();
};
});
// Test |onprocessorerror| called upon failure of process() method.
audit.define('process-error',
(task, should) => {
let processErrorWorkletNode =
new AudioWorkletNode(context, 'process-error');
processErrorWorkletNode.connect(context.destination);
processErrorWorkletNode.onprocessorerror = () => {
// Without 'processorerror' event callback, this test will be
// timed out.
task.done();
};
context.startRendering();
});
// 'error-processor.js' contains 2 class definitions represents an error
// in the constructor and an error in the process method respectively.
context.audioWorklet.addModule(filePath).then(() => {
audit.run();
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html>
<head>
<title>
Test cross-thread passing of AudioWorkletNodeOptions
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
const audit = Audit.createTaskRunner();
const context = new AudioContext();
let filePath = 'processors/option-test-processor.js';
// Create a OptionTestProcessor and feed |processorData| to it. The
// processor should echo the received data to the node's |onmessage|
// handler.
audit.define('valid-processor-data', (task, should) => {
context.audioWorklet.addModule(filePath).then(() => {
let processorOptions = {
description: 'foo',
payload: [0, 1, 2, 3]
};
let optionTestNode =
new AudioWorkletNode(context, 'option-test-processor', {
processorOptions: processorOptions
});
optionTestNode.port.onmessage = (event) => {
should(event.data.processorOptions.description,
'|description| field in processorOptions from processor("' +
event.data.processorOptions.description + '")')
.beEqualTo(processorOptions.description,
'the field in node constructor options ("' +
processorOptions.description + '")');
should(event.data.processorOptions.payload,
'|payload| array in processorOptions from processor([' +
event.data.processorOptions.payload + '])')
.beEqualToArray([0, 1, 2, 3],
'the array in node constructor options ([' +
event.data.processorOptions.payload + '])');
task.done();
};
});
});
// Passing empty option dictionary should work without a problem.
audit.define('empty-option', (task, should) => {
context.audioWorklet.addModule(filePath).then(() => {
let optionTestNode =
new AudioWorkletNode(context, 'option-test-processor');
optionTestNode.port.onmessage = (event) => {
should(Object.keys(event.data).length,
'Number of properties in data from processor')
.beEqualTo(2);
should(event.data.numberOfInputs,
'|numberOfInputs| field in data from processor')
.beEqualTo(1);
should(event.data.numberOfOutputs,
'|numberOfOutputs| field in data from processor')
.beEqualToArray(1);
task.done();
};
});
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>
Checking BaseAudioContext.audioWorklet
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let realtimeContext = new AudioContext();
let offlineContext = new OfflineAudioContext(1, 1, 44100);
// Test if AudioWorklet exists.
audit.define('Test if AudioWorklet exists', (task, should) => {
should(realtimeContext.audioWorklet instanceof AudioWorklet &&
offlineContext.audioWorklet instanceof AudioWorklet,
'BaseAudioContext.audioWorklet is an instance of AudioWorklet')
.beTrue();
task.done();
});
audit.run();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,18 @@
/**
* @class DummyProcessor
* @extends AudioWorkletProcessor
*
* This processor class demonstrates the bare-bone structure of the processor.
*/
class DummyProcessor extends AudioWorkletProcessor {
constructor() {
super();
}
process(inputs, outputs, parameters) {
// Doesn't do anything here.
return true;
}
}
registerProcessor('dummy', DummyProcessor);

Просмотреть файл

@ -0,0 +1,33 @@
/**
* @class ConstructorErrorProcessor
* @extends AudioWorkletProcessor
*/
class ConstructorErrorProcessor extends AudioWorkletProcessor {
constructor() {
throw 'ConstructorErrorProcessor: an error thrown from constructor.';
}
process() {
return true;
}
}
/**
* @class ProcessErrorProcessor
* @extends AudioWorkletProcessor
*/
class ProcessErrorProcessor extends AudioWorkletProcessor {
constructor() {
super();
}
process() {
throw 'ProcessErrorProcessor: an error throw from process method.';
return true;
}
}
registerProcessor('constructor-error', ConstructorErrorProcessor);
registerProcessor('process-error', ProcessErrorProcessor);

Просмотреть файл

@ -0,0 +1,33 @@
/**
* @class GainProcessor
* @extends AudioWorkletProcessor
*
* This processor class demonstrates the bare-bone structure of the processor.
*/
class GainProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [
{name: 'gain', defaultValue: 0.707}
];
}
constructor() {
super();
}
process(inputs, outputs, parameters) {
let input = inputs[0];
let output = outputs[0];
let gain = parameters.gain;
for (let channel = 0; channel < input.length; ++channel) {
let inputChannel = input[channel];
let outputChannel = output[channel];
for (let i = 0; i < inputChannel.length; ++i)
outputChannel[i] = inputChannel[i] * gain[i];
}
return true;
}
}
registerProcessor('gain', GainProcessor);

Просмотреть файл

@ -0,0 +1,49 @@
/**
* @class OnePoleFilter
* @extends AudioWorkletProcessor
*
* A simple One-pole filter.
*/
class OnePoleFilter extends AudioWorkletProcessor {
// This gets evaluated as soon as the global scope is created.
static get parameterDescriptors() {
return [{
name: 'frequency',
defaultValue: 250,
minValue: 0,
maxValue: 0.5 * sampleRate
}];
}
constructor() {
super();
this.updateCoefficientsWithFrequency_(250);
}
updateCoefficientsWithFrequency_(frequency) {
this.b1_ = Math.exp(-2 * Math.PI * frequency / sampleRate);
this.a0_ = 1.0 - this.b1_;
this.z1_ = 0;
}
process(inputs, outputs, parameters) {
let input = inputs[0];
let output = outputs[0];
let frequency = parameters.frequency;
for (let channel = 0; channel < output.length; ++channel) {
let inputChannel = input[channel];
let outputChannel = output[channel];
for (let i = 0; i < outputChannel.length; ++i) {
this.updateCoefficientsWithFrequency_(frequency[i]);
this.z1_ = inputChannel[i] * this.a0_ + this.z1_ * this.b1_;
outputChannel[i] = this.z1_;
}
}
return true;
}
}
registerProcessor('one-pole-filter', OnePoleFilter);

Просмотреть файл

@ -0,0 +1,19 @@
/**
* @class OptionTestProcessor
* @extends AudioWorkletProcessor
*
* This processor class demonstrates the option passing feature by echoing the
* received |nodeOptions| back to the node.
*/
class OptionTestProcessor extends AudioWorkletProcessor {
constructor(nodeOptions) {
super();
this.port.postMessage(nodeOptions);
}
process() {
return true;
}
}
registerProcessor('option-test-processor', OptionTestProcessor);

Просмотреть файл

@ -0,0 +1,29 @@
/**
* @class PortProcessor
* @extends AudioWorkletProcessor
*
* This processor class demonstrates the message port functionality.
*/
class PortProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.port.onmessage = this.handleMessage.bind(this);
this.port.postMessage({
state: 'created',
timeStamp: currentTime
});
}
handleMessage(event) {
this.port.postMessage({
message: event.data,
timeStamp: currentTime
});
}
process() {
return true;
}
}
registerProcessor('port-processor', PortProcessor);

Просмотреть файл

@ -0,0 +1,25 @@
/**
* @class TimingInfoProcessor
* @extends AudioWorkletProcessor
*
* This processor class is to test the timing information in AWGS.
*/
class TimingInfoProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.port.onmessage = this.echoMessage.bind(this);
}
echoMessage(event) {
this.port.postMessage({
currentTime: currentTime,
currentFrame: currentFrame
});
}
process() {
return true;
}
}
registerProcessor('timing-info-processor', TimingInfoProcessor);