tor-browser

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

adding-events.html (5350B)


      1 <!doctype html>
      2 <html>
      3  <head>
      4    <title>Adding Events</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    <script src="/webaudio/resources/audio-param.js"></script>
      9  </head>
     10 
     11  <body>
     12    <script>
     13 
     14      // Arbitrary power of two to eliminate round-off in computing time from frame.
     15      const sampleRate = 8192;
     16 
     17      // Test insertion of an event in the middle of rendering.
     18      //
     19      // options dictionary:
     20      //   method - automation method to test
     21      //   prefix - string to use for prefixing messages
     22      async function testInsertion(options) {
     23        const {method, prefix} = options;
     24 
     25        // Channel 0 is the output for the test, and channel 1 is the
     26        // reference output.
     27        const context = new OfflineAudioContext({
     28          numberOfChannels: 2,
     29          length: sampleRate,
     30          sampleRate: sampleRate
     31        });
     32 
     33        const merger = new ChannelMergerNode(
     34            context, {numberOfChannels: context.destination.channelCount});
     35        merger.connect(context.destination);
     36 
     37        // Initial value and final values of the source node
     38        const initialValue = 1;
     39        const finalValue = 2;
     40 
     41        // Set up the node for the automations under test
     42        const src = new ConstantSourceNode(context, { offset: initialValue });
     43        src.connect(merger, 0, 0);
     44 
     45        // Set initial event to occur at this time.  Keep it in the first
     46        // render quantum.
     47        const initialEventTime = 64 / context.sampleRate;
     48        // Any exception will naturally fail the test.
     49        src.offset.setValueAtTime(initialValue, initialEventTime);
     50 
     51        // Let time pass and then add a new event with time in the future.
     52        const insertAtFrame = 512;
     53        const insertTime = insertAtFrame / context.sampleRate;
     54        const automationEndFrame = 1024 + 64;
     55        const automationEndTime = automationEndFrame / context.sampleRate;
     56 
     57        // Schedule the insertion while rendering is in progress.
     58        context.suspend(insertTime).then(() => {
     59          src.offset[method](finalValue, automationEndTime);
     60          context.resume();
     61        });
     62 
     63        // Set up graph for the reference result.  Automate the source with
     64        // the events scheduled from the beginning.  Let the gain node
     65        // simulate the insertion of the event above.  This is done by
     66        // setting the gain to 1 at the insertion time.
     67        const srcRef = new ConstantSourceNode(context, {offset: 1});
     68        const g = new GainNode(context, {gain: 0});
     69        srcRef.connect(g).connect(merger, 0, 1);
     70        srcRef.offset.setValueAtTime(initialValue, initialEventTime);
     71        srcRef.offset[method](finalValue, automationEndTime);
     72 
     73        // Allow everything through after |insertAtFrame| frames.
     74        g.gain.setValueAtTime(1, insertTime);
     75 
     76        // Go!
     77        src.start();
     78        srcRef.start();
     79 
     80        const audioBuffer = await context.startRendering();
     81 
     82        const actual = audioBuffer.getChannelData(0);
     83        const expected = audioBuffer.getChannelData(1);
     84 
     85        // Verify that the output is 1 until we reach
     86        // insertAtFrame. Ignore the expected data because that always
     87        // produces 1.
     88        {
     89          const actualBeforeInsert = actual.slice(0, insertAtFrame);
     90          const expectedBeforeInsert = new Float32Array(insertAtFrame);
     91          expectedBeforeInsert.fill(initialValue);
     92          assert_array_equal_within_eps(
     93              actualBeforeInsert,
     94              expectedBeforeInsert,
     95              0,
     96              `${prefix}: output[0:${insertAtFrame - 1}]`);
     97        }
     98 
     99        // Verify ramp is correct by comparing it to the expected
    100        {
    101          const rampStart = insertAtFrame;
    102          const rampEndInclusive = automationEndFrame;
    103          const rampEndExclusive = rampEndInclusive + 1;
    104 
    105          const actualRamp = actual.slice(rampStart, rampEndExclusive);
    106          const expectedRamp = expected.slice(rampStart, rampEndExclusive);
    107 
    108          assert_array_equal_within_eps(
    109              actualRamp,
    110              expectedRamp,
    111              {absoluteThreshold: 0},
    112              `${prefix}: output[${rampStart}:${rampEndInclusive}]`);
    113        }
    114 
    115        // Verify final output has the expected value
    116        {
    117          const tailStart = automationEndFrame + 1;
    118          const actualTail = actual.slice(tailStart);
    119          const refTail = new Float32Array(actualTail.length);
    120          refTail.fill(finalValue);
    121 
    122          assert_array_equal_within_eps(
    123              actualTail,
    124              refTail,
    125              0,
    126              `${prefix}: output[${tailStart}:]`);
    127        }
    128      }
    129 
    130      // Define tests (replacing audit.define/audit.run with promise_test)
    131      promise_test(async () => {
    132        await testInsertion({
    133          method: 'linearRampToValueAtTime',
    134          prefix: 'linearRamp'
    135        });
    136      }, 'linearRamp: Insert linearRamp after running for some time');
    137 
    138      promise_test(async () => {
    139        await testInsertion({
    140          method: 'exponentialRampToValueAtTime',
    141          prefix: 'exponentialRamp'
    142        });
    143      }, 'exponentialRamp: Insert exponentialRamp after running for some time');
    144    </script>
    145  </body>
    146 </html>