Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Unified Diff: third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html

Issue 1803153002: Add min/max values for AudioParams (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html
new file mode 100644
index 0000000000000000000000000000000000000000..a917b826248d63ab7b6742429a05b29a398e8702
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html
@@ -0,0 +1,396 @@
+<!doctype html>
+<html>
+ <head>
+ <script src="../resources/js-test.js"></script>
+ <script src="resources/compatibility.js"></script>
+ <script src="resources/audio-testing.js"></script>
+ <title>Test AudioParam Nominal Range Values</title>
+ </head>
+
+ <body>
+ <script>
+ description("Test Automation of SpatialListener Position.");
+ window.jsTestIsAsync = true;
+
+ // Some arbitrary sample rate for the offline context.
+ var sampleRate = 48000;
+
+ // The actual offline context
+ var context;
+
+ // The set of all methods that we've tested for verifying that we tested all of the necessary
+ // objects.
+ var testedMethods = new Set();
+
+ // The most positive single float value (the value just before infinity). Be careful when
+ // changing this value! Javascript only uses double floats, so the value here should be the
+ // max single-float value, converted directly to a double-float value. This also depends on
+ // Javascript reading this value and producing the desired double-float value correctly.
+ var mostPositiveFloat = 3.4028234663852886e38;
+
+ var audit = Audit.createTaskRunner();
+
+ // Array describing the tests that should be run.
+ var testConfigs = [{
+ // The name of the method to create the particular node to be tested.
+ creator: "createGain",
+
+ // Any args to pass to the creator function.
+ args: [],
+
+ // The min/max limits for each AudioParam of the node. This is a dictionary whose keys are
+ // the names of each AudioParam in the node. Don't define this if the node doesn't have any
+ // AudioParam attributes.
+ limits: {
+ gain: {
+ // The expected min and max values for this AudioParam.
+ minValue: -mostPositiveFloat,
+ maxValue: mostPositiveFloat
+ }
+ }
+ }, {
+ creator: "createDelay",
+ // Just specify a non-default value for the maximum delay so we can make sure the limits are
+ // set correctly.
+ args: [1.5],
+ limits: {
+ delayTime: {
+ minValue: 0,
+ maxValue: 1.5
+ }
+ }
+ }, {
+ creator: "createBufferSource",
+ args: [],
+ limits: {
+ playbackRate: {
+ minValue: -mostPositiveFloat,
+ maxValue: mostPositiveFloat
+ },
+ detune: {
+ minValue: -mostPositiveFloat,
+ maxValue: mostPositiveFloat
+ }
+ }
+ }, {
+ creator: "createStereoPanner",
+ args: [],
+ limits: {
+ pan: {
+ minValue: -1,
+ maxValue: 1
+ }
+ }
+ }, {
+ creator: "createDynamicsCompressor",
+ args: [],
+ // Do not set limits for reduction; it's currently an AudioParam but should be a float.
+ // So let the test fail for reduction. When reduction is changed, this test will then
+ // correctly pass.
+ limits: {
+ threshold: {
+ minValue: -100,
+ maxValue: 0
+ },
+ knee: {
+ minValue: 0,
+ maxValue: 40
+ },
+ ratio: {
+ minValue: 1,
+ maxValue: 20
+ },
+ attack: {
+ minValue: 0,
+ maxValue: 1
+ },
+ release: {
+ minValue: 0,
+ maxValue: 1
+ }
+ }
+ },
+ {
+ creator: "createBiquadFilter",
+ args: [],
+ limits: {
+ gain: {
+ minValue: -mostPositiveFloat,
+ maxValue: mostPositiveFloat
+ },
+ Q: {
+ minValue: -mostPositiveFloat,
+ maxValue: mostPositiveFloat
+ },
+ frequency: {
+ minValue: 0,
+ maxValue: sampleRate / 2
+ },
+ detune: {
+ minValue: -mostPositiveFloat,
+ maxValue: mostPositiveFloat
+ }
+ }
+ }, {
+ creator: "createOscillator",
+ args: [],
+ limits: {
+ frequency: {
+ minValue: 0,
+ maxValue: sampleRate / 2
+ },
+ detune: {
+ minValue: -mostPositiveFloat,
+ maxValue: mostPositiveFloat
+ }
+ }
+ },
+ // These nodes don't have AudioParams, but we want to test them anyway. Any arguments for the
+ // constructor are pretty much arbitrary; they just need to be valid.
+ {
+ creator: "createBuffer",
+ args: [1, 1, sampleRate],
+ }, {
+ creator: "createIIRFilter",
+ args: [[1,2],[3,4]]
+ }, {
+ creator: "createWaveShaper",
+ args: [],
+ }, {
+ creator: "createConvolver",
+ args: [],
+ }, {
+ creator: "createAnalyser",
+ args: [],
+ }, {
+ creator: "createScriptProcessor",
+ args: [0],
+ }, {
+ creator: "createPeriodicWave",
+ args: [Float32Array.from([0, 0]), Float32Array.from([1, 0])],
+ }, {
+ creator: "createChannelSplitter",
+ args: [],
+ }, {
+ creator: "createChannelMerger",
+ args: [],
+ }, {
+ creator: "createPanner",
+ args: [],
+ }, {
+ creator: "createMediaElementSource",
+ args: [new Audio()]
+ },{
+ creator: "createMediaStreamDestination",
+ args: []
+ }
+ // Can't currently test MediaStreamSource
+ ];
+
+ // Create the context so we can use it in the following test.
+ audit.defineTask("initialize", function (done) {
+ // Just any context so that we can create the nodes.
+ context = new OfflineAudioContext(1, 1, sampleRate);
+ done();
+ });
+
+ // Create a task for each entry in testConfigs
+ for (var test in testConfigs) {
+ var config = testConfigs[test]
+ audit.defineTask(config.creator, (function (c) {
+ return function (done) {
+ var node = context[c.creator](...c.args);
+ testLimits(c.creator, node, c.limits);
+ done();
+ };
+ })(config));
+ }
+
+ // Verify that we have tested all the create methods available on the context.
+ audit.defineTask("verifyTests", function (done) {
+ var allNodes = new Set();
+ // Create the set of all "create" methods from the context.
+ for (var method in context) {
+ if (typeof context[method] === "function" && method.substring(0, 6) === "create") {
+ allNodes.add(method);
+ }
+ }
+
+ // Compute the difference between the set of all create methods on the context and the set
+ // of tests that we've run.
+ var diff = new Set([...allNodes].filter(x => !testedMethods.has(x)));
+
+ // Can't currently test a MediaStreamSourceNode, so remove it from the diff set.
+ diff.delete("createMediaStreamSource");
+
+ // It's a test failure if we didn't test all of the create methods in the context (except
+ // createMediaStreamSource, of course).
+ if (diff.size) {
+ var output = [];
+ for (let item of diff)
+ output.push(" " + item.substring(6));
+ testFailed("These nodes were not tested:" + output + "\n");
+ } else {
+ testPassed("All nodes were tested.\n");
+ }
+
+ done();
+ });
+
+ // Simple test of a few automation methods to verify we get warnings.
+ audit.defineTask("automation", function (done) {
+ // Just use a DelayNode for testing because the audio param has finite limits.
+ var d = context.createDelay();
+
+ // The console output should have the warnings that we're interested in.
+ d.delayTime.setValueAtTime(-1, 0);
+ d.delayTime.linearRampToValueAtTime(2, 1);
+ d.delayTime.exponentialRampToValueAtTime(3, 2);
+ d.delayTime.setTargetAtTime(-1, 3, .1);
+ d.delayTime.setValueCurveAtTime(Float32Array.from([.1, .2, 1.5, -1]), 4, .1);
+ done();
+ });
+
+ // All done!
+ audit.defineTask("finish", function (done) {
+ finishJSTest();
+ done();
+ });
+
+ audit.runTasks();
+
+ // Is |object| an AudioParam? We determine this by checking the constructor name.
+ function isAudioParam(object) {
+ return object && object.constructor.name === "AudioParam";
+ }
+
+ // Does |limitOptions| exist and does it have valid values for the expected min and max
+ // values?
+ function hasValidLimits(limitOptions) {
+ return limitOptions && (typeof limitOptions.minValue === "number") && (typeof limitOptions.maxValue === "number");
+ }
+
+ // Check the min and max values for the AudioParam attribute named |paramName| for the |node|.
+ // The expected limits is given by the dictionary |limits|. If some test fails, add the name
+ // of the failed
+ function validateAudioParamLimits(node, paramName, limits) {
+ var nodeName = node.constructor.name;
+ var parameter = node[paramName];
+ var prefix = nodeName + "." + paramName;
+
+ var success = true;
+ if (hasValidLimits(limits[paramName])) {
+ // Verify that the min and max values for the parameter are correct.
+ var isCorrect = Should(prefix + ".minValue", parameter.minValue)
+ .beEqualTo(limits[paramName].minValue);
+ isCorrect = Should(prefix + ".maxValue", parameter.maxValue)
+ .beEqualTo(limits[paramName].maxValue) && isCorrect;
+
+ // Verify that the min and max attributes are read-only
+ parameter.minValue = Math.PI;
+ var isReadOnly;
+ isReadOnly = Should(prefix + ".minValue = Math.PI", parameter.minValue)
+ .notBeEqualTo(Math.PI);
+ if (isReadOnly)
+ testPassed(prefix + ".minValue is read-only.");
+ else
+ testFailed(prefix + ".minValue should be read-only but was changed.");
+ isCorrect = isReadOnly && isCorrect;
+
+ parameter.maxValue = Math.PI;
+ isReadOnly = Should(prefix + ".maxValue = Math.PI", parameter.maxValue)
+ .notBeEqualTo(Math.PI);
+ if (isReadOnly)
+ testPassed(prefix + ".maxValue is read-only.");
+ else
+ testFailed(prefix + ".maxValue should be read-only but was changed.");
+ isCorrect = isReadOnly && isCorrect;
+
+ // Now try to set the parameter outside the nominal range.
+ var newValue = 2 * limits[paramName].minValue - 1;
+
+ var isClipped = true;
+ var clippingTested = false;
+ // If the new value is beyond float the largest single-precision float, skip the test
+ // because Chrome throws an error.
+ if (newValue >= -mostPositiveFloat) {
+ parameter.value = newValue;
+ clippingTested = true;
+ isClipped = Should("Set " + prefix + ".value = " + newValue, parameter.value)
+ .beEqualTo(parameter.minValue) && isClipped;
+ }
+
+ newValue = 2 * limits[paramName].maxValue + 1;
+
+ if (newValue <= mostPositiveFloat) {
+ parameter.value = newValue;
+ clippingTested = true;
+ isClipped = Should("Set " + prefix + ".value = " + newValue, parameter.value)
+ .beEqualTo(parameter.maxValue) && isClipped;
+
+ }
+
+ if (clippingTested) {
+ if (isClipped)
+ testPassed(prefix + " was correctly clipped to lie within the nominal range.")
+ else
+ testPassed(prefix + " was not correctly clipped to lie within the nominal range.")
+ }
+
+ isCorrect = isCorrect && isClipped;
+
+ success = isCorrect && success;
+ } else {
+ // Test config didn't specify valid limits. Fail this test!
+ testFailed("Limits for " + nodeName + "." + paramName + " were not correctly defined.");
+ success = false;
+ }
+
+ return success;
+ }
+
+ // Test all of the AudioParams for |node| using the expected values in |limits|.
+ // |creatorName| is the name of the method to create the node, and is used to keep trakc of
+ // which tests we've run.
+ function testLimits(creatorName, node, limits) {
+ var nodeName = node.constructor.name;
+ testedMethods.add(creatorName);
+
+ var success = true;
+
+ // List of all of the AudioParams that were tested.
+ var audioParams = [];
+
+ // List of AudioParams that failed the test.
+ var incorrectParams = [];
+
+ // Look through all of the keys for the node and extract just the AudioParams
+ Object.keys(node.__proto__).forEach(function (paramName) {
+ if (isAudioParam(node[paramName])) {
+ audioParams.push(paramName);
+ var isValid = validateAudioParamLimits(node, paramName, limits, incorrectParams);
+ if (!isValid)
+ incorrectParams.push(paramName);
+
+ success = isValid && success;
+ }
+ });
+
+ // Print an appropriate message depending on whether there were AudioParams defined or not.
+ if (audioParams.length) {
+ var message = "Nominal ranges for AudioParam(s) of " + node.constructor.name;
+ if (success)
+ testPassed(message + " are correct.\n");
+ else
+ testFailed(message + " are incorrect for: " + incorrectParams + ".\n");
+ return success;
+ } else {
+ if (limits)
+ testFailed(nodeName + " has no AudioParams but test expected " + limits + ".\n");
+ else
+ testPassed(nodeName + " has no AudioParams as expected.\n");
+ }
+ }
+ </script>
+ </body>
+</html>

Powered by Google App Engine
This is Rietveld 408576698