tor-browser

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

test_bug1447273.html (7239B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Test bug 1447273 - GainNode with a stereo input and changing volume</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <script type="text/javascript" src="webaudio.js"></script>
      7  <script type="text/javascript" src="head.js"></script>
      8  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      9 </head>
     10 <body>
     11 <pre id="test">
     12 <script class="testbody" type="text/javascript">
     13 /**
     14 * Sets up a stereo BufferSource and plumbs it through different gain node
     15 * configurations. A control gain path with no changes to gain is used along
     16 * with 2 other paths which should increase their gain. The result should be
     17 * that audio travelling along the increased gain paths is louder than the
     18 * control path.
     19 */
     20 
     21 SimpleTest.waitForExplicitFinish();
     22 SimpleTest.requestFlakyTimeout(
     23  "This test uses a live audio context and uses a setTimeout to schedule a " +
     24  "change to the graph.");
     25 addLoadEvent(function() {
     26  let context = new AudioContext();
     27 
     28  let numChannels = 2;
     29  let sampleRate = context.sampleRate;
     30  // 60 seconds to mitigate timing issues on slow test machines
     31  let recordingLength = 60;
     32  let bufferLength = sampleRate * recordingLength;
     33  let gainExplicitlyIncreased = false;
     34  let sourceFinished = false;
     35 
     36  // Create source buffer
     37  let sourceBuffer = context.createBuffer(numChannels, bufferLength, sampleRate);
     38  for (let i = 0; i < bufferLength; ++i) {
     39    sourceBuffer.getChannelData(0)[i] = 1;
     40    sourceBuffer.getChannelData(1)[i] = 1;
     41  }
     42  let source = context.createBufferSource();
     43  source.buffer = sourceBuffer;
     44 
     45  let gainNoChange = context.createGain();
     46  let gainExplicitAssignment = context.createGain();
     47  let gainSetValueAtTime = context.createGain();
     48 
     49  // All gain nodes start of with the same gain
     50  gainNoChange.gain.value = 0.25;
     51  gainExplicitAssignment.gain.value = 0.25;
     52  gainSetValueAtTime.gain.value = 0.25;
     53 
     54  // Connect source to gain nodes:
     55  // source--> gainNoChange
     56  //       |-> gainExplicitAssignment
     57  //       \-> gainSetValueAtTime
     58  source.connect(gainNoChange);
     59  source.connect(gainExplicitAssignment);
     60  source.connect(gainSetValueAtTime);
     61 
     62  // Create intermediate media streams (required to repro bug 1447273)
     63  let destNoChange = context.createMediaStreamDestination();
     64  let destExplicitAssignement = context.createMediaStreamDestination();
     65  let destSetValueAtTime = context.createMediaStreamDestination();
     66 
     67  let sourceNoChange = context.createMediaStreamSource(destNoChange.stream);
     68  let sourceExplicitAssignement = context.createMediaStreamSource(destExplicitAssignement.stream);
     69  let sourceSetValueAtTime = context.createMediaStreamSource(destSetValueAtTime.stream);
     70 
     71  // Connect gain nodes to our intermediate streams:
     72  // source--> gainNoChange           -> destNoChange            -> sourceNoChange
     73  //       |-> gainExplicitAssignment -> destExplicitAssignement -> sourceExplicitAssignement
     74  //       \-> gainSetValueAtTime     -> destSetValueAtTime      -> sourceSetValueAtTime
     75  gainNoChange.connect(destNoChange);
     76  gainExplicitAssignment.connect(destExplicitAssignement);
     77  gainSetValueAtTime.connect(destSetValueAtTime);
     78 
     79  // Create analysers for each path
     80  let analyserNoChange = context.createAnalyser();
     81  let analyserExplicitAssignment = context.createAnalyser();
     82  let analyserSetValueAtTime = context.createAnalyser();
     83 
     84  // Connect our intermediate media streams to analysers:
     85  // source--> gainNoChange           -> destNoChange            -> sourceNoChange            -> analyserNoChange
     86  //       |-> gainExplicitAssignment -> destExplicitAssignement -> sourceExplicitAssignement -> analyserExplicitAssignment
     87  //       \-> gainSetValueAtTime     -> destSetValueAtTime      -> sourceSetValueAtTime      -> analyserSetValueAtTime
     88  sourceNoChange.connect(analyserNoChange);
     89  sourceExplicitAssignement.connect(analyserExplicitAssignment);
     90  sourceSetValueAtTime.connect(analyserSetValueAtTime);
     91 
     92  // Two seconds in, increase gain for setValueAt path
     93  gainSetValueAtTime.gain.setValueAtTime(0.5, 2);
     94 
     95  // Maximum values seen at each analyser node, will be updated by
     96  // checkAnalysersForMaxValues() during test.
     97  let maxNoGainChange = 0;
     98  let maxExplicitAssignment = 0;
     99  let maxSetValueAtTime = 0;
    100 
    101  // Poll analysers and check for max values
    102  function checkAnalysersForMaxValues() {
    103    let findMaxValue =
    104      (array) => array.reduce((a, b) => Math.max(Math.abs(a), Math.abs(b)));
    105 
    106    let dataArray = new Float32Array(analyserNoChange.fftSize);
    107    analyserNoChange.getFloatTimeDomainData(dataArray);
    108    maxNoGainChange = Math.max(maxNoGainChange, findMaxValue(dataArray));
    109 
    110    analyserExplicitAssignment.getFloatTimeDomainData(dataArray);
    111    maxExplicitAssignment = Math.max(maxExplicitAssignment, findMaxValue(dataArray));
    112 
    113    analyserSetValueAtTime.getFloatTimeDomainData(dataArray);
    114    maxSetValueAtTime = Math.max(maxSetValueAtTime, findMaxValue(dataArray));
    115 
    116    // End test if we've met our conditions
    117    // Add a small amount to initial gain to make sure we're not getting
    118    // passes due to rounding errors.
    119    let epsilon = 0.01;
    120    if (maxExplicitAssignment > (maxNoGainChange + epsilon) &&
    121        maxSetValueAtTime > (maxNoGainChange + epsilon)) {
    122      source.stop();
    123    }
    124  }
    125 
    126  source.onended = () => {
    127    sourceFinished = true;
    128    info(`maxNoGainChange: ${maxNoGainChange}`);
    129    info(`maxExplicitAssignment: ${maxExplicitAssignment}`);
    130    info(`maxSetValueAtTime: ${maxSetValueAtTime}`);
    131    ok(gainExplicitlyIncreased,
    132       "Gain should be explicitly assinged during test!");
    133    // Add a small amount to initial gain to make sure we're not getting
    134    // passes due to rounding errors.
    135    let epsilon = 0.01;
    136    ok(maxExplicitAssignment > (maxNoGainChange + epsilon),
    137       "Volume should increase due to explicit assignment to gain.value");
    138    ok(maxSetValueAtTime > (maxNoGainChange + epsilon),
    139       "Volume should increase due to setValueAtTime on gain.value");
    140    SimpleTest.finish();
    141  };
    142 
    143  // Start the graph
    144  source.start(0);
    145 
    146  // We'll use this callback to check our analysers for gain
    147  function animationFrameCb() {
    148    if (sourceFinished) {
    149      return;
    150    }
    151    requestAnimationFrame(animationFrameCb);
    152    checkAnalysersForMaxValues();
    153  }
    154 
    155  // Using timers is gross, but as of writing there doesn't appear to be a
    156  // nicer way to perform gain.value = 0.5 on our node. When/if we support
    157  // suspend(time) on offline contexts we could potentially use that instead.
    158 
    159  // Roughly 2 seconds through our source buffer (setTimeout flakiness) increase
    160  // our gain on gainExplicitAssignment path.
    161  window.setTimeout(() => {
    162    gainExplicitAssignment.gain.value = 0.5;
    163    // Make debugging flaky timeouts in test easier
    164    info("Gain explicitly set!")
    165    gainExplicitlyIncreased = true;
    166    // Start checking analysers, we do this only after changing volume to avoid
    167    // possible starvation of this timeout from requestAnimationFrame calls.
    168    animationFrameCb();
    169  }, 2000);
    170 });
    171 
    172 </script>
    173 </pre>
    174 </body>
    175 </html>