diff options
Diffstat (limited to 'testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-audiobuffersource-connections.html')
-rw-r--r-- | testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-audiobuffersource-connections.html | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-audiobuffersource-connections.html b/testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-audiobuffersource-connections.html new file mode 100644 index 0000000000..0b94bd70f9 --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audioparam-interface/k-rate-audiobuffersource-connections.html @@ -0,0 +1,164 @@ +<!doctype html> +<html> + <head> + <title>k-rate AudioParams with inputs for AudioBufferSourceNode</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 = 8000; + const testDuration = 0.25; + + [['playbackRate', [1, 0], [2, testDuration]], + ['detune', [-1200, 0], [1200, testDuration]]] + .forEach(param => { + audit.define( + {label: param[0], description: `AudioBufferSource ${param[0]}`}, + async (task, should) => { + await doTest(should, { + prefix: task.label, + paramName: param[0], + startValue: param[1], + endValue: param[2] + }); + task.done(); + }); + }); + + audit.run(); + + async function doTest(should, options) { + // Test k-rate automation of AudioBufferSourceNode with connected + // input. + // + // A reference source 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, startValue, endValue} = 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); + + // Linear ramp to use for the buffer sources + let ramp = createLinearRampBuffer(context, context.length); + + // Create the reference and test nodes. + let refNode; + let tstNode; + + const nodeOptions = {buffer: ramp}; + + should( + () => refNode = new AudioBufferSourceNode(context, nodeOptions), + `${prefix}: refNode = new AudioBufferSourceNode(context, ${ + JSON.stringify(nodeOptions)})`) + .notThrow(); + + should( + () => tstNode = new AudioBufferSourceNode(context, nodeOptions), + `${prefix}: tstNode = new AudioBufferSourceNode(context, ${ + JSON.stringify(nodeOptions)})`) + .notThrow(); + + + // Automate the AudioParam of the reference node with a linear ramp + should( + () => refNode[paramName].setValueAtTime(...startValue), + `${prefix}: refNode[${paramName}].setValueAtTime(${ + startValue[0]}, ${startValue[1]})`) + .notThrow(); + + should( + () => refNode[paramName].linearRampToValueAtTime(...endValue), + `${prefix}: refNode[${paramName}].linearRampToValueAtTime(${ + endValue[0]}, ${endValue[1]})`) + .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 reference node. + + // Compute the start and end values based on the defaultValue of the + // param and the desired startValue and endValue. The input is added to + // the intrinsic value of the AudioParam, so we need to account for + // that. + + let mod; + should( + () => mod = new ConstantSourceNode(context, {offset: 0}), + `${prefix}: mod = new ConstantSourceNode(context, {offset: 0})`) + .notThrow(); + + let modStart = startValue[0] - refNode[paramName].defaultValue; + let modEnd = endValue[0] - refNode[paramName].defaultValue; + should( + () => mod.offset.setValueAtTime(modStart, startValue[1]), + `${prefix}: mod.offset.setValueAtTime(${modStart}, ${ + startValue[1]})`) + .notThrow(); + should( + () => mod.offset.linearRampToValueAtTime(modEnd, endValue[1]), + `${prefix}: mod.offset.linearRampToValueAtTime(${modEnd}, ${ + endValue[1]})`) + .notThrow(); + + // Connect up everything. + should( + () => mod.connect(tstNode[paramName]), + `${prefix}: mod.connect(tstNode[${paramName}])`) + .notThrow(); + + refNode.connect(merger, 0, 0); + tstNode.connect(merger, 0, 1); + + // Go! + refNode.start(); + tstNode.start(); + mod.start(); + + const buffer = await context.startRendering(); + let expected = buffer.getChannelData(0); + let actual = buffer.getChannelData(1); + + // Quick sanity check that output isn't zero. This means we messed up + // the connections or automations or the buffer source. + should(expected, `Expected k-rate ${paramName} AudioParam with input`) + .notBeConstantValueOf(0); + should(actual, `Actual k-rate ${paramName} AudioParam with input`) + .notBeConstantValueOf(0); + + // 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> |