| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8" /> |
| <title> |
| Test get parameterDescriptor as various iterables |
| </title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/webaudio/js/helpers.js"></script> |
| </head> |
| |
| <body> |
| <script id="params"> |
| // A series of AudioParamDescriptors, copied one by one into various iterable |
| // data structures. This is used by both the processor side and the main |
| // thread side, so is in a different script tag. |
| const PARAMS = [ |
| { |
| name: "a control-rate parameter", |
| defaultValue: 0.5, |
| minValue: 0, |
| maxValue: 1, |
| automationRate: "a-rate", |
| }, |
| { |
| name: "你好", |
| defaultValue: 2.5, |
| minValue: 0, |
| maxValue: 7, |
| automationRate: "a-rate", |
| }, |
| { |
| name: "🎶", |
| defaultValue: 8.5, |
| minValue: 0, |
| maxValue: 11115, |
| automationRate: "k-rate", |
| }, |
| ]; |
| </script> |
| <script id="processors" type="worklet"> |
| registerProcessor("set", |
| class SetParamProcessor extends AudioWorkletProcessor { |
| static get parameterDescriptors() { |
| var s = new Set(); |
| s.add(PARAMS[0]); |
| s.add(PARAMS[1]); |
| s.add(PARAMS[2]); |
| return s; |
| } |
| constructor() { super(); } |
| process() { |
| } |
| }); |
| |
| registerProcessor("array", |
| class ArrayParamProcessor extends AudioWorkletProcessor { |
| static get parameterDescriptors() { |
| return PARAMS; |
| } |
| constructor() { super(); } |
| process() { } |
| }); |
| |
| function* gen() { |
| yield PARAMS[0]; |
| yield PARAMS[1]; |
| yield PARAMS[2]; |
| } |
| registerProcessor("generator", |
| class GeneratorParamProcessor extends AudioWorkletProcessor { |
| static get parameterDescriptors() { |
| return gen(); |
| } |
| constructor() { super(); } |
| process() { } |
| }); |
| // Test a processor that has a get parameterDescriptors, but it returns |
| // something that is not iterable. |
| try { |
| registerProcessor("invalid", |
| class InvalidParamProcessor extends AudioWorkletProcessor { |
| static get parameterDescriptors() { |
| return 4; |
| } |
| constructor() { super(); } |
| process() { } |
| }); |
| throw "This should not have been reached."; |
| } catch (e) { |
| // unclear how to signal success here, but we can signal failure in the |
| // developer console |
| if (e.name != "TypeError") { |
| throw "This should be TypeError"; |
| } |
| } |
| // Test a processor that has a get parameterDescriptors, with a duplicate |
| // param name something that is not iterable. |
| try { |
| registerProcessor("duplicate-param-name", |
| class DuplicateParamProcessor extends AudioWorkletProcessor { |
| static get parameterDescriptors() { |
| var p = { |
| name: "a", |
| defaultValue: 1, |
| minValue: 0, |
| maxValue: 1, |
| automationRate: "k-rate", |
| }; |
| return [p,p]; |
| } |
| constructor() { super(); } |
| process() { } |
| }); |
| throw "This should not have been reached."; |
| } catch (e) { |
| // unclear how to signal success here, but we can signal failure in the |
| // developer console |
| if (e.name != "NotSupportedError") { |
| throw "This should be NotSupportedError"; |
| } |
| } |
| // Test a processor that has a no get parameterDescriptors. |
| try { |
| registerProcessor("no-params", |
| class NoParamProcessor extends AudioWorkletProcessor { |
| constructor() { super(); } |
| process() { } |
| }); |
| } catch (e) { |
| throw "Construction should have worked."; |
| } |
| </script> |
| <script> |
| setup({ explicit_done: true }); |
| // Mangle the PARAMS object into a map that has the same shape as what an |
| // AudioWorkletNode.parameter property would |
| var PARAMS_MAP = new Map(); |
| for (var param of PARAMS) { |
| var o = param; |
| var name = o.name; |
| delete o.name; |
| PARAMS_MAP.set(name, o); |
| } |
| |
| // This compares `lhs` and `rhs`, that are two maplike with the same shape |
| // as PARAMS_MAP. |
| function compare(testname, lhs, rhs) { |
| equals(lhs.size, rhs.size, "Map match in size for " + testname); |
| var i = 0; |
| for (var [k, v] of lhs) { |
| is_true(rhs.has(k), testname + ": " + k + " exists in both maps"); |
| var vrhs = rhs.get(k); |
| ["defaultValue", "minValue", "maxValue", "automationRate"].forEach( |
| paramKey => { |
| equals( |
| v[paramKey], |
| vrhs[paramKey], |
| `Values for ${k}.${paramKey} match for ${testname}` |
| ); |
| } |
| ); |
| } |
| } |
| var ac = new AudioContext(); |
| var url = URLFromScriptsElements(["params", "processors"]); |
| ac.audioWorklet |
| .addModule(url) |
| .then(() => { |
| ["set", "array", "generator"].forEach(iterable => { |
| test(() => { |
| var node = new AudioWorkletNode(ac, iterable); |
| compare(iterable, node.parameters, PARAMS_MAP); |
| }, `Creating an AudioWorkletNode with a ${iterable} for |
| parameter descriptor worked`); |
| }); |
| }) |
| .then(function() { |
| test(function() { |
| assert_throws_dom("InvalidStateError", function() { |
| new AudioWorkletNode(ac, "invalid"); |
| }); |
| }, `Attempting to create an AudioWorkletNode with an non |
| iterable for parameter descriptor should not work`); |
| }) |
| .then(function() { |
| test(() => { |
| new AudioWorkletNode(ac, "no-params"); |
| }, `Attempting to create an AudioWorkletNode from a processor |
| that does not have a parameterDescriptors getter should work`); |
| }) |
| .then(function() { |
| test(function() { |
| assert_throws_dom("InvalidStateError", function() { |
| new AudioWorkletNode(ac, "duplicate-param-name"); |
| }); |
| }, `Attempting to create an AudioWorkletNode with two parameter |
| descriptor with the same name should not work`); |
| }).then(function() { |
| done(); |
| }); |
| </script> |
| </body> |
| </html> |