tor-browser

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

audionode-connect-method-chaining.html (5512B)


      1 <!DOCTYPE html>
      2 <html>
      3  <head>
      4    <title>AudioNode.connect() Method Chaining and Validation Tests</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  <body>
     10    <script>
     11      // Dictionary of AudioNode types and their constructor arguments
     12      const audioNodeTypesToTest = [
     13        { name: 'Analyser' }, { name: 'BiquadFilter' },
     14        { name: 'BufferSource' }, { name: 'ChannelMerger', args: [6] },
     15        { name: 'ChannelSplitter', args: [6] }, { name: 'Convolver' },
     16        { name: 'Delay' }, { name: 'DynamicsCompressor' }, { name: 'Gain' },
     17        { name: 'Oscillator' }, { name: 'Panner' },
     18        { name: 'ScriptProcessor', args: [512, 1, 1] },
     19        { name: 'StereoPanner' }, { name: 'WaveShaper' }
     20      ];
     21 
     22      // Verifies that AudioNode.connect() returns the destination node.
     23      function verifyConnectReturnValue(
     24          t, { sourceNode, destinationNode, returnedValue, description }) {
     25            assert_equals(
     26              returnedValue,
     27              destinationNode,
     28              `${description} should return the destination node`
     29            );
     30      }
     31 
     32      // Creates a source node and tests .connect() chaining with:
     33      //  - a simple GainNode
     34      //  - a BiquadFilterNode with output index
     35      //  - a ChannelMergerNode with both output and input index
     36      function testConnectChainingForNodeType(t, audioContext, nodeInfo) {
     37        const sourceNode =
     38            audioContext[`create${nodeInfo.name}`].apply(audioContext,
     39                nodeInfo.args || []);
     40        const sourceTypeName = sourceNode.constructor.name;
     41 
     42        const gainNode = audioContext.createGain();
     43        verifyConnectReturnValue(t, {
     44          sourceNode,
     45          destinationNode: gainNode,
     46          returnedValue: sourceNode.connect(gainNode),
     47          description: `${sourceTypeName}.connect(GainNode)`
     48        });
     49 
     50        const biquadNode = audioContext.createBiquadFilter();
     51        verifyConnectReturnValue(t, {
     52          sourceNode,
     53          destinationNode: biquadNode,
     54          returnedValue: sourceNode.connect(biquadNode, 0),
     55          description: `${sourceTypeName}.connect(BiquadFilterNode, 0)`
     56        });
     57 
     58        const channelMergerNode = audioContext.createChannelMerger();
     59        verifyConnectReturnValue(t, {
     60          sourceNode,
     61          destinationNode: channelMergerNode,
     62          returnedValue: sourceNode.connect(channelMergerNode, 0, 1),
     63          description: `${sourceTypeName}.connect(ChannelMergerNode, 0, 1)`
     64        });
     65      }
     66 
     67      test(t => {
     68        const audioContext = new AudioContext();
     69 
     70        for (const nodeInfo of audioNodeTypesToTest) {
     71          testConnectChainingForNodeType(t, audioContext, nodeInfo);
     72        }
     73      }, 'Verify connect() method chaining for common AudioNode types ' +
     74          'returns destination');
     75 
     76      test(t => {
     77        const audioContext = new AudioContext();
     78 
     79        const audioElement = document.createElement('audio');
     80        testConnectChainingForNodeType(t, audioContext, {
     81          name: 'MediaElementSource',
     82          args: [audioElement]
     83        });
     84 
     85        const mediaStreamDestination =
     86            audioContext.createMediaStreamDestination();
     87        const mediaStream = mediaStreamDestination.stream;
     88 
     89        testConnectChainingForNodeType(t, audioContext, {
     90          name: 'MediaStreamSource',
     91          args: [mediaStream]
     92        });
     93      }, 'Verify connect() method chaining for MediaElementSourceNode ' +
     94          'and MediaStreamSourceNode');
     95 
     96      test(t => {
     97        const contextA = new AudioContext();
     98        const contextB = new AudioContext();
     99        const gainA1 = contextA.createGain();
    100        const gainA2 = contextA.createGain();
    101 
    102        assert_throws_dom(
    103          'IndexSizeError',
    104          () => {
    105            gainA1.connect(gainA2, 1).connect(contextA.destination);
    106          },
    107          'Connecting to an invalid output index should throw IndexSizeError'
    108        );
    109 
    110        assert_throws_dom(
    111          'InvalidAccessError',
    112          () => {
    113            gainA1.connect(gainA2).connect(contextB.destination);
    114          },
    115          'Connecting nodes across different AudioContexts should ' +
    116              'throw InvalidAccessError'
    117        );
    118      }, 'Test exceptions thrown by invalid connect() chaining');
    119 
    120      promise_test(async t => {
    121        const context = new OfflineAudioContext(1, 128, 8000);
    122 
    123        const constantBuffer = createConstantBuffer(context, 1, 1.0);
    124        const bufferSource = context.createBufferSource();
    125        bufferSource.buffer = constantBuffer;
    126        bufferSource.loop = true;
    127 
    128        const gainNode1 = context.createGain();
    129        gainNode1.gain.value = 0.5;
    130 
    131        const gainNode2 = context.createGain();
    132        gainNode2.gain.value = 0.25;
    133        bufferSource.connect(gainNode1)
    134            .connect(gainNode2)
    135                .connect(context.destination);
    136        bufferSource.start();
    137 
    138        const renderedBuffer = await context.startRendering();
    139 
    140        assert_array_approx_equals(
    141          renderedBuffer.getChannelData(0),
    142          new Float32Array(renderedBuffer.length).fill(0.125),
    143          1e-6,
    144          'Output of chained gain nodes should be input * 0.5 * 0.25 = 0.125'
    145        );
    146      }, 'Test correct signal flow and output value after chaining ' +
    147          '.connect() on gain nodes');
    148    </script>
    149  </body>
    150 </html>