diff options
Diffstat (limited to 'testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-dynamics-compressor-connections.html')
-rw-r--r-- | testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-dynamics-compressor-connections.html | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-dynamics-compressor-connections.html b/testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-dynamics-compressor-connections.html new file mode 100644 index 0000000000..c1755cd155 --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-dynamics-compressor-connections.html @@ -0,0 +1,145 @@ +<!doctype html> +<html> + <head> + <title>k-rate AudioParams with inputs for DynamicsCompressorNode</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/webaudio/resources/audit.js"></script> + <script src="/webaudio/resources/audit-util.js"></script> + </head> + + <body> + <script> + let audit = Audit.createTaskRunner(); + + // Fairly abitrary sampleRate and somewhat duration + const sampleRate = 48000; + const testDuration = 0.25; + + ['attack', 'knee', 'ratio', 'release', 'threshold'].forEach(param => { + audit.define( + {label: param, description: `Dynamics compressor ${param}`}, + async (task, should) => { + await doTest(should, {prefix: task.label, paramName: param}); + task.done(); + }); + }); + + audit.run(); + + async function doTest(should, options) { + // Test k-rate automation of DynamicsCompressorNode with connected + // input. + // + // A reference compressor node is created with an automation on the + // selected AudioParam. For simplicity, we just use a linear ramp from + // the minValue to the maxValue of the AudioParam. + // + // The test node has an input signal connected to the AudioParam. This + // input signal is created to match the automation on the reference + // node. + // + // Finally, the output from the two nodes must be identical if k-rate + // inputs are working correctly. + // + // Options parameter is a dictionary with the following required + // members: + // prefix - prefix to use for the messages. + // paramName - Name of the AudioParam to be tested + + let {prefix, paramName} = options; + + let context = new OfflineAudioContext({ + numberOfChannels: 2, + sampleRate: sampleRate, + length: testDuration * sampleRate + }); + + let merger = new ChannelMergerNode( + context, {numberOfInputs: context.destination.channelCount}); + merger.connect(context.destination); + + // Use an oscillator for the source. Pretty arbitrary parameters. + let src = + new OscillatorNode(context, {type: 'sawtooth', frequency: 440}); + + // Create the reference and test nodes. + let refNode; + let tstNode; + + should( + () => refNode = new DynamicsCompressorNode(context), + `${prefix}: refNode = new DynamicsCompressorNode(context)`) + .notThrow(); + + let tstOptions = {}; + tstOptions[paramName] = refNode[paramName].minValue; + should( + () => tstNode = new DynamicsCompressorNode(context, tstOptions), + `${prefix}: tstNode = new DynamicsCompressorNode(context, ${ + JSON.stringify(tstOptions)})`) + .notThrow(); + + + // Automate the AudioParam of the reference node with a linear ramp + should( + () => refNode[paramName].setValueAtTime( + refNode[paramName].minValue, 0), + `${prefix}: refNode[${paramName}].setValueAtTime(refNode[${ + paramName}].minValue, 0)`) + .notThrow(); + + should( + () => refNode[paramName].linearRampToValueAtTime( + refNode[paramName].maxValue, testDuration), + `${prefix}: refNode[${paramName}].linearRampToValueAtTime(refNode[${ + paramName}].minValue, ${testDuration})`) + .notThrow(); + + + // Create the input node and automate it so that it's output when added + // to the intrinsic value of the AudioParam we get the same values as + // the automations on the ference node. We need to do it this way + // because the ratio AudioParam has a nominal range of [1, 20] so we + // can't just set the value to 0, which is what we'd normally do. + let mod; + should( + () => mod = new ConstantSourceNode(context, {offset: 0}), + `${prefix}: mod = new ConstantSourceNode(context, {offset: 0})`) + .notThrow(); + let endValue = + refNode[paramName].maxValue - refNode[paramName].minValue; + should( + () => mod.offset.setValueAtTime(0, 0), + `${prefix}: mod.offset.setValueAtTime(0, 0)`) + .notThrow(); + should( + () => mod.offset.linearRampToValueAtTime(endValue, testDuration), + `${prefix}: mod.offset.linearRampToValueAtTime(${endValue}, ${ + testDuration})`) + .notThrow(); + + // Connect up everything. + should( + () => mod.connect(tstNode[paramName]), + `${prefix}: mod.connect(tstNode[${paramName}])`) + .notThrow(); + + src.connect(refNode).connect(merger, 0, 0); + src.connect(tstNode).connect(merger, 0, 1); + + // Go! + src.start(); + mod.start(); + + const buffer = await context.startRendering(); + let expected = buffer.getChannelData(0); + let actual = buffer.getChannelData(1); + + // The expected and actual results must be EXACTLY the same. + should(actual, `k-rate ${paramName} AudioParam with input`) + .beCloseToArray(expected, {absoluteThreshold: 0}); + } + </script> + </body> +</html> |