diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/webaudio/the-audio-api/the-pannernode-interface/panner-automation-basic.html | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/webaudio/the-audio-api/the-pannernode-interface/panner-automation-basic.html')
-rw-r--r-- | testing/web-platform/tests/webaudio/the-audio-api/the-pannernode-interface/panner-automation-basic.html | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-pannernode-interface/panner-automation-basic.html b/testing/web-platform/tests/webaudio/the-audio-api/the-pannernode-interface/panner-automation-basic.html new file mode 100644 index 0000000000..5c3df0e6fd --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-pannernode-interface/panner-automation-basic.html @@ -0,0 +1,298 @@ +<!DOCTYPE html> +<html> + <head> + <title> + Test Basic PannerNode with Automation Position Properties + </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="../../resources/audit-util.js"></script> + <script src="../../resources/audit.js"></script> + <script src="../../resources/panner-formulas.js"></script> + </head> + <body> + <script id="layout-test-code"> + let sampleRate = 48000; + + // These tests are quite slow, so don't run for many frames. 256 frames + // should be enough to demonstrate that automations are working. + let renderFrames = 256; + let renderDuration = renderFrames / sampleRate; + + let audit = Audit.createTaskRunner(); + + // Array of tests for setting the panner positions. These tests basically + // verify that the position setters for the panner and listener are + // working correctly. + let testConfig = [ + { + setter: 'positionX', + }, + { + setter: 'positionY', + }, + { + setter: 'positionZ', + } + ]; + + // Create tests for the panner position setters. Both mono and steroe + // sources are tested. + for (let k = 0; k < testConfig.length; ++k) { + let config = testConfig[k]; + // Function to create the test to define the test. + let tester = function(config, channelCount) { + return (task, should) => { + let nodes = createGraph(channelCount); + let {context, source, panner} = nodes; + + let message = channelCount == 1 ? 'Mono' : 'Stereo'; + message += ' panner.' + config.setter; + + testPositionSetter(should, { + nodes: nodes, + pannerSetter: panner[config.setter], + message: message + }).then(() => task.done()); + } + }; + + audit.define('Stereo panner.' + config.setter, tester(config, 2)); + audit.define('Mono panner.' + config.setter, tester(config, 1)); + } + + // Create tests for the listener position setters. Both mono and steroe + // sources are tested. + for (let k = 0; k < testConfig.length; ++k) { + let config = testConfig[k]; + // Function to create the test to define the test. + let tester = function(config, channelCount) { + return (task, should) => { + let nodes = createGraph(channelCount); + let {context, source, panner} = nodes; + + let message = channelCount == 1 ? 'Mono' : 'Stereo'; + message += ' listener.' + config.setter; + + // Some relatively arbitrary (non-default) position for the source + // location. + panner.setPosition(1, 0, 1); + + testPositionSetter(should, { + nodes: nodes, + pannerSetter: context.listener[config.setter], + message: message + }).then(() => task.done()); + } + }; + + audit.define('Stereo listener.' + config.setter, tester(config, 2)); + audit.define('Mono listener.' + config.setter, tester(config, 1)); + } + + // Test setPosition method. + audit.define('setPosition', (task, should) => { + let {context, panner, source} = createGraph(2); + + // Initialize source position (values don't really matter). + panner.setPosition(1, 1, 1); + + // After some (unimportant) time, move the panner to a (any) new + // location. + let suspendFrame = 128; + context.suspend(suspendFrame / sampleRate) + .then(function() { + panner.setPosition(-100, 2000, 8000); + }) + .then(context.resume.bind(context)); + + context.startRendering() + .then(function(resultBuffer) { + verifyPannerOutputChanged( + should, resultBuffer, + {message: 'setPosition', suspendFrame: suspendFrame}); + }) + .then(() => task.done()); + }); + + audit.define('orientation setter', (task, should) => { + let {context, panner, source} = createGraph(2); + + // For orientation to matter, we need to make the source directional, + // and also move away from the listener (because the default location is + // 0,0,0). + panner.setPosition(0, 0, 1); + panner.coneInnerAngle = 0; + panner.coneOuterAngle = 360; + panner.coneOuterGain = .001; + + // After some (unimportant) time, change the panner orientation to a new + // orientation. The only constraint is that the orientation changes + // from before. + let suspendFrame = 128; + context.suspend(suspendFrame / sampleRate) + .then(function() { + panner.orientationX.value = -100; + panner.orientationY.value = 2000; + panner.orientationZ.value = 8000; + }) + .then(context.resume.bind(context)); + + context.startRendering() + .then(function(resultBuffer) { + verifyPannerOutputChanged(should, resultBuffer, { + message: 'panner.orientation{XYZ}', + suspendFrame: suspendFrame + }); + }) + .then(() => task.done()); + }); + + audit.define('forward setter', (task, should) => { + let {context, panner, source} = createGraph(2); + + // For orientation to matter, we need to make the source directional, + // and also move away from the listener (because the default location is + // 0,0,0). + panner.setPosition(0, 0, 1); + panner.coneInnerAngle = 0; + panner.coneOuterAngle = 360; + panner.coneOuterGain = .001; + + // After some (unimportant) time, change the panner orientation to a new + // orientation. The only constraint is that the orientation changes + // from before. + let suspendFrame = 128; + context.suspend(suspendFrame / sampleRate) + .then(function() { + context.listener.forwardX.value = -100; + context.listener.forwardY.value = 2000; + context.listener.forwardZ.value = 8000; + }) + .then(context.resume.bind(context)); + + context.startRendering() + .then(function(resultBuffer) { + verifyPannerOutputChanged(should, resultBuffer, { + message: 'listener.forward{XYZ}', + suspendFrame: suspendFrame + }); + }) + .then(() => task.done()); + }); + + audit.define('up setter', (task, should) => { + let {context, panner, source} = createGraph(2); + + // For orientation to matter, we need to make the source directional, + // and also move away from the listener (because the default location is + // 0,0,0). + panner.setPosition(0, 0, 1); + panner.coneInnerAngle = 0; + panner.coneOuterAngle = 360; + panner.coneOuterGain = .001; + panner.setPosition(1, 0, 1); + + // After some (unimportant) time, change the panner orientation to a new + // orientation. The only constraint is that the orientation changes + // from before. + let suspendFrame = 128; + context.suspend(suspendFrame / sampleRate) + .then(function() { + context.listener.upX.value = 100; + context.listener.upY.value = 100; + context.listener.upZ.value = 100; + ; + }) + .then(context.resume.bind(context)); + + context.startRendering() + .then(function(resultBuffer) { + verifyPannerOutputChanged( + should, resultBuffer, + {message: 'listener.up{XYZ}', suspendFrame: suspendFrame}); + }) + .then(() => task.done()); + }); + + audit.run(); + + function createGraph(channelCount) { + let context = new OfflineAudioContext(2, renderFrames, sampleRate); + let panner = context.createPanner(); + let source = context.createBufferSource(); + source.buffer = + createConstantBuffer(context, 1, channelCount == 1 ? 1 : [1, 2]); + source.loop = true; + + source.connect(panner); + panner.connect(context.destination); + + source.start(); + return {context: context, source: source, panner: panner}; + } + + function testPositionSetter(should, options) { + let {nodes, pannerSetter, message} = options; + + let {context, source, panner} = nodes; + + // Set panner x position. (Value doesn't matter); + pannerSetter.value = 1; + + // Wait a bit and set a new position. (Actual time and position doesn't + // matter). + let suspendFrame = 128; + context.suspend(suspendFrame / sampleRate) + .then(function() { + pannerSetter.value = 10000; + }) + .then(context.resume.bind(context)); + + return context.startRendering().then(function(resultBuffer) { + verifyPannerOutputChanged( + should, resultBuffer, + {message: message, suspendFrame: suspendFrame}); + }); + } + + function verifyPannerOutputChanged(should, resultBuffer, options) { + let {message, suspendFrame} = options; + // Verify that the first part of output is constant. (Doesn't matter + // what.) + let data0 = resultBuffer.getChannelData(0); + let data1 = resultBuffer.getChannelData(1); + + let middle = '[0, ' + suspendFrame + ') '; + should( + data0.slice(0, suspendFrame), + message + '.value frame ' + middle + 'channel 0') + .beConstantValueOf(data0[0]); + should( + data1.slice(0, suspendFrame), + message + '.value frame ' + middle + 'channel 1') + .beConstantValueOf(data1[0]); + + // The rest after suspendTime should be constant and different from the + // first part. + middle = '[' + suspendFrame + ', ' + renderFrames + ') '; + should( + data0.slice(suspendFrame), + message + '.value frame ' + middle + 'channel 0') + .beConstantValueOf(data0[suspendFrame]); + should( + data1.slice(suspendFrame), + message + '.value frame ' + middle + 'channel 1') + .beConstantValueOf(data1[suspendFrame]); + should( + data0[suspendFrame], + message + ': Output at frame ' + suspendFrame + ' channel 0') + .notBeEqualTo(data0[0]); + should( + data1[suspendFrame], + message + ': Output at frame ' + suspendFrame + ' channel 1') + .notBeEqualTo(data1[0]); + } + </script> + </body> +</html> |