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