DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
<!DOCTYPE HTML>
<html>
<head>
  <title>Media test: disable phase inversion in opus decoder</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<audio preload=none id="a" controls></audio>
<audio preload=none id="b" controls></audio>
<script class="testbody" type="text/javascript">
/*
  This test makes use of an (stereo) opus file with phase inversion of 180 degrees (right = -left => right + left = 0).
  Firstly, the phase inversion is verified on a normal stereo playback.
  Secondly, mono playback is forced which results in the phase inversion being disabled (Bug 1431810).
*/
SimpleTest.waitForExplicitFinish();

/* global a, b */

function areChannelsInverted(b1, b2) {
  for (var i = 0; i < b1.length; i++) {
    if (Math.abs(b1[i] + b2[i]) > 9e-2) {
      return false;
    }
  }
  return true;
}

function areChannelsEqual(b1, b2) {
  for (var i = 0; i < b1.length; i++) {
    if (Math.abs(b1[i] - b2[i]) > 9e-3) {
      return false;
    }
  }
  return true;
}

function isSilent(b) {
  for (var i = 0; i < b.length; i++) {
    if (b[i] != 0.0) {
      return false;
    }
  }
  return true;
}

function mediaElementWithPhaseInversion(audioContext, mediaElement, success) {
  let audio_source = audioContext.createMediaElementSource(mediaElement);
  let script_processor = audioContext.createScriptProcessor();
  audio_source.connect(script_processor);

  mediaElement.onplay = () => {
    script_processor.onaudioprocess = (e) => {
      let right = e.inputBuffer.getChannelData(0);
      let left = e.inputBuffer.getChannelData(1);

      // This is leading or trailing silence
      // produced by ScriptProcessor.
      if (isSilent(right) && isSilent(left)) {
        return;
      }

      ok(areChannelsInverted(right, left), "Channels must be inverted");
    }
  }

  mediaElement.onended = () => {
    ok(true, "End of file.");
    mediaElement.onended = null;
    script_processor.onaudioprocess = null;
    success();
  }

  mediaElement.src = "test-stereo-phase-inversion-180.opus";
  // Normal playback channels will by inverted
  mediaElement.play();
}

function mediaElementWithPhaseInversionDisabled(audioContext, mediaElement, success) {
  let audio_source = audioContext.createMediaElementSource(mediaElement);
  let script_processor = audioContext.createScriptProcessor();
  audio_source.connect(script_processor);

  mediaElement.onplay = () => {
    script_processor.onaudioprocess = (e) => {
      let right = e.inputBuffer.getChannelData(0);
      let left = e.inputBuffer.getChannelData(1);

      // This is leading or trailing silence
      // produced by ScriptProcessor.
      if (isSilent(right) && isSilent(left)) {
        return;
      }

      ok(!areChannelsInverted(right, left), "Channels must not be inverted");
      ok(areChannelsEqual(right, left), "Channels must be equal");
    }
  }

  mediaElement.onended = () => {
    ok(true, "End of file.");
    mediaElement.onended = null;
    script_processor.onaudioprocess = null;
    success();
  }

  mediaElement.src = "test-stereo-phase-inversion-180.opus";

  // Downmix to mono will force to disable opus phase inversion
  SpecialPowers.pushPrefEnv({"set": [["accessibility.monoaudio.enable", true]]})
  .then(() => {
    mediaElement.play();
  });
}

let ac = new AudioContext();

function testPhaseInversion(mediaElement) {
  return new Promise((accept, reject) => {
    mediaElementWithPhaseInversion(ac, a, accept);
  });
}

function testPhaseInversionDisabled(mediaElement) {
  return new Promise((accept, reject) => {
    mediaElementWithPhaseInversionDisabled(ac, b, accept);
  });
}

// Start testing
testPhaseInversion(a)
.then( () => testPhaseInversionDisabled(b) )
.then( () => SimpleTest.finish() )

</script>
</pre>
</body>
</html>