tor-browser

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

test_bug1431810_opus_downmix_to_mono.html (3816B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <title>Media test: disable phase inversion in opus decoder</title>
      5  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      6  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
      7 </head>
      8 <body>
      9 <audio preload=none id="a" controls></audio>
     10 <audio preload=none id="b" controls></audio>
     11 <script class="testbody" type="text/javascript">
     12 /*
     13  This test makes use of an (stereo) opus file with phase inversion of 180 degrees (right = -left => right + left = 0).
     14  Firstly, the phase inversion is verified on a normal stereo playback.
     15  Secondly, mono playback is forced which results in the phase inversion being disabled (Bug 1431810).
     16 */
     17 SimpleTest.waitForExplicitFinish();
     18 
     19 /* global a, b */
     20 
     21 function areChannelsInverted(b1, b2) {
     22  for (var i = 0; i < b1.length; i++) {
     23    if (Math.abs(b1[i] + b2[i]) > 9e-2) {
     24      return false;
     25    }
     26  }
     27  return true;
     28 }
     29 
     30 function areChannelsEqual(b1, b2) {
     31  for (var i = 0; i < b1.length; i++) {
     32    if (Math.abs(b1[i] - b2[i]) > 9e-3) {
     33      return false;
     34    }
     35  }
     36  return true;
     37 }
     38 
     39 function isSilent(b) {
     40  for (var i = 0; i < b.length; i++) {
     41    if (b[i] != 0.0) {
     42      return false;
     43    }
     44  }
     45  return true;
     46 }
     47 
     48 function mediaElementWithPhaseInversion(audioContext, mediaElement, success) {
     49  let audio_source = audioContext.createMediaElementSource(mediaElement);
     50  let script_processor = audioContext.createScriptProcessor();
     51  audio_source.connect(script_processor);
     52 
     53  mediaElement.onplay = () => {
     54    script_processor.onaudioprocess = (e) => {
     55      let right = e.inputBuffer.getChannelData(0);
     56      let left = e.inputBuffer.getChannelData(1);
     57 
     58      // This is leading or trailing silence
     59      // produced by ScriptProcessor.
     60      if (isSilent(right) && isSilent(left)) {
     61        return;
     62      }
     63 
     64      ok(areChannelsInverted(right, left), "Channels must be inverted");
     65    }
     66  }
     67 
     68  mediaElement.onended = () => {
     69    ok(true, "End of file.");
     70    mediaElement.onended = null;
     71    script_processor.onaudioprocess = null;
     72    success();
     73  }
     74 
     75  mediaElement.src = "test-stereo-phase-inversion-180.opus";
     76  // Normal playback channels will by inverted
     77  mediaElement.play();
     78 }
     79 
     80 function mediaElementWithPhaseInversionDisabled(audioContext, mediaElement, success) {
     81  let audio_source = audioContext.createMediaElementSource(mediaElement);
     82  let script_processor = audioContext.createScriptProcessor();
     83  audio_source.connect(script_processor);
     84 
     85  mediaElement.onplay = () => {
     86    script_processor.onaudioprocess = (e) => {
     87      let right = e.inputBuffer.getChannelData(0);
     88      let left = e.inputBuffer.getChannelData(1);
     89 
     90      // This is leading or trailing silence
     91      // produced by ScriptProcessor.
     92      if (isSilent(right) && isSilent(left)) {
     93        return;
     94      }
     95 
     96      ok(!areChannelsInverted(right, left), "Channels must not be inverted");
     97      ok(areChannelsEqual(right, left), "Channels must be equal");
     98    }
     99  }
    100 
    101  mediaElement.onended = () => {
    102    ok(true, "End of file.");
    103    mediaElement.onended = null;
    104    script_processor.onaudioprocess = null;
    105    success();
    106  }
    107 
    108  mediaElement.src = "test-stereo-phase-inversion-180.opus";
    109 
    110  // Downmix to mono will force to disable opus phase inversion
    111  SpecialPowers.pushPrefEnv({"set": [["accessibility.monoaudio.enable", true]]})
    112  .then(() => {
    113    mediaElement.play();
    114  });
    115 }
    116 
    117 let ac = new AudioContext();
    118 
    119 function testPhaseInversion() {
    120  return new Promise((accept) => {
    121    mediaElementWithPhaseInversion(ac, a, accept);
    122  });
    123 }
    124 
    125 function testPhaseInversionDisabled() {
    126  return new Promise((accept) => {
    127    mediaElementWithPhaseInversionDisabled(ac, b, accept);
    128  });
    129 }
    130 
    131 // Start testing
    132 testPhaseInversion(a)
    133 .then( () => testPhaseInversionDisabled(b) )
    134 .then( () => SimpleTest.finish() )
    135 
    136 </script>
    137 </pre>
    138 </body>
    139 </html>