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-constantsourcenode-interface | |
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-constantsourcenode-interface')
5 files changed, 515 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic.html b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic.html new file mode 100644 index 0000000000..4f925df5cd --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic.html @@ -0,0 +1,85 @@ +<!DOCTYPE html> +<html> + <head> + <title> + Basic ConstantSourceNode Tests + </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/start-stop-exceptions.js"></script> + </head> + <body> + <script id="layout-test-code"> + let context = new AudioContext(); + + let audit = Audit.createTaskRunner(); + + audit.define('createConstantSource()', (task, should) => { + let node; + let prefix = 'Factory method: '; + + should(() => { + node = context.createConstantSource(); + }, prefix + 'node = context.createConstantSource()').notThrow(); + should( + node instanceof ConstantSourceNode, + prefix + 'node instance of ConstantSourceNode') + .beEqualTo(true); + + verifyNodeDefaults(should, node, prefix); + + task.done(); + }); + + audit.define('new ConstantSourceNode()', (task, should) => { + let node; + let prefix = 'Constructor: '; + + should(() => { + node = new ConstantSourceNode(context); + }, prefix + 'node = new ConstantSourceNode()').notThrow(); + should( + node instanceof ConstantSourceNode, + prefix + 'node instance of ConstantSourceNode') + .beEqualTo(true); + + + verifyNodeDefaults(should, node, prefix); + + task.done(); + }); + + audit.define('start/stop exceptions', (task, should) => { + let node = new ConstantSourceNode(context); + + testStartStop(should, node); + task.done(); + }); + + function verifyNodeDefaults(should, node, prefix) { + should(node.numberOfInputs, prefix + 'node.numberOfInputs') + .beEqualTo(0); + should(node.numberOfOutputs, prefix + 'node.numberOfOutputs') + .beEqualTo(1); + should(node.channelCount, prefix + 'node.channelCount').beEqualTo(2); + should(node.channelCountMode, prefix + 'node.channelCountMode') + .beEqualTo('max'); + should( + node.channelInterpretation, prefix + 'node.channelInterpretation') + .beEqualTo('speakers'); + + should(node.offset.value, prefix + 'node.offset.value').beEqualTo(1); + should(node.offset.defaultValue, prefix + 'node.offset.defaultValue') + .beEqualTo(1); + should(node.offset.minValue, prefix + 'node.offset.minValue') + .beEqualTo(Math.fround(-3.4028235e38)); + should(node.offset.maxValue, prefix + 'node.offset.maxValue') + .beEqualTo(Math.fround(3.4028235e38)); + } + + audit.run(); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-onended.html b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-onended.html new file mode 100644 index 0000000000..64bc54f21b --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-onended.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> + <head> + <title> + Test ConstantSourceNode onended + </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script id="layout-test-code"> + let sampleRate = 44100.0; + // Number of frames that the source will run; fairly arbitrary + let numberOfFrames = 32; + // Number of frames to render; arbitrary, but should be larger than + // numberOfFrames; + let renderFrames = 16 * numberOfFrames; + + let context = new OfflineAudioContext(1, renderFrames, sampleRate); + let src = new ConstantSourceNode(context); + src.connect(context.destination); + + let tester = async_test('ConstantSourceNode onended event fired'); + + src.onended = function() { + tester.step(function() { + assert_true(true, 'ConstantSourceNode.onended fired'); + }); + tester.done(); + }; + + src.start(); + src.stop(numberOfFrames / context.sampleRate); + + context.startRendering(); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-output.html b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-output.html new file mode 100644 index 0000000000..5990376cff --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-output.html @@ -0,0 +1,207 @@ +<!DOCTYPE html> +<html> + <head> + <title> + Test ConstantSourceNode Output + </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/audioparam-testing.js"></script> + </head> + <body> + <script id="layout-test-code"> + let sampleRate = 48000; + let renderDuration = 0.125; + let renderFrames = sampleRate * renderDuration; + + let audit = Audit.createTaskRunner(); + + audit.define('constant source', (task, should) => { + // Verify a constant source outputs the correct (fixed) constant. + let context = new OfflineAudioContext(1, renderFrames, sampleRate); + let node = new ConstantSourceNode(context, {offset: 0.5}); + node.connect(context.destination); + node.start(); + + context.startRendering() + .then(function(buffer) { + let actual = buffer.getChannelData(0); + let expected = new Float32Array(actual.length); + expected.fill(node.offset.value); + + should(actual, 'Basic: ConstantSourceNode({offset: 0.5})') + .beEqualToArray(expected); + }) + .then(() => task.done()); + }); + + audit.define('stop before start', (task, should) => { + let context = new OfflineAudioContext(1, renderFrames, sampleRate); + let node = new ConstantSourceNode(context, {offset: 1}); + node.connect(context.destination); + node.start(61 / context.sampleRate); + node.stop(31 / context.sampleRate); + + context.startRendering() + .then(function(buffer) { + let actual = buffer.getChannelData(0); + should(actual, + "ConstantSourceNode with stop before " + + "start must output silence") + .beConstantValueOf(0); + }) + .then(() => task.done()); + }); + + audit.define('stop equal to start', (task, should) => { + let context = new OfflineAudioContext(1, renderFrames, sampleRate); + let node = new ConstantSourceNode(context, {offset: 1}); + node.connect(context.destination); + node.start(31 / context.sampleRate); + node.stop(31 / context.sampleRate); + + context.startRendering() + .then(function(buffer) { + let actual = buffer.getChannelData(0); + should(actual, + "ConstantSourceNode with stop equal to start " + + " must output silence") + .beConstantValueOf(0); + }) + .then(() => task.done()); + }); + + audit.define('start/stop', (task, should) => { + // Verify a constant source starts and stops at the correct time and has + // the correct (fixed) value. + let context = new OfflineAudioContext(1, renderFrames, sampleRate); + let node = new ConstantSourceNode(context, {offset: 1}); + node.connect(context.destination); + + let startFrame = 10; + let stopFrame = 300; + + node.start(startFrame / context.sampleRate); + node.stop(stopFrame / context.sampleRate); + + context.startRendering() + .then(function(buffer) { + let actual = buffer.getChannelData(0); + let expected = new Float32Array(actual.length); + // The expected output is all 1s from start to stop time. + expected.fill(0); + + for (let k = startFrame; k < stopFrame; ++k) { + expected[k] = node.offset.value; + } + + let prefix = 'start/stop: '; + should(actual.slice(0, startFrame), + prefix + 'ConstantSourceNode frames [0, ' + + startFrame + ')') + .beConstantValueOf(0); + + should(actual.slice(startFrame, stopFrame), + prefix + 'ConstantSourceNode frames [' + + startFrame + ', ' + stopFrame + ')') + .beConstantValueOf(1); + + should( + actual.slice(stopFrame), + prefix + 'ConstantSourceNode frames [' + stopFrame + + ', ' + renderFrames + ')') + .beConstantValueOf(0); + }) + .then(() => task.done()); + + }); + + audit.define('basic automation', (task, should) => { + // Verify that automation works as expected. + let context = new OfflineAudioContext(1, renderFrames, sampleRate); + let source = context.createConstantSource(); + source.connect(context.destination); + + let rampEndTime = renderDuration / 2; + source.offset.setValueAtTime(0.5, 0); + source.offset.linearRampToValueAtTime(1, rampEndTime); + + source.start(); + + context.startRendering() + .then(function(buffer) { + let actual = buffer.getChannelData(0); + let expected = createLinearRampArray( + 0, rampEndTime, 0.5, 1, context.sampleRate); + + let rampEndFrame = Math.ceil(rampEndTime * context.sampleRate); + let prefix = 'Automation: '; + + should(actual.slice(0, rampEndFrame), + prefix + 'ConstantSourceNode.linearRamp(1, 0.5)') + .beCloseToArray(expected, { + // Experimentally determined threshold. + relativeThreshold: 7.1610e-7 + }); + + should(actual.slice(rampEndFrame), + prefix + 'ConstantSourceNode after ramp') + .beConstantValueOf(1); + }) + .then(() => task.done()); + }); + + audit.define('connected audioparam', (task, should) => { + // Verify the constant source output with connected AudioParam produces + // the correct output. + let context = new OfflineAudioContext(2, renderFrames, sampleRate) + context.destination.channelInterpretation = 'discrete'; + let source = new ConstantSourceNode(context, {offset: 1}); + let osc = context.createOscillator(); + let merger = context.createChannelMerger(2); + merger.connect(context.destination); + + source.connect(merger, 0, 0); + osc.connect(merger, 0, 1); + osc.connect(source.offset); + + osc.start(); + let sourceStartFrame = 10; + source.start(sourceStartFrame / context.sampleRate); + + context.startRendering() + .then(function(buffer) { + // Channel 0 and 1 should be identical, except channel 0 (the + // source) is silent at the beginning. + let actual = buffer.getChannelData(0); + let expected = buffer.getChannelData(1); + // The expected output should be oscillator + 1 because offset + // is 1. + expected = expected.map(x => 1 + x); + let prefix = 'Connected param: '; + + // The initial part of the output should be silent because the + // source node hasn't started yet. + should( + actual.slice(0, sourceStartFrame), + prefix + 'ConstantSourceNode frames [0, ' + sourceStartFrame + + ')') + .beConstantValueOf(0); + // The rest of the output should be the same as the oscillator (in + // channel 1) + should( + actual.slice(sourceStartFrame), + prefix + 'ConstantSourceNode frames [' + sourceStartFrame + + ', ' + renderFrames + ')') + .beCloseToArray(expected.slice(sourceStartFrame), 0); + + }) + .then(() => task.done()); + }); + + audit.run(); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/ctor-constantsource.html b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/ctor-constantsource.html new file mode 100644 index 0000000000..ea4a65e146 --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/ctor-constantsource.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html> + <head> + <title> + Test Constructor: ConstantSource + </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit-util.js"></script> + <script src="/webaudio/resources/audit.js"></script> + <script src="/webaudio/resources/audionodeoptions.js"></script> + </head> + <body> + <script id="layout-test-code"> + let context; + + let audit = Audit.createTaskRunner(); + + audit.define('initialize', (task, should) => { + context = initializeContext(should); + task.done(); + }); + + audit.define('invalid constructor', (task, should) => { + testInvalidConstructor(should, 'ConstantSourceNode', context); + task.done(); + }); + + audit.define('default constructor', (task, should) => { + let prefix = 'node0'; + let node = + testDefaultConstructor(should, 'ConstantSourceNode', context, { + prefix: prefix, + numberOfInputs: 0, + numberOfOutputs: 1, + channelCount: 2, + channelCountMode: 'max', + channelInterpretation: 'speakers' + }); + + testDefaultAttributes( + should, node, prefix, [{name: 'offset', value: 1}]); + + task.done(); + }); + + audit.run(); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/test-constantsourcenode.html b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/test-constantsourcenode.html new file mode 100644 index 0000000000..04f61106c1 --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-constantsourcenode-interface/test-constantsourcenode.html @@ -0,0 +1,135 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test the ConstantSourceNode Interface</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +test(function(t) { + var ac = new AudioContext(); + + var csn = ac.createConstantSource(); + assert_equals(csn.offset.value, 1.0, "Default offset is 1.0"); + + csn = new ConstantSourceNode(ac); + assert_equals(csn.offset.value, 1.0, "Default offset is 1.0"); + + csn = new ConstantSourceNode(ac, {offset: -0.25}); + assert_equals(csn.offset.value, -0.25, "Offset can be set during construction"); +}, "ConstantSourceNode can be constructed"); + +test(function(t) { + var ac = new AudioContext(); + + var csn = ac.createConstantSource(); + + assert_throws_dom("InvalidStateError", function() { + csn.stop(1); + }, "Start must be called before stop"); + + assert_throws_js(RangeError, function() { + csn.start(-1); + }, "When can not be negative"); + + csn.start(0); + assert_throws_js(RangeError, function() { + csn.stop(-1); + }, "When can not be negative"); +}, "ConstantSourceNode stop and start"); + +async_test(function(t) { + var ac = new OfflineAudioContext(1, 2048, 44100); + var csn = ac.createConstantSource(); + csn.connect(ac.destination); + csn.start() + csn.stop(1024/44100) + csn.onended = function(e) { + t.step(function() { + assert_equals(e.type, "ended", "Event type should be 'ended', received: " + e.type); + }); + t.done(); + } + ac.startRendering(); +}, "ConstantSourceNode onended event"); + +async_test(function(t) { + var ac = new OfflineAudioContext(1, 2048, 44100); + var csn = ac.createConstantSource(); + csn.connect(ac.destination); + csn.start(512/44100) + csn.stop(1024/44100) + + ac.oncomplete = function(e) { + t.step(function() { + var result = e.renderedBuffer.getChannelData(0); + for (var i = 0; i < 2048; ++i) { + if (i >= 512 && i < 1024) { + assert_equals(result[i], 1.0, "sample " + i + " should equal 1.0"); + } else { + assert_equals(result[i], 0.0, "sample " + i + " should equal 0.0"); + } + } + }); + t.done(); + } + + ac.startRendering(); +}, "ConstantSourceNode start and stop when work"); + +async_test(function(t) { + var ac = new OfflineAudioContext(1, 2048, 44100); + var csn = ac.createConstantSource(); + csn.offset.value = 0.25; + csn.connect(ac.destination); + csn.start() + + ac.oncomplete = function(e) { + t.step(function() { + var result = e.renderedBuffer.getChannelData(0); + for (var i = 0; i < 2048; ++i) { + assert_equals(result[i], 0.25, "sample " + i + " should equal 0.25"); + } + }); + t.done(); + } + + ac.startRendering(); +}, "ConstantSourceNode with no automation"); + +async_test(function(t) { + var ac = new OfflineAudioContext(1, 2048, 44100); + + var timeConstant = 2.0; + var offsetStart = 0.25; + var offsetEnd = 0.1; + + var csn = ac.createConstantSource(); + csn.offset.value = offsetStart; + csn.offset.setTargetAtTime(offsetEnd, 1024/ac.sampleRate, timeConstant); + csn.connect(ac.destination); + csn.start() + + ac.oncomplete = function(e) { + t.step(function() { + // create buffer with expected values + var buffer = ac.createBuffer(1, 2048, ac.sampleRate); + for (var i = 0; i < 2048; ++i) { + if (i < 1024) { + buffer.getChannelData(0)[i] = offsetStart; + } else { + time = (i-1024)/ac.sampleRate; + buffer.getChannelData(0)[i] = offsetEnd + (offsetStart - offsetEnd)*Math.exp(-time/timeConstant); + } + } + + var result = e.renderedBuffer.getChannelData(0); + var expected = buffer.getChannelData(0); + for (var i = 0; i < 2048; ++i) { + assert_true(Math.abs(result[i] - expected[i]) < 1.342e-6, "sample " + i + " should equal " + expected[i]); + } + }); + t.done(); + } + + ac.startRendering(); +}, "ConstantSourceNode with automation"); +</script> |