tor-browser

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

audionode-channel-rules.html (10343B)


      1 <!DOCTYPE html>
      2 <html>
      3  <head>
      4    <title>
      5      audionode-channel-rules.html
      6    </title>
      7    <script src="/resources/testharness.js"></script>
      8    <script src="/resources/testharnessreport.js"></script>
      9    <script src="/webaudio/resources/audit-util.js"></script>
     10    <script src="/webaudio/resources/audit.js"></script>
     11    <script src="/webaudio/resources/mixing-rules.js"></script>
     12  </head>
     13  <body>
     14    <script id="layout-test-code">
     15      let audit = Audit.createTaskRunner();
     16      let context = 0;
     17      // Use a power of two to eliminate round-off converting frames to time.
     18      let sampleRate = 32768;
     19      let renderNumberOfChannels = 8;
     20      let singleTestFrameLength = 8;
     21      let testBuffers;
     22 
     23      // A list of connections to an AudioNode input, each of which is to be
     24      // used in one or more specific test cases.  Each element in the list is a
     25      // string, with the number of connections corresponding to the length of
     26      // the string, and each character in the string is from '1' to '8'
     27      // representing a 1 to 8 channel connection (from an AudioNode output).
     28 
     29      // For example, the string "128" means 3 connections, having 1, 2, and 8
     30      // channels respectively.
     31 
     32      let connectionsList = [
     33        '1', '2', '3', '4', '5', '6', '7', '8', '11', '12', '14', '18', '111',
     34        '122', '123', '124', '128'
     35      ];
     36 
     37      // A list of mixing rules, each of which will be tested against all of the
     38      // connections in connectionsList.
     39      let mixingRulesList = [
     40        {
     41          channelCount: 2,
     42          channelCountMode: 'max',
     43          channelInterpretation: 'speakers'
     44        },
     45        {
     46          channelCount: 4,
     47          channelCountMode: 'clamped-max',
     48          channelInterpretation: 'speakers'
     49        },
     50 
     51        // Test up-down-mix to some explicit speaker layouts.
     52        {
     53          channelCount: 1,
     54          channelCountMode: 'explicit',
     55          channelInterpretation: 'speakers'
     56        },
     57        {
     58          channelCount: 2,
     59          channelCountMode: 'explicit',
     60          channelInterpretation: 'speakers'
     61        },
     62        {
     63          channelCount: 4,
     64          channelCountMode: 'explicit',
     65          channelInterpretation: 'speakers'
     66        },
     67        {
     68          channelCount: 6,
     69          channelCountMode: 'explicit',
     70          channelInterpretation: 'speakers'
     71        },
     72 
     73        {
     74          channelCount: 2,
     75          channelCountMode: 'max',
     76          channelInterpretation: 'discrete'
     77        },
     78        {
     79          channelCount: 4,
     80          channelCountMode: 'clamped-max',
     81          channelInterpretation: 'discrete'
     82        },
     83        {
     84          channelCount: 4,
     85          channelCountMode: 'explicit',
     86          channelInterpretation: 'discrete'
     87        },
     88        {
     89          channelCount: 8,
     90          channelCountMode: 'explicit',
     91          channelInterpretation: 'discrete'
     92        },
     93      ];
     94 
     95      let numberOfTests = mixingRulesList.length * connectionsList.length;
     96 
     97      // Print out the information for an individual test case.
     98      function printTestInformation(
     99          testNumber, actualBuffer, expectedBuffer, frameLength, frameOffset) {
    100        let actual = stringifyBuffer(actualBuffer, frameLength);
    101        let expected =
    102            stringifyBuffer(expectedBuffer, frameLength, frameOffset);
    103        debug('TEST CASE #' + testNumber + '\n');
    104        debug('actual channels:\n' + actual);
    105        debug('expected channels:\n' + expected);
    106      }
    107 
    108      function scheduleTest(
    109          testNumber, connections, channelCount, channelCountMode,
    110          channelInterpretation) {
    111        let mixNode = context.createGain();
    112        mixNode.channelCount = channelCount;
    113        mixNode.channelCountMode = channelCountMode;
    114        mixNode.channelInterpretation = channelInterpretation;
    115        mixNode.connect(context.destination);
    116 
    117        for (let i = 0; i < connections.length; ++i) {
    118          let connectionNumberOfChannels =
    119              connections.charCodeAt(i) - '0'.charCodeAt(0);
    120 
    121          let source = context.createBufferSource();
    122          // Get a buffer with the right number of channels, converting from
    123          // 1-based to 0-based index.
    124          let buffer = testBuffers[connectionNumberOfChannels - 1];
    125          source.buffer = buffer;
    126          source.connect(mixNode);
    127 
    128          // Start at the right offset.
    129          let sampleFrameOffset = testNumber * singleTestFrameLength;
    130          let time = sampleFrameOffset / sampleRate;
    131          source.start(time);
    132        }
    133      }
    134 
    135      function checkTestResult(
    136          renderedBuffer, testNumber, connections, channelCount,
    137          channelCountMode, channelInterpretation, should) {
    138        let s = 'connections: ' + connections + ', ' + channelCountMode;
    139 
    140        // channelCount is ignored in "max" mode.
    141        if (channelCountMode == 'clamped-max' ||
    142            channelCountMode == 'explicit') {
    143          s += '(' + channelCount + ')';
    144        }
    145 
    146        s += ', ' + channelInterpretation;
    147 
    148        let computedNumberOfChannels = computeNumberOfChannels(
    149            connections, channelCount, channelCountMode);
    150 
    151        // Create a zero-initialized silent AudioBuffer with
    152        // computedNumberOfChannels.
    153        let destBuffer = context.createBuffer(
    154            computedNumberOfChannels, singleTestFrameLength,
    155            context.sampleRate);
    156 
    157        // Mix all of the connections into the destination buffer.
    158        for (let i = 0; i < connections.length; ++i) {
    159          let connectionNumberOfChannels =
    160              connections.charCodeAt(i) - '0'.charCodeAt(0);
    161          let sourceBuffer =
    162              testBuffers[connectionNumberOfChannels - 1];  // convert from
    163                                                            // 1-based to
    164                                                            // 0-based index
    165 
    166          if (channelInterpretation == 'speakers') {
    167            speakersSum(sourceBuffer, destBuffer);
    168          } else if (channelInterpretation == 'discrete') {
    169            discreteSum(sourceBuffer, destBuffer);
    170          } else {
    171            alert('Invalid channel interpretation!');
    172          }
    173        }
    174 
    175        // Use this when debugging mixing rules.
    176        // printTestInformation(testNumber, renderedBuffer, destBuffer,
    177        // singleTestFrameLength, sampleFrameOffset);
    178 
    179        // Validate that destBuffer matches the rendered output.  We need to
    180        // check the rendered output at a specific sample-frame-offset
    181        // corresponding to the specific test case we're checking for based on
    182        // testNumber.
    183 
    184        let sampleFrameOffset = testNumber * singleTestFrameLength;
    185        for (let c = 0; c < renderNumberOfChannels; ++c) {
    186          let renderedData = renderedBuffer.getChannelData(c);
    187          for (let frame = 0; frame < singleTestFrameLength; ++frame) {
    188            let renderedValue = renderedData[frame + sampleFrameOffset];
    189 
    190            let expectedValue = 0;
    191            if (c < destBuffer.numberOfChannels) {
    192              let expectedData = destBuffer.getChannelData(c);
    193              expectedValue = expectedData[frame];
    194            }
    195 
    196            // We may need to add an epsilon in the comparison if we add more
    197            // test vectors.
    198            if (renderedValue != expectedValue) {
    199              let message = s + 'rendered: ' + renderedValue +
    200                  ' expected: ' + expectedValue + ' channel: ' + c +
    201                  ' frame: ' + frame;
    202              // testFailed(s);
    203              should(renderedValue, s).beEqualTo(expectedValue);
    204              return;
    205            }
    206          }
    207        }
    208 
    209        should(true, s).beTrue();
    210      }
    211 
    212      function checkResult(buffer, should) {
    213        // Sanity check result.
    214        should(buffer.length, 'Rendered number of frames')
    215            .beEqualTo(numberOfTests * singleTestFrameLength);
    216        should(buffer.numberOfChannels, 'Rendered number of channels')
    217            .beEqualTo(renderNumberOfChannels);
    218 
    219        // Check all the tests.
    220        let testNumber = 0;
    221        for (let m = 0; m < mixingRulesList.length; ++m) {
    222          let mixingRules = mixingRulesList[m];
    223          for (let i = 0; i < connectionsList.length; ++i, ++testNumber) {
    224            checkTestResult(
    225                buffer, testNumber, connectionsList[i],
    226                mixingRules.channelCount, mixingRules.channelCountMode,
    227                mixingRules.channelInterpretation, should);
    228          }
    229        }
    230      }
    231 
    232      audit.define(
    233          {label: 'test', description: 'Channel mixing rules for AudioNodes'},
    234          function(task, should) {
    235 
    236            // Create 8-channel offline audio context.  Each test will render 8
    237            // sample-frames starting at sample-frame position testNumber * 8.
    238            let totalFrameLength = numberOfTests * singleTestFrameLength;
    239            context = new OfflineAudioContext(
    240                renderNumberOfChannels, totalFrameLength, sampleRate);
    241 
    242            // Set destination to discrete mixing.
    243            context.destination.channelCount = renderNumberOfChannels;
    244            context.destination.channelCountMode = 'explicit';
    245            context.destination.channelInterpretation = 'discrete';
    246 
    247            // Create test buffers from 1 to 8 channels.
    248            testBuffers = new Array();
    249            for (let i = 0; i < renderNumberOfChannels; ++i) {
    250              testBuffers[i] = createShiftedImpulseBuffer(
    251                  context, i + 1, singleTestFrameLength);
    252            }
    253 
    254            // Schedule all the tests.
    255            let testNumber = 0;
    256            for (let m = 0; m < mixingRulesList.length; ++m) {
    257              let mixingRules = mixingRulesList[m];
    258              for (let i = 0; i < connectionsList.length; ++i, ++testNumber) {
    259                scheduleTest(
    260                    testNumber, connectionsList[i], mixingRules.channelCount,
    261                    mixingRules.channelCountMode,
    262                    mixingRules.channelInterpretation);
    263              }
    264            }
    265 
    266            // Render then check results.
    267            // context.oncomplete = checkResult;
    268            context.startRendering().then(buffer => {
    269              checkResult(buffer, should);
    270              task.done();
    271            });
    272            ;
    273          });
    274 
    275      audit.run();
    276    </script>
    277  </body>
    278 </html>