| OLD | NEW |
| (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/audit-util.js"></script> | |
| 7 <script src="resources/audio-testing.js"></script> | |
| 8 <script src="resources/panner-formulas.js"></script> | |
| 9 <title>Test Basic PannerNode with Automation Position Properties</title> | |
| 10 </head> | |
| 11 | |
| 12 <body> | |
| 13 <script> | |
| 14 description("Test Basic PannerNode with Automation Position Properties."); | |
| 15 window.jsTestIsAsync = true; | |
| 16 | |
| 17 var sampleRate = 48000; | |
| 18 | |
| 19 // These tests are quite slow, so don't run for many frames. 256 frames s
hould be enough to | |
| 20 // demonstrate that automations are working. | |
| 21 var renderFrames = 256; | |
| 22 var renderDuration = renderFrames / sampleRate; | |
| 23 | |
| 24 var audit = Audit.createTaskRunner(); | |
| 25 | |
| 26 // Array of tests for setting the panner positions. These tests basically
verify that the | |
| 27 // position setters for the panner and listener are working correctly. | |
| 28 var testConfig = [{ | |
| 29 setter: "positionX", | |
| 30 }, { | |
| 31 setter: "positionY", | |
| 32 }, { | |
| 33 setter: "positionZ", | |
| 34 }]; | |
| 35 | |
| 36 // Create tests for the panner position setters. Both mono and steroe sou
rces are tested. | |
| 37 for (var k = 0; k < testConfig.length; ++k) { | |
| 38 var config = testConfig[k]; | |
| 39 // Function to create the test to define the test. | |
| 40 var tester = function (config, channelCount) { | |
| 41 return function (done) { | |
| 42 var nodes = createGraph(channelCount); | |
| 43 var {context, source, panner} = nodes; | |
| 44 | |
| 45 var message = channelCount == 1 ? "Mono" : "Stereo"; | |
| 46 message += " panner." + config.setter; | |
| 47 | |
| 48 testPositionSetter({ | |
| 49 nodes: nodes, | |
| 50 pannerSetter: panner[config.setter], | |
| 51 message: message | |
| 52 }).then(done); | |
| 53 } | |
| 54 } | |
| 55 | |
| 56 audit.defineTask("Stereo panner." + config.setter, tester(config, 2)); | |
| 57 audit.defineTask("Mono panner." + config.setter, tester(config, 1)); | |
| 58 } | |
| 59 | |
| 60 // Create tests for the listener position setters. Both mono and steroe s
ources are tested. | |
| 61 for (var k = 0; k < testConfig.length; ++k) { | |
| 62 var config = testConfig[k]; | |
| 63 // Function to create the test to define the test. | |
| 64 var tester = function (config, channelCount) { | |
| 65 return function (done) { | |
| 66 var nodes = createGraph(channelCount); | |
| 67 var {context, source, panner} = nodes; | |
| 68 | |
| 69 var message = channelCount == 1 ? "Mono" : "Stereo"; | |
| 70 message += " listener." + config.setter; | |
| 71 | |
| 72 // Some relatively arbitrary (non-default) position for the source l
ocation. | |
| 73 panner.setPosition(1,0,1); | |
| 74 | |
| 75 testPositionSetter({ | |
| 76 nodes: nodes, | |
| 77 pannerSetter: context.listener[config.setter], | |
| 78 message: message | |
| 79 }).then(done); | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 audit.defineTask("Stereo listener." + config.setter, tester(config, 2)); | |
| 84 audit.defineTask("Mono listener." + config.setter, tester(config, 1)); | |
| 85 } | |
| 86 | |
| 87 // Test setPosition method. | |
| 88 audit.defineTask("setPosition", function (done) { | |
| 89 var {context, panner, source} = createGraph(2); | |
| 90 | |
| 91 // Initialize source position (values don't really matter). | |
| 92 panner.setPosition(1,1,1); | |
| 93 | |
| 94 // After some (unimportant) time, move the panner to a (any) new locatio
n. | |
| 95 var suspendFrame = 128; | |
| 96 context.suspend(suspendFrame / sampleRate).then(function () { | |
| 97 panner.setPosition(-100, 2000, 8000); | |
| 98 }).then(context.resume.bind(context)); | |
| 99 | |
| 100 context.startRendering().then(function (resultBuffer) { | |
| 101 verifyPannerOutputChanged(resultBuffer, {message: "setPosition", suspe
ndFrame: suspendFrame}); | |
| 102 }).then(done); | |
| 103 }); | |
| 104 | |
| 105 audit.defineTask("orientation setter", function (done) { | |
| 106 var {context, panner, source} = createGraph(2); | |
| 107 | |
| 108 // For orientation to matter, we need to make the source directional, an
d also move away | |
| 109 // from the listener (because the default location is 0,0,0). | |
| 110 panner.setPosition(0,0,1); | |
| 111 panner.coneInnerAngle = 0; | |
| 112 panner.coneOuterAngle = 360; | |
| 113 panner.coneOuterGain = .001; | |
| 114 | |
| 115 // After some (unimportant) time, change the panner orientation to a new
orientation. The | |
| 116 // only constraint is that the orientation changes from before. | |
| 117 var suspendFrame = 128; | |
| 118 context.suspend(suspendFrame / sampleRate).then(function () { | |
| 119 panner.orientationX.value = -100; | |
| 120 panner.orientationY.value = 2000; | |
| 121 panner.orientationZ.value = 8000; | |
| 122 }).then(context.resume.bind(context)); | |
| 123 | |
| 124 context.startRendering().then(function (resultBuffer) { | |
| 125 verifyPannerOutputChanged(resultBuffer, {message: "panner.orientation{
XYZ}", suspendFrame: suspendFrame}); | |
| 126 }).then(done); | |
| 127 }); | |
| 128 | |
| 129 audit.defineTask("forward setter", function (done) { | |
| 130 var {context, panner, source} = createGraph(2); | |
| 131 | |
| 132 // For orientation to matter, we need to make the source directional, an
d also move away | |
| 133 // from the listener (because the default location is 0,0,0). | |
| 134 panner.setPosition(0,0,1); | |
| 135 panner.coneInnerAngle = 0; | |
| 136 panner.coneOuterAngle = 360; | |
| 137 panner.coneOuterGain = .001; | |
| 138 | |
| 139 // After some (unimportant) time, change the panner orientation to a new
orientation. The | |
| 140 // only constraint is that the orientation changes from before. | |
| 141 var suspendFrame = 128; | |
| 142 context.suspend(suspendFrame / sampleRate).then(function () { | |
| 143 context.listener.forwardX.value = -100; | |
| 144 context.listener.forwardY.value = 2000; | |
| 145 context.listener.forwardZ.value = 8000; | |
| 146 }).then(context.resume.bind(context)); | |
| 147 | |
| 148 context.startRendering().then(function (resultBuffer) { | |
| 149 verifyPannerOutputChanged(resultBuffer, {message: "listener.forward{XY
Z}", suspendFrame: suspendFrame}); | |
| 150 }).then(done); | |
| 151 }); | |
| 152 | |
| 153 audit.defineTask("up setter", function (done) { | |
| 154 var {context, panner, source} = createGraph(2); | |
| 155 | |
| 156 // For orientation to matter, we need to make the source directional, an
d also move away | |
| 157 // from the listener (because the default location is 0,0,0). | |
| 158 panner.setPosition(0,0,1); | |
| 159 panner.coneInnerAngle = 0; | |
| 160 panner.coneOuterAngle = 360; | |
| 161 panner.coneOuterGain = .001; | |
| 162 panner.setPosition(1,0,1); | |
| 163 | |
| 164 // After some (unimportant) time, change the panner orientation to a new
orientation. The | |
| 165 // only constraint is that the orientation changes from before. | |
| 166 var suspendFrame = 128; | |
| 167 context.suspend(suspendFrame / sampleRate).then(function () { | |
| 168 context.listener.upX.value = 100; | |
| 169 context.listener.upY.value = 100; | |
| 170 context.listener.upZ.value = 100;; | |
| 171 }).then(context.resume.bind(context)); | |
| 172 | |
| 173 context.startRendering().then(function (resultBuffer) { | |
| 174 verifyPannerOutputChanged(resultBuffer, {message: "listener.up{XYZ}",
suspendFrame: suspendFrame}); | |
| 175 }).then(done); | |
| 176 }); | |
| 177 | |
| 178 audit.defineTask("finish", function (done) { | |
| 179 finishJSTest(); | |
| 180 done(); | |
| 181 }); | |
| 182 | |
| 183 audit.runTasks(); | |
| 184 | |
| 185 function createGraph(channelCount) { | |
| 186 var context = new OfflineAudioContext(2, renderFrames, sampleRate); | |
| 187 var panner = context.createPanner(); | |
| 188 var source = context.createBufferSource(); | |
| 189 source.buffer = createConstantBuffer(context, 1, channelCount == 1 ? 1 :
[1, 2]); | |
| 190 source.loop = true; | |
| 191 | |
| 192 source.connect(panner); | |
| 193 panner.connect(context.destination); | |
| 194 | |
| 195 source.start(); | |
| 196 return { | |
| 197 context: context, | |
| 198 source: source, | |
| 199 panner: panner | |
| 200 }; | |
| 201 } | |
| 202 | |
| 203 function testPositionSetter(options) { | |
| 204 var {nodes, pannerSetter, message} = options; | |
| 205 | |
| 206 var {context, source, panner} = nodes; | |
| 207 | |
| 208 // Set panner x position. (Value doesn't matter); | |
| 209 pannerSetter.value = 1; | |
| 210 | |
| 211 // Wait a bit and set a new position. (Actual time and position doesn't
matter). | |
| 212 var suspendFrame = 128; | |
| 213 context.suspend(suspendFrame / sampleRate).then(function () { | |
| 214 pannerSetter.value = 10000; | |
| 215 }).then(context.resume.bind(context)); | |
| 216 | |
| 217 return context.startRendering().then(function (resultBuffer) { | |
| 218 verifyPannerOutputChanged(resultBuffer, {message: message, suspendFram
e: suspendFrame}); | |
| 219 }); | |
| 220 } | |
| 221 | |
| 222 function verifyPannerOutputChanged(resultBuffer, options) { | |
| 223 var {message, suspendFrame} = options; | |
| 224 // Verify that the first part of output is constant. (Doesn't matter w
hat.) | |
| 225 var success = true; | |
| 226 var data0 = resultBuffer.getChannelData(0); | |
| 227 var data1 = resultBuffer.getChannelData(1); | |
| 228 | |
| 229 var middle = "[0, " + suspendFrame + ") "; | |
| 230 success = Should(message + ".value frame " + middle + "channel 0", dat
a0.slice(0, suspendFrame)) | |
| 231 .beConstantValueOf(data0[0]) && success; | |
| 232 success = Should(message + ".value frame " + middle + "channel 1", dat
a1.slice(0, suspendFrame)) | |
| 233 .beConstantValueOf(data1[0]) && success; | |
| 234 | |
| 235 // The rest after suspendTime should be constant and different from th
e first part. | |
| 236 middle = "[" + suspendFrame + ", " + renderFrames + ") "; | |
| 237 success = Should(message + ".value frame " + middle + "channel 0", | |
| 238 data0.slice(suspendFrame)) | |
| 239 .beConstantValueOf(data0[suspendFrame]) && success; | |
| 240 success = Should(message + ".value frame " + middle + "channel 0", | |
| 241 data1.slice(suspendFrame)) | |
| 242 .beConstantValueOf(data1[suspendFrame]) && success; | |
| 243 success = Should("Output at frame " + suspendFrame + " channel 0", dat
a0[suspendFrame]) | |
| 244 .notBeEqualTo(data0[0]) && success; | |
| 245 success = Should("Output at frame " + suspendFrame + " channel 1", dat
a1[suspendFrame]) | |
| 246 .notBeEqualTo(data1[0]) && success; | |
| 247 | |
| 248 var prefix = "Directly setting " + message + ".value"; | |
| 249 if (success) | |
| 250 testPassed(prefix + " worked.\n"); | |
| 251 else | |
| 252 testFailed(prefix + " failed.\n"); | |
| 253 } | |
| 254 </script> | |
| 255 </body> | |
| 256 </html> | |
| OLD | NEW |