tor-browser

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

audiobuffer-copy-channel.html (12276B)


      1 <!DOCTYPE html>
      2 <html>
      3  <head>
      4    <title>
      5      Test Basic Functionality of AudioBuffer.copyFromChannel and
      6      AudioBuffer.copyToChannel
      7    </title>
      8    <script src="/resources/testharness.js"></script>
      9    <script src="/resources/testharnessreport.js"></script>
     10    <script src="/webaudio/resources/audit-util.js"></script>
     11    <script src="/webaudio/resources/audit.js"></script>
     12  </head>
     13  <body>
     14    <script id="layout-test-code">
     15      // Define utility routines.
     16 
     17      // Initialize the AudioBuffer |buffer| with a ramp signal on each channel.
     18      // The ramp starts at channel number + 1.
     19      function initializeAudioBufferRamp(buffer) {
     20        for (let c = 0; c < buffer.numberOfChannels; ++c) {
     21          let d = buffer.getChannelData(c);
     22          for (let k = 0; k < d.length; ++k) {
     23            d[k] = k + c + 1;
     24          }
     25        }
     26      }
     27 
     28      // Create a Float32Array of length |length| and initialize the array to
     29      // -1.
     30      function createInitializedF32Array(length) {
     31        let x = new Float32Array(length);
     32        for (let k = 0; k < length; ++k) {
     33          x[k] = -1;
     34        }
     35        return x;
     36      }
     37 
     38      // Create a Float32Array of length |length| that is initialized to be a
     39      // ramp starting at 1.
     40      function createFloat32RampArray(length) {
     41        let x = new Float32Array(length);
     42        for (let k = 0; k < x.length; ++k) {
     43          x[k] = k + 1;
     44        }
     45 
     46        return x;
     47      }
     48 
     49      // Test that the array |x| is a ramp starting at value |start| of length
     50      // |length|, starting at |startIndex| in the array.  |startIndex| is
     51      // optional and defaults to 0. Any other values must be -1.
     52      function shouldBeRamp(
     53          should, testName, x, startValue, length, startIndex) {
     54        let k;
     55        let startingIndex = startIndex || 0;
     56        let expected = Array(x.length);
     57 
     58        // Fill the expected array with the correct results.
     59 
     60        // The initial part (if any) must be -1.
     61        for (k = 0; k < startingIndex; ++k) {
     62          expected[k] = -1;
     63        }
     64 
     65        // The second part should be a ramp starting with |startValue|
     66        for (; k < startingIndex + length; ++k) {
     67          expected[k] = startValue + k - startingIndex;
     68        }
     69 
     70        // The last part (if any) should be -1.
     71        for (; k < x.length; ++k) {
     72          expected[k] = -1;
     73        }
     74 
     75        should(x, testName, {numberOfArrayLog: 32}).beEqualToArray(expected);
     76      }
     77 
     78      let audit = Audit.createTaskRunner();
     79 
     80      let context = new AudioContext();
     81      // Temp array for testing exceptions for copyToChannel/copyFromChannel.
     82      // The length is arbitrary.
     83      let x = new Float32Array(8);
     84 
     85      // Number of frames in the AudioBuffer for testing.  This is pretty
     86      // arbitrary so choose a fairly small value.
     87      let bufferLength = 16;
     88 
     89      // Number of channels in the AudioBuffer.  Also arbitrary, but it should
     90      // be greater than 1 for test coverage.
     91      let numberOfChannels = 3;
     92 
     93      // AudioBuffer that will be used for testing copyFrom and copyTo.
     94      let buffer = context.createBuffer(
     95          numberOfChannels, bufferLength, context.sampleRate);
     96 
     97      let initialValues = Array(numberOfChannels);
     98 
     99      // Initialize things
    100      audit.define('initialize', (task, should) => {
    101        // Initialize to -1.
    102        initialValues.fill(-1);
    103        should(initialValues, 'Initialized values').beConstantValueOf(-1)
    104        task.done();
    105      });
    106 
    107      // Test that expected exceptions are signaled for copyFrom.
    108      audit.define('copyFrom-exceptions', (task, should) => {
    109        should(
    110            AudioBuffer.prototype.copyFromChannel,
    111            'AudioBuffer.prototype.copyFromChannel')
    112            .exist();
    113 
    114        should(
    115            () => {
    116              buffer = context.createBuffer(
    117                  numberOfChannels, bufferLength, context.sampleRate);
    118            },
    119            '0: buffer = context.createBuffer(' + numberOfChannels + ', ' +
    120                bufferLength + ', context.sampleRate)')
    121            .notThrow();
    122        should(() => {
    123          buffer.copyFromChannel(null, 0);
    124        }, '1: buffer.copyFromChannel(null, 0)').throw(TypeError);
    125        should(() => {
    126          buffer.copyFromChannel(context, 0);
    127        }, '2: buffer.copyFromChannel(context, 0)').throw(TypeError);
    128        should(() => {
    129          buffer.copyFromChannel(x, -1);
    130        }, '3: buffer.copyFromChannel(x, -1)').throw(DOMException, 'IndexSizeError');
    131        should(
    132            () => {
    133              buffer.copyFromChannel(x, numberOfChannels);
    134            },
    135            '4: buffer.copyFromChannel(x, ' + numberOfChannels + ')')
    136            .throw(DOMException, 'IndexSizeError');
    137        ;
    138        should(() => {
    139          buffer.copyFromChannel(x, 0, -1);
    140        }, '5: buffer.copyFromChannel(x, 0, -1)').notThrow();
    141        should(
    142            () => {
    143              buffer.copyFromChannel(x, 0, bufferLength);
    144            },
    145            '6: buffer.copyFromChannel(x, 0, ' + bufferLength + ')')
    146            .notThrow();
    147 
    148        should(() => {
    149          buffer.copyFromChannel(x, 3);
    150        }, '7: buffer.copyFromChannel(x, 3)').throw(DOMException, 'IndexSizeError');
    151 
    152        // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()`
    153        // WebAssembly.Memory's size is in multiples of 64 KiB
    154        const shared_buffer = new Float32Array(new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer);
    155        should(
    156            () => {
    157              buffer.copyFromChannel(shared_buffer, 0);
    158            },
    159            '8: buffer.copyFromChannel(SharedArrayBuffer view, 0)')
    160            .throw(TypeError);
    161 
    162        should(
    163            () => {
    164              buffer.copyFromChannel(shared_buffer, 0, 0);
    165            },
    166            '9: buffer.copyFromChannel(SharedArrayBuffer view, 0, 0)')
    167            .throw(TypeError);
    168 
    169        task.done();
    170      });
    171 
    172      // Test that expected exceptions are signaled for copyTo.
    173      audit.define('copyTo-exceptions', (task, should) => {
    174        should(
    175            AudioBuffer.prototype.copyToChannel,
    176            'AudioBuffer.prototype.copyToChannel')
    177            .exist();
    178        should(() => {
    179          buffer.copyToChannel(null, 0);
    180        }, '0: buffer.copyToChannel(null, 0)').throw(TypeError);
    181        should(() => {
    182          buffer.copyToChannel(context, 0);
    183        }, '1: buffer.copyToChannel(context, 0)').throw(TypeError);
    184        should(() => {
    185          buffer.copyToChannel(x, -1);
    186        }, '2: buffer.copyToChannel(x, -1)').throw(DOMException, 'IndexSizeError');
    187        should(
    188            () => {
    189              buffer.copyToChannel(x, numberOfChannels);
    190            },
    191            '3: buffer.copyToChannel(x, ' + numberOfChannels + ')')
    192            .throw(DOMException, 'IndexSizeError');
    193        should(() => {
    194          buffer.copyToChannel(x, 0, -1);
    195        }, '4: buffer.copyToChannel(x, 0, -1)').notThrow();
    196        should(
    197            () => {
    198              buffer.copyToChannel(x, 0, bufferLength);
    199            },
    200            '5: buffer.copyToChannel(x, 0, ' + bufferLength + ')')
    201            .notThrow();
    202 
    203        should(() => {
    204          buffer.copyToChannel(x, 3);
    205        }, '6: buffer.copyToChannel(x, 3)').throw(DOMException, 'IndexSizeError');
    206 
    207        // See https://github.com/whatwg/html/issues/5380 for why not `new SharedArrayBuffer()`
    208        // WebAssembly.Memory's size is in multiples of 64 KiB
    209        const shared_buffer = new Float32Array(new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer);
    210        should(
    211            () => {
    212              buffer.copyToChannel(shared_buffer, 0);
    213            },
    214            '7: buffer.copyToChannel(SharedArrayBuffer view, 0)')
    215            .throw(TypeError);
    216 
    217        should(
    218            () => {
    219              buffer.copyToChannel(shared_buffer, 0, 0);
    220            },
    221            '8: buffer.copyToChannel(SharedArrayBuffer view, 0, 0)')
    222            .throw(TypeError);
    223 
    224        task.done();
    225      });
    226 
    227      // Test copyFromChannel
    228      audit.define('copyFrom-validate', (task, should) => {
    229        // Initialize the AudioBuffer to a ramp for testing copyFrom.
    230        initializeAudioBufferRamp(buffer);
    231 
    232        // Test copyFrom operation with a short destination array, filling the
    233        // destination completely.
    234        for (let c = 0; c < numberOfChannels; ++c) {
    235          let dst8 = createInitializedF32Array(8);
    236          buffer.copyFromChannel(dst8, c);
    237          shouldBeRamp(
    238              should, 'buffer.copyFromChannel(dst8, ' + c + ')', dst8, c + 1, 8)
    239        }
    240 
    241        // Test copyFrom operation with a short destination array using a
    242        // non-zero start index that still fills the destination completely.
    243        for (let c = 0; c < numberOfChannels; ++c) {
    244          let dst8 = createInitializedF32Array(8);
    245          buffer.copyFromChannel(dst8, c, 1);
    246          shouldBeRamp(
    247              should, 'buffer.copyFromChannel(dst8, ' + c + ', 1)', dst8, c + 2,
    248              8)
    249        }
    250 
    251        // Test copyFrom operation with a short destination array using a
    252        // non-zero start index that does not fill the destinatiom completely.
    253        // The extra elements should be unchanged.
    254        for (let c = 0; c < numberOfChannels; ++c) {
    255          let dst8 = createInitializedF32Array(8);
    256          let startInChannel = bufferLength - 5;
    257          buffer.copyFromChannel(dst8, c, startInChannel);
    258          shouldBeRamp(
    259              should,
    260              'buffer.copyFromChannel(dst8, ' + c + ', ' + startInChannel + ')',
    261              dst8, c + 1 + startInChannel, bufferLength - startInChannel);
    262        }
    263 
    264        // Copy operation with the destination longer than the buffer, leaving
    265        // the trailing elements of the destination untouched.
    266        for (let c = 0; c < numberOfChannels; ++c) {
    267          let dst26 = createInitializedF32Array(bufferLength + 10);
    268          buffer.copyFromChannel(dst26, c);
    269          shouldBeRamp(
    270              should, 'buffer.copyFromChannel(dst26, ' + c + ')', dst26, c + 1,
    271              bufferLength);
    272        }
    273 
    274        task.done();
    275      });
    276 
    277      // Test copyTo
    278      audit.define('copyTo-validate', (task, should) => {
    279        // Create a source consisting of a ramp starting at 1, longer than the
    280        // AudioBuffer
    281        let src = createFloat32RampArray(bufferLength + 10);
    282 
    283        // Test copyTo with AudioBuffer shorter than Float32Array. The
    284        // AudioBuffer should be completely filled with the Float32Array.
    285        should(
    286            () => {
    287              buffer =
    288                  createConstantBuffer(context, bufferLength, initialValues);
    289            },
    290            'buffer = createConstantBuffer(context, ' + bufferLength + ', [' +
    291                initialValues + '])')
    292            .notThrow();
    293 
    294        for (let c = 0; c < numberOfChannels; ++c) {
    295          buffer.copyToChannel(src, c);
    296          shouldBeRamp(
    297              should, 'buffer.copyToChannel(src, ' + c + ')',
    298              buffer.getChannelData(c), 1, bufferLength);
    299        }
    300 
    301        // Test copyTo with AudioBuffer longer than the Float32Array.  The tail
    302        // of the AudioBuffer should be unchanged.
    303        buffer = createConstantBuffer(context, bufferLength, initialValues);
    304        let src10 = createFloat32RampArray(10);
    305        for (let c = 0; c < numberOfChannels; ++c) {
    306          buffer.copyToChannel(src10, c);
    307          shouldBeRamp(
    308              should, 'buffer.copyToChannel(src10, ' + c + ')',
    309              buffer.getChannelData(c), 1, 10);
    310        }
    311 
    312        // Test copyTo with non-default startInChannel.  Part of the AudioBuffer
    313        // should filled with the beginning and end sections untouched.
    314        buffer = createConstantBuffer(context, bufferLength, initialValues);
    315        for (let c = 0; c < numberOfChannels; ++c) {
    316          let startInChannel = 5;
    317          buffer.copyToChannel(src10, c, startInChannel);
    318 
    319          shouldBeRamp(
    320              should,
    321              'buffer.copyToChannel(src10, ' + c + ', ' + startInChannel + ')',
    322              buffer.getChannelData(c), 1, src10.length, startInChannel);
    323        }
    324        task.done();
    325      });
    326 
    327      audit.run();
    328    </script>
    329  </body>
    330 </html>