tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

k-rate-audiobuffersource-connections.html (5006B)


      1 <!doctype html>
      2 <html>
      3  <head>
      4    <title>k-rate AudioParams with inputs for AudioBufferSourceNode</title>
      5    <script src="/resources/testharness.js"></script>
      6    <script src="/resources/testharnessreport.js"></script>
      7    <script src="/webaudio/resources/audit-util.js"></script>
      8  </head>
      9 
     10  <body>
     11    <script>
     12      const sampleRate = 8000;
     13      const testDuration = 0.25;
     14 
     15      const testCases = [
     16        { paramName: 'playbackRate', startValue: [1, 0],
     17            endValue: [2, testDuration] },
     18        { paramName: 'detune', startValue: [-1200, 0],
     19            endValue: [1200, testDuration] }
     20      ];
     21 
     22      for (const { paramName, startValue, endValue } of testCases) {
     23        promise_test(async t => {
     24          const prefix = `AudioBufferSourceNode ${paramName}`;
     25          await runKRateParamInputTest(t, {
     26            prefix,
     27            paramName,
     28            startValue,
     29            endValue
     30          });
     31        }, `Verify k-rate AudioParam input works correctly for ${paramName}`);
     32      }
     33 
     34      async function runKRateParamInputTest(test, options) {
     35        // Test k-rate automation of AudioBufferSourceNode with connected
     36        // input.
     37        //
     38        // A reference source node is created with an automation on the
     39        // selected AudioParam. For simplicity, we just use a linear ramp from
     40        // the minValue to the maxValue of the AudioParam.
     41        //
     42        // The test node has an input signal connected to the AudioParam.  This
     43        // input signal is created to match the automation on the reference
     44        // node.
     45        //
     46        // Finally, the output from the two nodes must be identical if k-rate
     47        // inputs are working correctly.
     48        //
     49        // Options parameter is a dictionary with the following required
     50        // members:
     51        //   prefix    - prefix to use for the messages.
     52        //   paramName - Name of the AudioParam to be tested
     53 
     54        const { prefix, paramName, startValue, endValue } = options;
     55 
     56        const context = new OfflineAudioContext({
     57          numberOfChannels: 2,
     58          sampleRate,
     59          length: testDuration * sampleRate
     60        });
     61 
     62        const merger = new ChannelMergerNode(context, {
     63          numberOfInputs: context.destination.channelCount
     64        });
     65        merger.connect(context.destination);
     66 
     67        const rampBuffer = createLinearRampBuffer(context, context.length);
     68 
     69        let refNode, tstNode;
     70 
     71        const nodeOptions = { buffer: rampBuffer };
     72 
     73        test.step(() => {
     74          refNode = new AudioBufferSourceNode(context, nodeOptions);
     75        }, `${prefix}: create reference AudioBufferSourceNode`);
     76 
     77        test.step(() => {
     78          tstNode = new AudioBufferSourceNode(context, nodeOptions);
     79        }, `${prefix}: create test AudioBufferSourceNode`);
     80 
     81        // Set automation on the reference node’s param
     82        test.step(() => {
     83          refNode[paramName].setValueAtTime(...startValue);
     84        }, `${prefix}: setValueAtTime(${startValue[0]}, ${startValue[1]})`);
     85 
     86        test.step(() => {
     87          refNode[paramName].linearRampToValueAtTime(...endValue);
     88        }, `${prefix}: linearRampToValueAtTime(${endValue[0]}, ` +
     89            `${endValue[1]})`);
     90 
     91        // Modulate test node’s param via input signal
     92        let mod = new ConstantSourceNode(context, { offset: 0 });
     93 
     94        const modStart = startValue[0] - refNode[paramName].defaultValue;
     95        const modEnd = endValue[0] - refNode[paramName].defaultValue;
     96 
     97        test.step(() => {
     98          mod.offset.setValueAtTime(modStart, startValue[1]);
     99        }, `${prefix}: mod.offset.setValueAtTime(${modStart}, ` +
    100            ` ${startValue[1]})`);
    101 
    102        test.step(() => {
    103          mod.offset.linearRampToValueAtTime(modEnd, endValue[1]);
    104        }, `${prefix}: mod.offset.linearRampToValueAtTime(${modEnd}, ` +
    105            ` ${endValue[1]})`);
    106 
    107        test.step(() => {
    108          mod.connect(tstNode[paramName]);
    109        }, `${prefix}: mod.connect(tstNode[${paramName}])`);
    110 
    111        // Connect both nodes to different merger inputs
    112        refNode.connect(merger, 0, 0);
    113        tstNode.connect(merger, 0, 1);
    114 
    115        // Start all nodes
    116        refNode.start();
    117        tstNode.start();
    118        mod.start();
    119 
    120        const renderedBuffer = await context.startRendering();
    121 
    122        const expected = renderedBuffer.getChannelData(0);
    123        const actual = renderedBuffer.getChannelData(1);
    124 
    125        // Sanity check: outputs should not be silent
    126        assert_false(
    127          expected.every(v => v === 0),
    128          `${prefix}: expected output is not silent`
    129        );
    130 
    131        assert_false(
    132          actual.every(v => v === 0),
    133          `${prefix}: actual output is not silent`
    134        );
    135 
    136        // Expected and actual outputs must match exactly
    137        assert_array_approx_equals(
    138          actual,
    139          expected,
    140          0,
    141          `${prefix}: actual matches expected for k-rate AudioParam input`
    142        );
    143      }
    144    </script>
    145  </body>
    146 </html>