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>