tor-browser

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

k-rate-dynamics-compressor-connections.html (3847B)


      1 <!DOCTYPE html>
      2 <html>
      3  <head>
      4    <title>k-rate AudioParams with inputs for DynamicsCompressorNode</title>
      5    <script src="/resources/testharness.js"></script>
      6    <script src="/resources/testharnessreport.js"></script>
      7  </head>
      8  <body>
      9    <script>
     10      // Fairly arbitrary sampleRate and somewhat duration
     11      const sampleRate = 48000;
     12      const testDuration = 0.25;
     13 
     14      ['attack', 'knee', 'ratio', 'release', 'threshold'].forEach(paramName => {
     15        promise_test(async () => {
     16          await doTest({prefix: paramName, paramName: paramName});
     17        }, `Verify k-rate '${paramName}' with input on DynamicsCompressorNode`);
     18      });
     19 
     20      async function doTest(options) {
     21        // Test k-rate automation of DynamicsCompressorNode with connected
     22        // input.
     23        //
     24        // A reference compressor node is created with an automation on the
     25        // selected AudioParam. For simplicity, we just use a linear ramp from
     26        // the minValue to the maxValue of the AudioParam.
     27        //
     28        // The test node has an input signal connected to the AudioParam.  This
     29        // input signal is created to match the automation on the reference
     30        // node.
     31        //
     32        // Finally, the output from the two nodes must be identical if k-rate
     33        // inputs are working correctly.
     34        //
     35        // Options parameter is a dictionary with the following required
     36        // members:
     37        //   prefix    - prefix to use for the messages.
     38        //   paramName - Name of the AudioParam to be tested
     39 
     40        const {prefix, paramName} = options;
     41 
     42        const context = new OfflineAudioContext({
     43          numberOfChannels: 2,
     44          sampleRate: sampleRate,
     45          length: testDuration * sampleRate
     46        });
     47 
     48        const merger = new ChannelMergerNode(
     49            context, {numberOfInputs: context.destination.channelCount});
     50        merger.connect(context.destination);
     51 
     52        // Use an oscillator for the source.  Pretty arbitrary parameters.
     53        const src = new OscillatorNode(context, {
     54          type: 'sawtooth',
     55          frequency: 440
     56        });
     57 
     58        // Create the reference and test nodes.
     59        let refNode = new DynamicsCompressorNode(context);
     60 
     61        const tstOptions = {};
     62        tstOptions[paramName] = refNode[paramName].minValue;
     63 
     64        let tstNode = new DynamicsCompressorNode(context, tstOptions);
     65 
     66        // Automate the AudioParam of the reference node with a linear ramp
     67        refNode[paramName].setValueAtTime(refNode[paramName].minValue, 0);
     68        refNode[paramName].linearRampToValueAtTime(
     69            refNode[paramName].maxValue, testDuration);
     70 
     71        // Create the input node and automate it so that its output, when added
     72        // to the intrinsic value of the AudioParam, matches the automation
     73        // on the reference node.
     74        //
     75        // We need to do it this way because the ratio AudioParam has a nominal
     76        // range of [1, 20], so we can't just set the value to 0.
     77        let mod = new ConstantSourceNode(context, {offset: 0});
     78 
     79        const endValue =
     80            refNode[paramName].maxValue - refNode[paramName].minValue;
     81 
     82        mod.offset.setValueAtTime(0, 0);
     83        mod.offset.linearRampToValueAtTime(endValue, testDuration);
     84        mod.connect(tstNode[paramName]);
     85 
     86        src.connect(refNode).connect(merger, 0, 0);
     87        src.connect(tstNode).connect(merger, 0, 1);
     88 
     89        src.start();
     90        mod.start();
     91 
     92        const buffer = await context.startRendering();
     93        const expected = buffer.getChannelData(0);
     94        const actual = buffer.getChannelData(1);
     95 
     96        for (let i = 0; i < expected.length; ++i) {
     97          assert_equals(
     98              actual[i], expected[i],
     99              `${prefix}: Sample[${i}] must match exactly`);
    100        }
    101      }
    102    </script>
    103  </body>
    104 </html>