OLD | NEW |
1 <!doctype html> | 1 <!doctype html> |
2 <html> | 2 <html> |
3 <head> | 3 <head> |
4 <title>Test Clamping of Distance for PannerNode</title> | 4 <title>Test Clamping of Distance for PannerNode</title> |
5 <script src="../../resources/testharness.js"></script> | 5 <script src="../../resources/testharness.js"></script> |
6 <script src="../../resources/testharnessreport.js"></script> | 6 <script src="../../resources/testharnessreport.js"></script> |
7 <script src="../resources/audit-util.js"></script> | 7 <script src="../resources/audit-util.js"></script> |
8 <script src="../resources/audio-testing.js"></script> | 8 <script src="../resources/audit.js"></script> |
9 </head> | 9 </head> |
10 | 10 |
11 <body> | 11 <body> |
12 <script> | 12 <script> |
13 // Arbitrary sample rate and render length. | 13 // Arbitrary sample rate and render length. |
14 var sampleRate = 48000; | 14 var sampleRate = 48000; |
15 var renderFrames = 128; | 15 var renderFrames = 128; |
16 | 16 |
17 var audit = Audit.createTaskRunner(); | 17 var audit = Audit.createTaskRunner(); |
18 | 18 |
19 audit.defineTask("ref-distance-error", function (taskDone) { | 19 audit.define("ref-distance-error", (task, should) => { |
20 testDistanceLimits({name: "refDistance", isZeroAllowed: true}); | 20 testDistanceLimits(should, {name: "refDistance"}); |
21 taskDone(); | 21 task.done(); |
22 }); | 22 }); |
23 | 23 |
24 audit.defineTask("max-distance-error", function (taskDone) { | 24 audit.define("max-distance-error", (task, should) => { |
25 testDistanceLimits({name: "maxDistance", isZeroAllowed: false}); | 25 testDistanceLimits(should, {name: "maxDistance"}); |
26 taskDone(); | 26 task.done(); |
27 }); | 27 }); |
28 | 28 |
29 function testDistanceLimits(options) { | 29 function testDistanceLimits(should, options) { |
30 // Verify that exceptions are thrown for invalid values of refDistance. | 30 // Verify that exceptions are thrown for invalid values of refDistance. |
31 var context = new OfflineAudioContext(1, renderFrames, sampleRate); | 31 var context = new OfflineAudioContext(1, renderFrames, sampleRate); |
32 | 32 |
33 var attrName = options.name; | 33 var attrName = options.name; |
34 var prefix = "new PannerNode(c, {" + attrName + ": "; | 34 var prefix = "new PannerNode(c, {" + attrName + ": "; |
35 | 35 |
36 success = Should(prefix + "-1})", function () { | 36 should(function () { |
37 var nodeOptions = {}; | 37 var nodeOptions = {}; |
38 nodeOptions[attrName] = -1; | 38 nodeOptions[attrName] = -1; |
39 new PannerNode(context, nodeOptions); | 39 new PannerNode(context, nodeOptions); |
40 }).throw("RangeError"); | 40 }, prefix + "-1})").throw("RangeError"); |
41 | 41 |
42 if (options.isZeroAllowed) { | 42 should(function () { |
43 success = Should(prefix + "0})", function () { | 43 var nodeOptions = {}; |
44 var nodeOptions = {}; | 44 nodeOptions[attrName] = 0; |
45 nodeOptions[attrName] = 0; | 45 new PannerNode(context, nodeOptions); |
46 new PannerNode(context, nodeOptions); | 46 }, prefix + "0})").throw("RangeError"); |
47 }).notThrow() && success; | |
48 } else { | |
49 success = Should(prefix + "0})", function () { | |
50 var nodeOptions = {}; | |
51 nodeOptions[attrName] = 0; | |
52 new PannerNode(context, nodeOptions); | |
53 }).throw("RangeError") && success; | |
54 } | |
55 | 47 |
56 // The smallest representable positive single float. | 48 // The smallest representable positive single float. |
57 var leastPositiveDoubleFloat = 4.9406564584124654e-324; | 49 var leastPositiveDoubleFloat = 4.9406564584124654e-324; |
58 | 50 |
59 success = Should(prefix + leastPositiveDoubleFloat + "})", | 51 should( |
60 function () { | 52 function () { |
61 var nodeOptions = {}; | 53 var nodeOptions = {}; |
62 nodeOptions[attrName] = leastPositiveDoubleFloat; | 54 nodeOptions[attrName] = leastPositiveDoubleFloat; |
63 new PannerNode(context, nodeOptions); | 55 new PannerNode(context, nodeOptions); |
64 }).notThrow() && success; | 56 }, prefix + leastPositiveDoubleFloat + "})") |
| 57 .notThrow(); |
65 | 58 |
66 prefix = "panner." + attrName + " = "; | 59 prefix = "panner." + attrName + " = "; |
67 panner = new PannerNode(context); | 60 panner = new PannerNode(context); |
68 success = Should(prefix + "-1", function () { | 61 should(function () { |
69 panner[attrName] = -1; | 62 panner[attrName] = -1; |
70 }).throw("RangeError") && success; | 63 }, prefix + "-1").throw("RangeError"); |
71 | 64 |
72 if (options.isZeroAllowed) { | 65 should(function () { |
73 success = Should(prefix + "0", function () { | 66 panner[attrName] = 0; |
74 panner[attrName] = 0; | 67 }, prefix + "0").throw("RangeError"); |
75 }).notThrow() && success; | |
76 } else { | |
77 success = Should(prefix + "0", function () { | |
78 panner[attrName] = 0; | |
79 }).throw("RangeError") && success; | |
80 } | |
81 | 68 |
82 success = Should(prefix + leastPositiveDoubleFloat, function () { | 69 should(function () { |
83 panner[attrName] = leastPositiveDoubleFloat; | 70 panner[attrName] = leastPositiveDoubleFloat; |
84 }).notThrow() && success; | 71 }, prefix + leastPositiveDoubleFloat).notThrow(); |
85 | |
86 Should("Invalid " + attrName + " values handled", success) | |
87 .summarize("correctly", "incorrectly"); | |
88 | |
89 } | 72 } |
90 | 73 |
91 audit.defineTask("min-distance", function (taskDone) { | 74 audit.define("min-distance", (task, should) => { |
92 // Test clamping of panner distance to refDistance for all of the | 75 // Test clamping of panner distance to refDistance for all of the |
93 // distance models. The actual distance is arbitrary as long as it's | 76 // distance models. The actual distance is arbitrary as long as it's |
94 // less than refDistance. We test default and non-default values for | 77 // less than refDistance. We test default and non-default values for |
95 // the panner's refDistance and maxDistance. | 78 // the panner's refDistance and maxDistance. |
96 // correctly. | 79 // correctly. |
97 Promise.all([ | 80 Promise.all([ |
98 runTest({ | 81 runTest(should, { |
99 distance: 0.01, | 82 distance: 0.01, |
100 distanceModel: "linear", | 83 distanceModel: "linear", |
101 }), | 84 }), |
102 runTest({ | 85 runTest(should, { |
103 distance: 0.01, | 86 distance: 0.01, |
104 distanceModel: "exponential", | 87 distanceModel: "exponential", |
105 }), | 88 }), |
106 runTest({ | 89 runTest(should, { |
107 distance: 0.01, | 90 distance: 0.01, |
108 distanceModel: "inverse", | 91 distanceModel: "inverse", |
109 }), | 92 }), |
110 runTest({ | 93 runTest(should, { |
111 distance: 2, | 94 distance: 2, |
112 distanceModel: "linear", | 95 distanceModel: "linear", |
113 maxDistance: 1000, | 96 maxDistance: 1000, |
114 refDistance: 10, | 97 refDistance: 10, |
115 }), | 98 }), |
116 runTest({ | 99 runTest(should, { |
117 distance: 2, | 100 distance: 2, |
118 distanceModel: "exponential", | 101 distanceModel: "exponential", |
119 maxDistance: 1000, | 102 maxDistance: 1000, |
120 refDistance: 10, | 103 refDistance: 10, |
121 }), | 104 }), |
122 runTest({ | 105 runTest(should, { |
123 distance: 2, | 106 distance: 2, |
124 distanceModel: "inverse", | 107 distanceModel: "inverse", |
125 maxDistance: 1000, | 108 maxDistance: 1000, |
126 refDistance: 10, | 109 refDistance: 10, |
127 }), | 110 }), |
128 ]).then(taskDone); | 111 ]) |
| 112 .then(() => task.done()); |
129 }); | 113 }); |
130 | 114 |
131 audit.defineTask("max-distance", function (taskDone) { | 115 audit.define("max-distance", (task, should) => { |
132 // Like the "min-distance" task, but for clamping to the max | 116 // Like the "min-distance" task, but for clamping to the max |
133 // distance. The actual distance is again arbitrary as long as it is | 117 // distance. The actual distance is again arbitrary as long as it is |
134 // greater than maxDistance. | 118 // greater than maxDistance. |
135 Promise.all([ | 119 Promise.all([ |
136 runTest({ | 120 runTest(should, { |
137 distance: 20000, | 121 distance: 20000, |
138 distanceModel: "linear", | 122 distanceModel: "linear", |
139 }), | 123 }), |
140 runTest({ | 124 runTest(should, { |
141 distance: 21000, | 125 distance: 21000, |
142 distanceModel: "exponential", | 126 distanceModel: "exponential", |
143 }), | 127 }), |
144 runTest({ | 128 runTest(should, { |
145 distance: 23000, | 129 distance: 23000, |
146 distanceModel: "inverse", | 130 distanceModel: "inverse", |
147 }), | 131 }), |
148 runTest({ | 132 runTest(should, { |
149 distance: 5000, | 133 distance: 5000, |
150 distanceModel: "linear", | 134 distanceModel: "linear", |
151 maxDistance: 1000, | 135 maxDistance: 1000, |
152 refDistance: 10, | 136 refDistance: 10, |
153 }), | 137 }), |
154 runTest({ | 138 runTest(should, { |
155 distance: 5000, | 139 distance: 5000, |
156 distanceModel: "exponential", | 140 distanceModel: "exponential", |
157 maxDistance: 1000, | 141 maxDistance: 1000, |
158 refDistance: 10, | 142 refDistance: 10, |
159 }), | 143 }), |
160 runTest({ | 144 runTest(should, { |
161 distance: 5000, | 145 distance: 5000, |
162 distanceModel: "inverse", | 146 distanceModel: "inverse", |
163 maxDistance: 1000, | 147 maxDistance: 1000, |
164 refDistance: 10, | 148 refDistance: 10, |
165 }), | 149 }), |
166 ]).then(taskDone); | 150 ]) |
| 151 .then(() => task.done()); |
167 }); | 152 }); |
168 | 153 |
169 function runTest(options) { | 154 function runTest(should, options) { |
170 var context = new OfflineAudioContext(2, renderFrames, sampleRate); | 155 var context = new OfflineAudioContext(2, renderFrames, sampleRate); |
171 var src = new OscillatorNode(context, { | 156 var src = new OscillatorNode(context, { |
172 type: "sawtooth", | 157 type: "sawtooth", |
173 frequency: 20*440, | 158 frequency: 20*440, |
174 }); | 159 }); |
175 | 160 |
176 // Set panner options. Use a non-default rolloffFactor so that the | 161 // Set panner options. Use a non-default rolloffFactor so that the |
177 // various distance models look distinctly different. | 162 // various distance models look distinctly different. |
178 var pannerOptions = {}; | 163 var pannerOptions = {}; |
179 Object.assign(pannerOptions, options, {rolloffFactor: 0.5}); | 164 Object.assign(pannerOptions, options, {rolloffFactor: 0.5}); |
(...skipping 25 matching lines...) Expand all Loading... |
205 | 190 |
206 pannerRef.positionZ.setValueAtTime(xRef, 0); | 191 pannerRef.positionZ.setValueAtTime(xRef, 0); |
207 pannerTest.positionZ.setValueAtTime(xTest, 0); | 192 pannerTest.positionZ.setValueAtTime(xTest, 0); |
208 | 193 |
209 src.start(); | 194 src.start(); |
210 | 195 |
211 return context.startRendering().then(function (resultBuffer) { | 196 return context.startRendering().then(function (resultBuffer) { |
212 var actual = resultBuffer.getChannelData(0); | 197 var actual = resultBuffer.getChannelData(0); |
213 var expected = resultBuffer.getChannelData(1); | 198 var expected = resultBuffer.getChannelData(1); |
214 | 199 |
215 Should("Model: " + options.distanceModel + ": Distance (" + xTest + ")
is outside the range [" + | 200 should(xTest < pannerRef.refDistance || xTest > pannerRef.maxDistance, |
216 pannerRef.refDistance + ", " + pannerRef.maxDistance + "]", | 201 "Model: " + options.distanceModel + ": Distance (" + xTest + |
217 xTest < pannerRef.refDistance || xTest > pannerRef.maxDistance) | 202 ") is outside the range [" + pannerRef.refDistance + ", " + |
| 203 pannerRef.maxDistance + "]") |
218 .beEqualTo(true); | 204 .beEqualTo(true); |
219 Should("Test panner output " + JSON.stringify(options), actual) | 205 should(actual, "Test panner output " + JSON.stringify(options)) |
220 .beEqualToArray(expected); | 206 .beEqualToArray(expected); |
221 }); | 207 }); |
222 } | 208 } |
223 | 209 |
224 audit.runTasks(); | 210 audit.run(); |
225 </script> | 211 </script> |
226 </body> | 212 </body> |
227 </html> | 213 </html> |
OLD | NEW |