OLD | NEW |
(Empty) | |
| 1 <!doctype html> |
| 2 <html> |
| 3 <head> |
| 4 <title>Test Processing Of AudioParams of Disconnected AudioNodes</title> |
| 5 <script src="../../resources/testharness.js"></script> |
| 6 <script src="../../resources/testharnessreport.js"></script> |
| 7 <script src="../resources/audio-testing.js"></script> |
| 8 </head> |
| 9 |
| 10 <body> |
| 11 <script> |
| 12 // Arbitrary sample rate. |
| 13 var sampleRate = 8000; |
| 14 |
| 15 // Arbitrary number of frames for the test, except it must be greater than |
| 16 // |automationEndFrame|. |
| 17 var renderFrames = 1024; |
| 18 |
| 19 // The linear ramp automation ends at this frame. Arbitrary, except it |
| 20 // must be strictly less than the render length. |
| 21 var automationEndFrame = 128; |
| 22 |
| 23 var audit = Audit.createTaskRunner(); |
| 24 |
| 25 // There should be a test for every single node which has an AudioParam. |
| 26 // Source nodes are not included in this because the AudioParams for the |
| 27 // source nodes only process when the node has been started. |
| 28 |
| 29 audit.defineTask("BiquadFilterNode", function (taskDone) { |
| 30 var nodeName = "BiquadFilterNode" |
| 31 Promise.all([ |
| 32 testParamAutomation({ |
| 33 nodeName: nodeName, |
| 34 paramName: "Q", |
| 35 initialValue: 2, |
| 36 rampFinalValue: 5 |
| 37 }), |
| 38 testParamAutomation({ |
| 39 nodeName: nodeName, |
| 40 paramName: "detune", |
| 41 initialValue: 1, |
| 42 rampFinalValue: 0.5 |
| 43 }), |
| 44 testParamAutomation({ |
| 45 nodeName: nodeName, |
| 46 paramName: "frequency", |
| 47 initialValue: 1000, |
| 48 rampFinalValue: 100 |
| 49 }), |
| 50 testParamAutomation({ |
| 51 nodeName: nodeName, |
| 52 paramName: "gain", |
| 53 initialValue: -3, |
| 54 rampFinalValue: 3 |
| 55 }), |
| 56 ]).then(taskDone); |
| 57 }); |
| 58 |
| 59 audit.defineTask("DelayNode", function (taskDone) { |
| 60 testParamAutomation({ |
| 61 nodeName: "DelayNode", |
| 62 paramName: "delayTime", |
| 63 initialValue: 0.25, |
| 64 rampFinalValue: 0.5 |
| 65 }).then(taskDone); |
| 66 }); |
| 67 |
| 68 audit.defineTask("DynamicsCompressorNode", function (taskDone) { |
| 69 var nodeName = "DynamicsCompressorNode"; |
| 70 Promise.all([ |
| 71 testParamAutomation({ |
| 72 nodeName: nodeName, |
| 73 paramName: "attack", |
| 74 initialValue: 0.1, |
| 75 rampFinalValue: 0.5 |
| 76 }), |
| 77 testParamAutomation({ |
| 78 nodeName: nodeName, |
| 79 paramName: "knee", |
| 80 initialValue: 0, |
| 81 rampFinalValue: 25 |
| 82 }), |
| 83 testParamAutomation({ |
| 84 nodeName: nodeName, |
| 85 paramName: "ratio", |
| 86 initialValue: 1, |
| 87 rampFinalValue: 15 |
| 88 }), |
| 89 testParamAutomation({ |
| 90 nodeName: nodeName, |
| 91 paramName: "release", |
| 92 initialValue: 0, |
| 93 rampFinalValue: 0.75 |
| 94 }), |
| 95 testParamAutomation({ |
| 96 nodeName: nodeName, |
| 97 paramName: "threshold", |
| 98 initialValue: -50, |
| 99 rampFinalValue: -10 |
| 100 }) |
| 101 ]).then(taskDone); |
| 102 }); |
| 103 |
| 104 audit.defineTask("GainNode", function (taskDone) { |
| 105 testParamAutomation({ |
| 106 nodeName: "GainNode", |
| 107 paramName: "gain", |
| 108 initialValue: 1, |
| 109 rampFinalValue: 0.5 |
| 110 }).then(taskDone); |
| 111 }); |
| 112 |
| 113 audit.defineTask("PannerNode", function (taskDone) { |
| 114 var nodeName = "PannerNode"; |
| 115 Promise.all([ |
| 116 testParamAutomation({ |
| 117 nodeName: nodeName, |
| 118 paramName: "positionX", |
| 119 initialValue: 0.1, |
| 120 rampFinalValue: 0.5 |
| 121 }), |
| 122 testParamAutomation({ |
| 123 nodeName: nodeName, |
| 124 paramName: "positionY", |
| 125 initialValue: 2, |
| 126 rampFinalValue: 30 |
| 127 }), |
| 128 testParamAutomation({ |
| 129 nodeName: nodeName, |
| 130 paramName: "positionZ", |
| 131 initialValue: 1, |
| 132 rampFinalValue: 15 |
| 133 }), |
| 134 testParamAutomation({ |
| 135 nodeName: nodeName, |
| 136 paramName: "orientationX", |
| 137 initialValue: 0.1, |
| 138 rampFinalValue: 0.5 |
| 139 }), |
| 140 testParamAutomation({ |
| 141 nodeName: nodeName, |
| 142 paramName: "orientationY", |
| 143 initialValue: 2, |
| 144 rampFinalValue: 30 |
| 145 }), |
| 146 testParamAutomation({ |
| 147 nodeName: nodeName, |
| 148 paramName: "orientationZ", |
| 149 initialValue: 1, |
| 150 rampFinalValue: 15 |
| 151 }), |
| 152 ]).then(taskDone); |
| 153 }); |
| 154 |
| 155 audit.defineTask("StereoPannerNode", function (taskDone) { |
| 156 testParamAutomation({ |
| 157 nodeName: "StereoPannerNode", |
| 158 paramName: "pan", |
| 159 initialValue: 1, |
| 160 rampFinalValue: 0.5 |
| 161 }).then(taskDone); |
| 162 }); |
| 163 |
| 164 audit.defineTask("AudioListener", function (taskDone) { |
| 165 Promise.all([ |
| 166 testAudioListener({ |
| 167 paramName: "positionX", |
| 168 initialValue: 1, |
| 169 rampFinalValue: 100 |
| 170 }), |
| 171 testAudioListener({ |
| 172 paramName: "positionY", |
| 173 initialValue: 1, |
| 174 rampFinalValue: 200 |
| 175 }), |
| 176 testAudioListener({ |
| 177 paramName: "positionZ", |
| 178 initialValue: 1, |
| 179 rampFinalValue: 300 |
| 180 }), |
| 181 testAudioListener({ |
| 182 paramName: "forwardX", |
| 183 initialValue: 1, |
| 184 rampFinalValue: -100 |
| 185 }), |
| 186 testAudioListener({ |
| 187 paramName: "forwardY", |
| 188 initialValue: 1, |
| 189 rampFinalValue: -200 |
| 190 }), |
| 191 testAudioListener({ |
| 192 paramName: "forwardZ", |
| 193 initialValue: 1, |
| 194 rampFinalValue: -300 |
| 195 }), |
| 196 testAudioListener({ |
| 197 paramName: "upX", |
| 198 initialValue: 1, |
| 199 rampFinalValue: 99 |
| 200 }), |
| 201 testAudioListener({ |
| 202 paramName: "upY", |
| 203 initialValue: 1, |
| 204 rampFinalValue: 42 |
| 205 }), |
| 206 testAudioListener({ |
| 207 paramName: "upZ", |
| 208 initialValue: 1, |
| 209 rampFinalValue: 137 |
| 210 }), |
| 211 ]).then(taskDone); |
| 212 }); |
| 213 |
| 214 // Run test of automation processing. |options| is a dictionary that |
| 215 // describes the node to test, the AudioParams to be tested and the values |
| 216 // for the AudioParam. The members of the dictionary are: |
| 217 // |
| 218 // nodeName - name of the node (constructor name) |
| 219 // paramName - name of the AudioParam to be tested |
| 220 // initialValue - starting value for linear ramp |
| 221 // rampFinalValue - finale value for linear ramp |
| 222 // |
| 223 // The test is considered to have succeeded if the |.value| of the AudioPa
ram |
| 224 // is the final value. |
| 225 // |
| 226 // A simple graph is created containing the node to be tested, connected |
| 227 // to the destination. A linear ramp automation is scheduled for the |
| 228 // specified AudioParam, starting and ending at the values given. |
| 229 // |
| 230 // Processing is started and after some number of frames, the |.value| of |
| 231 // the AudioParam is obtained and compared against the final value. These |
| 232 // should match exactly. |
| 233 function testParamAutomation(options) { |
| 234 var context = new OfflineAudioContext(1, renderFrames, sampleRate); |
| 235 |
| 236 // Create the node to be tested |
| 237 var node = new window[options.nodeName](context); |
| 238 node.connect(context.destination); |
| 239 |
| 240 // A linear ramp starting at frame 0 to frame |automationEndFrame| is |
| 241 // used for the test. This value is fairly arbitrary, but it should be |
| 242 // less than the total render frames. |
| 243 |
| 244 node[options.paramName].setValueAtTime(options.initialValue, 0); |
| 245 node[options.paramName].linearRampToValueAtTime(options.rampFinalValue, |
| 246 automationEndFrame / context.sampleRate); |
| 247 |
| 248 return context.startRendering() |
| 249 .then(function (resultBuffer) { |
| 250 // Sanity check: the given ramp final value must not be the default |
| 251 // value, otherwise we can't easily tell if the automation was |
| 252 // actually run. |
| 253 Should(options.nodeName + "." + options.paramName + " ramp final val
ue", |
| 254 options.rampFinalValue) |
| 255 .notBeEqualTo(node[options.paramName].defaultValue); |
| 256 |
| 257 // The actual AudioParam value should be the rampe final value. |
| 258 Should(options.nodeName + "." + options.paramName + |
| 259 ".value", |
| 260 node[options.paramName].value) |
| 261 .beEqualTo(options.rampFinalValue); |
| 262 }); |
| 263 } |
| 264 |
| 265 function testAudioListener(options) { |
| 266 var context = new OfflineAudioContext(1, renderFrames, sampleRate); |
| 267 |
| 268 // Create the node to be tested |
| 269 var node = new PannerNode(context); |
| 270 node.connect(context.destination); |
| 271 |
| 272 // A linear ramp starting at frame 0 to frame |automationEndFrame| is |
| 273 // used for the test. This value is fairly arbitrary, but it should be |
| 274 // less than the total render frames. |
| 275 |
| 276 context.listener[options.paramName].setValueAtTime(options.initialValue,
0); |
| 277 context.listener[options.paramName].linearRampToValueAtTime(options.ramp
FinalValue, |
| 278 automationEndFrame / context.sampleRate); |
| 279 |
| 280 return context.startRendering() |
| 281 .then(function (resultBuffer) { |
| 282 // Sanity check: the given ramp final value must not be the default |
| 283 // value, otherwise we can't easily tell if the automation was |
| 284 // actually run. |
| 285 Should("AudioListener." + options.paramName + " ramp final value", |
| 286 options.rampFinalValue) |
| 287 .notBeEqualTo(context.listener[options.paramName].defaultValue); |
| 288 |
| 289 // The actual AudioParam value should be the rampe final value. |
| 290 Should("AudioListener." + options.paramName + |
| 291 ".value", |
| 292 context.listener[options.paramName].value) |
| 293 .beEqualTo(options.rampFinalValue); |
| 294 }); |
| 295 } |
| 296 |
| 297 audit.runTasks(); |
| 298 </script> |
| 299 </body> |
| 300 </html> |
OLD | NEW |