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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 <!doctype html>
2 <html>
3 <head>
4 <script src="../resources/js-test.js"></script>
5 <script src="resources/compatibility.js"></script>
6 <script src="resources/audio-testing.js"></script>
7 <title>Test AudioParam Nominal Range Values</title>
8 </head>
9
10 <body>
11 <script>
12 description("Test Automation of SpatialListener Position.");
13 window.jsTestIsAsync = true;
14
15 // Some arbitrary sample rate for the offline context.
16 var sampleRate = 48000;
17
18 // The actual offline context
19 var context;
20
21 // The set of all methods that we've tested for verifying that we tested a ll of the necessary
22 // objects.
23 var testedMethods = new Set();
24
25 // The most positive single float value (the value just before infinity). Be careful when
26 // changing this value! Javascript only uses double floats, so the value here should be the
27 // max single-float value, converted directly to a double-float value. Th is also depends on
28 // Javascript reading this value and producing the desired double-float va lue correctly.
29 var mostPositiveFloat = 3.4028234663852886e38;
30
31 var audit = Audit.createTaskRunner();
32
33 // Array describing the tests that should be run.
34 var testConfigs = [{
35 // The name of the method to create the particular node to be tested.
36 creator: "createGain",
37
38 // Any args to pass to the creator function.
39 args: [],
40
41 // The min/max limits for each AudioParam of the node. This is a dictio nary whose keys are
42 // the names of each AudioParam in the node. Don't define this if the n ode doesn't have any
43 // AudioParam attributes.
44 limits: {
45 gain: {
46 // The expected min and max values for this AudioParam.
47 minValue: -mostPositiveFloat,
48 maxValue: mostPositiveFloat
49 }
50 }
51 }, {
52 creator: "createDelay",
53 // Just specify a non-default value for the maximum delay so we can make sure the limits are
54 // set correctly.
55 args: [1.5],
56 limits: {
57 delayTime: {
58 minValue: 0,
59 maxValue: 1.5
60 }
61 }
62 }, {
63 creator: "createBufferSource",
64 args: [],
65 limits: {
66 playbackRate: {
67 minValue: -mostPositiveFloat,
68 maxValue: mostPositiveFloat
69 },
70 detune: {
71 minValue: -mostPositiveFloat,
72 maxValue: mostPositiveFloat
73 }
74 }
75 }, {
76 creator: "createStereoPanner",
77 args: [],
78 limits: {
79 pan: {
80 minValue: -1,
81 maxValue: 1
82 }
83 }
84 }, {
85 creator: "createDynamicsCompressor",
86 args: [],
87 // Do not set limits for reduction; it's currently an AudioParam but sh ould be a float.
88 // So let the test fail for reduction. When reduction is changed, this test will then
89 // correctly pass.
90 limits: {
91 threshold: {
92 minValue: -100,
93 maxValue: 0
94 },
95 knee: {
96 minValue: 0,
97 maxValue: 40
98 },
99 ratio: {
100 minValue: 1,
101 maxValue: 20
102 },
103 attack: {
104 minValue: 0,
105 maxValue: 1
106 },
107 release: {
108 minValue: 0,
109 maxValue: 1
110 }
111 }
112 },
113 {
114 creator: "createBiquadFilter",
115 args: [],
116 limits: {
117 gain: {
118 minValue: -mostPositiveFloat,
119 maxValue: mostPositiveFloat
120 },
121 Q: {
122 minValue: -mostPositiveFloat,
123 maxValue: mostPositiveFloat
124 },
125 frequency: {
126 minValue: 0,
127 maxValue: sampleRate / 2
128 },
129 detune: {
130 minValue: -mostPositiveFloat,
131 maxValue: mostPositiveFloat
132 }
133 }
134 }, {
135 creator: "createOscillator",
136 args: [],
137 limits: {
138 frequency: {
139 minValue: 0,
140 maxValue: sampleRate / 2
141 },
142 detune: {
143 minValue: -mostPositiveFloat,
144 maxValue: mostPositiveFloat
145 }
146 }
147 },
148 // These nodes don't have AudioParams, but we want to test them anyway. A ny arguments for the
149 // constructor are pretty much arbitrary; they just need to be valid.
150 {
151 creator: "createBuffer",
152 args: [1, 1, sampleRate],
153 }, {
154 creator: "createIIRFilter",
155 args: [[1,2],[3,4]]
156 }, {
157 creator: "createWaveShaper",
158 args: [],
159 }, {
160 creator: "createConvolver",
161 args: [],
162 }, {
163 creator: "createAnalyser",
164 args: [],
165 }, {
166 creator: "createScriptProcessor",
167 args: [0],
168 }, {
169 creator: "createPeriodicWave",
170 args: [Float32Array.from([0, 0]), Float32Array.from([1, 0])],
171 }, {
172 creator: "createChannelSplitter",
173 args: [],
174 }, {
175 creator: "createChannelMerger",
176 args: [],
177 }, {
178 creator: "createPanner",
179 args: [],
180 }, {
181 creator: "createMediaElementSource",
182 args: [new Audio()]
183 },{
184 creator: "createMediaStreamDestination",
185 args: []
186 }
187 // Can't currently test MediaStreamSource
188 ];
189
190 // Create the context so we can use it in the following test.
191 audit.defineTask("initialize", function (done) {
192 // Just any context so that we can create the nodes.
193 context = new OfflineAudioContext(1, 1, sampleRate);
194 done();
195 });
196
197 // Create a task for each entry in testConfigs
198 for (var test in testConfigs) {
199 var config = testConfigs[test]
200 audit.defineTask(config.creator, (function (c) {
201 return function (done) {
202 var node = context[c.creator](...c.args);
203 testLimits(c.creator, node, c.limits);
204 done();
205 };
206 })(config));
207 }
208
209 // Verify that we have tested all the create methods available on the cont ext.
210 audit.defineTask("verifyTests", function (done) {
211 var allNodes = new Set();
212 // Create the set of all "create" methods from the context.
213 for (var method in context) {
214 if (typeof context[method] === "function" && method.substring(0, 6) == = "create") {
215 allNodes.add(method);
216 }
217 }
218
219 // Compute the difference between the set of all create methods on the c ontext and the set
220 // of tests that we've run.
221 var diff = new Set([...allNodes].filter(x => !testedMethods.has(x)));
222
223 // Can't currently test a MediaStreamSourceNode, so remove it from the d iff set.
224 diff.delete("createMediaStreamSource");
225
226 // It's a test failure if we didn't test all of the create methods in th e context (except
227 // createMediaStreamSource, of course).
228 if (diff.size) {
229 var output = [];
230 for (let item of diff)
231 output.push(" " + item.substring(6));
232 testFailed("These nodes were not tested:" + output + "\n");
233 } else {
234 testPassed("All nodes were tested.\n");
235 }
236
237 done();
238 });
239
240 // Simple test of a few automation methods to verify we get warnings.
241 audit.defineTask("automation", function (done) {
242 // Just use a DelayNode for testing because the audio param has finite l imits.
243 var d = context.createDelay();
244
245 // The console output should have the warnings that we're interested in.
246 d.delayTime.setValueAtTime(-1, 0);
247 d.delayTime.linearRampToValueAtTime(2, 1);
248 d.delayTime.exponentialRampToValueAtTime(3, 2);
249 d.delayTime.setTargetAtTime(-1, 3, .1);
250 d.delayTime.setValueCurveAtTime(Float32Array.from([.1, .2, 1.5, -1]), 4, .1);
251 done();
252 });
253
254 // All done!
255 audit.defineTask("finish", function (done) {
256 finishJSTest();
257 done();
258 });
259
260 audit.runTasks();
261
262 // Is |object| an AudioParam? We determine this by checking the construct or name.
263 function isAudioParam(object) {
264 return object && object.constructor.name === "AudioParam";
265 }
266
267 // Does |limitOptions| exist and does it have valid values for the expecte d min and max
268 // values?
269 function hasValidLimits(limitOptions) {
270 return limitOptions && (typeof limitOptions.minValue === "number") && (t ypeof limitOptions.maxValue === "number");
271 }
272
273 // Check the min and max values for the AudioParam attribute named |paramN ame| for the |node|.
274 // The expected limits is given by the dictionary |limits|. If some test fails, add the name
275 // of the failed
276 function validateAudioParamLimits(node, paramName, limits) {
277 var nodeName = node.constructor.name;
278 var parameter = node[paramName];
279 var prefix = nodeName + "." + paramName;
280
281 var success = true;
282 if (hasValidLimits(limits[paramName])) {
283 // Verify that the min and max values for the parameter are correct.
284 var isCorrect = Should(prefix + ".minValue", parameter.minValue)
285 .beEqualTo(limits[paramName].minValue);
286 isCorrect = Should(prefix + ".maxValue", parameter.maxValue)
287 .beEqualTo(limits[paramName].maxValue) && isCorrect;
288
289 // Verify that the min and max attributes are read-only
290 parameter.minValue = Math.PI;
291 var isReadOnly;
292 isReadOnly = Should(prefix + ".minValue = Math.PI", parameter.minValue )
293 .notBeEqualTo(Math.PI);
294 if (isReadOnly)
295 testPassed(prefix + ".minValue is read-only.");
296 else
297 testFailed(prefix + ".minValue should be read-only but was changed." );
298 isCorrect = isReadOnly && isCorrect;
299
300 parameter.maxValue = Math.PI;
301 isReadOnly = Should(prefix + ".maxValue = Math.PI", parameter.maxValue )
302 .notBeEqualTo(Math.PI);
303 if (isReadOnly)
304 testPassed(prefix + ".maxValue is read-only.");
305 else
306 testFailed(prefix + ".maxValue should be read-only but was changed." );
307 isCorrect = isReadOnly && isCorrect;
308
309 // Now try to set the parameter outside the nominal range.
310 var newValue = 2 * limits[paramName].minValue - 1;
311
312 var isClipped = true;
313 var clippingTested = false;
314 // If the new value is beyond float the largest single-precision float , skip the test
315 // because Chrome throws an error.
316 if (newValue >= -mostPositiveFloat) {
317 parameter.value = newValue;
318 clippingTested = true;
319 isClipped = Should("Set " + prefix + ".value = " + newValue, paramet er.value)
320 .beEqualTo(parameter.minValue) && isClipped;
321 }
322
323 newValue = 2 * limits[paramName].maxValue + 1;
324
325 if (newValue <= mostPositiveFloat) {
326 parameter.value = newValue;
327 clippingTested = true;
328 isClipped = Should("Set " + prefix + ".value = " + newValue, paramet er.value)
329 .beEqualTo(parameter.maxValue) && isClipped;
330
331 }
332
333 if (clippingTested) {
334 if (isClipped)
335 testPassed(prefix + " was correctly clipped to lie within the nomi nal range.")
336 else
337 testPassed(prefix + " was not correctly clipped to lie within the nominal range.")
338 }
339
340 isCorrect = isCorrect && isClipped;
341
342 success = isCorrect && success;
343 } else {
344 // Test config didn't specify valid limits. Fail this test!
345 testFailed("Limits for " + nodeName + "." + paramName + " were not cor rectly defined.");
346 success = false;
347 }
348
349 return success;
350 }
351
352 // Test all of the AudioParams for |node| using the expected values in |li mits|.
353 // |creatorName| is the name of the method to create the node, and is used to keep trakc of
354 // which tests we've run.
355 function testLimits(creatorName, node, limits) {
356 var nodeName = node.constructor.name;
357 testedMethods.add(creatorName);
358
359 var success = true;
360
361 // List of all of the AudioParams that were tested.
362 var audioParams = [];
363
364 // List of AudioParams that failed the test.
365 var incorrectParams = [];
366
367 // Look through all of the keys for the node and extract just the AudioP arams
368 Object.keys(node.__proto__).forEach(function (paramName) {
369 if (isAudioParam(node[paramName])) {
370 audioParams.push(paramName);
371 var isValid = validateAudioParamLimits(node, paramName, limits, inco rrectParams);
372 if (!isValid)
373 incorrectParams.push(paramName);
374
375 success = isValid && success;
376 }
377 });
378
379 // Print an appropriate message depending on whether there were AudioPar ams defined or not.
380 if (audioParams.length) {
381 var message = "Nominal ranges for AudioParam(s) of " + node.constructo r.name;
382 if (success)
383 testPassed(message + " are correct.\n");
384 else
385 testFailed(message + " are incorrect for: " + incorrectParams + ".\n ");
386 return success;
387 } else {
388 if (limits)
389 testFailed(nodeName + " has no AudioParams but test expected " + lim its + ".\n");
390 else
391 testPassed(nodeName + " has no AudioParams as expected.\n");
392 }
393 }
394 </script>
395 </body>
396 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698