Bug 1127188 - Make test_audioContextSuspendResumeClose.html less flaky. r=ehsan
authorPaul Adenot <paul@paul.cx>
Wed, 20 May 2015 14:30:47 +0200
changeset 266230 f4eb790b69e7e7348649dc2ddde7b14ac17a0ec2
parent 266229 3f40bd7da24517bb6a740415d399f24ab84cf8fe
child 266231 bb4c4edce8a824976dd64f08ba203728e16218ef
push id2231
push usermichael.l.comella@gmail.com
push dateFri, 22 May 2015 20:04:59 +0000
reviewersehsan
bugs1127188
milestone41.0a1
Bug 1127188 - Make test_audioContextSuspendResumeClose.html less flaky. r=ehsan
dom/media/webaudio/test/test_audioContextSuspendResumeClose.html
--- a/dom/media/webaudio/test/test_audioContextSuspendResumeClose.html
+++ b/dom/media/webaudio/test/test_audioContextSuspendResumeClose.html
@@ -89,137 +89,127 @@ function tryLegalOpeerationsOnClosedCont
 // producing silence
 // ac1 produce a sine fed to a MediaStreamAudioDestinationNode
 // ac2 is connected to ac1 with a MediaStreamAudioSourceNode, and check that
 // there is silence when ac1 is suspended
 function testMultiContextOutput() {
   var ac1 = new AudioContext(),
       ac2 = new AudioContext();
 
-  var osc1 = ac1.createOscillator(),
-      mediaStreamDestination1 = ac1.createMediaStreamDestination();
+  ac1.onstatechange = function() {
+    ac1.onstatechange = null;
 
-  var mediaStreamAudioSourceNode2 =
-    ac2.createMediaStreamSource(mediaStreamDestination1.stream),
-    sp2 = ac2.createScriptProcessor(),
-    suspendCalled = false,
-    silentBuffersInARow = 0;
+    var osc1 = ac1.createOscillator(),
+        mediaStreamDestination1 = ac1.createMediaStreamDestination();
+
+    var mediaStreamAudioSourceNode2 =
+      ac2.createMediaStreamSource(mediaStreamDestination1.stream),
+      sp2 = ac2.createScriptProcessor(),
+      silentBuffersInARow = 0;
 
 
-  sp2.onaudioprocess = function(e) {
-    if (!suspendCalled) {
-      ac1.suspend();
-      suspendCalled = true;
-    } else {
-      // Wait until the context that produce the tone is actually suspended. It
-      // can be that the second context receives a little amount of data because
-      // of the buffering between the two contexts.
-      if (ac1.state == "suspended") {
-        var input = e.inputBuffer.getChannelData(0);
-        var silent = true;
-        for (var i = 0; i < input.length; i++) {
-          if (input[i] != 0.0) {
-            silent = false;
-          }
-        }
+    sp2.onaudioprocess = function(e) {
+      ac1.suspend().then(function() {
+        is(ac1.state, "suspended", "ac1 is suspended");
+        sp2.onaudioprocess = checkSilence;
+      });
+      sp2.onaudioprocess = null;
+    }
 
-        if (silent) {
-          silentBuffersInARow++;
-          if (silentBuffersInARow == 10) {
-            ok(true,
-                "MediaStreams produce silence when their input is blocked.");
-            sp2.onaudioprocess = null;
-            ac1.close();
-            ac2.close();
-            todo(false,"1");
-            finish();
-          }
-        } else {
-          is(silentBuffersInARow, 0,
-              "No non silent buffer inbetween silent buffers.");
+    function checkSilence(e) {
+      var input = e.inputBuffer.getChannelData(0);
+      var silent = true;
+      for (var i = 0; i < input.length; i++) {
+        if (input[i] != 0.0) {
+          silent = false;
         }
       }
-    }
-  }
+
+      todo(false, "input buffer is " + (silent ? "silent" : "noisy"));
 
-  osc1.connect(mediaStreamDestination1);
+      if (silent) {
+        silentBuffersInARow++;
+        if (silentBuffersInARow == 10) {
+          ok(true,
+              "MediaStreams produce silence when their input is blocked.");
+          sp2.onaudioprocess = null;
+          ac1.close();
+          ac2.close();
+          todo(false,"1");
+          finish();
+        }
+      } else {
+        is(silentBuffersInARow, 0,
+            "No non silent buffer inbetween silent buffers.");
+      }
+    }
 
-  mediaStreamAudioSourceNode2.connect(sp2);
-  osc1.start();
+    osc1.connect(mediaStreamDestination1);
+
+    mediaStreamAudioSourceNode2.connect(sp2);
+    osc1.start();
+  }
 }
 
 
 // Test that there is no buffering between contexts when connecting a running
 // AudioContext to a suspended AudioContext. Our ScriptProcessorNode does some
 // buffering internally, so we ensure this by using a very very low frequency
 // on a sine, and oberve that the phase has changed by a big enough margin.
 function testMultiContextInput() {
   var ac1 = new AudioContext(),
       ac2 = new AudioContext();
 
-  var osc1 = ac1.createOscillator(),
-      mediaStreamDestination1 = ac1.createMediaStreamDestination(),
-      sp1 = ac1.createScriptProcessor();
+  ac1.onstatechange = function() {
+    ac1.onstatechange = null;
 
-  var mediaStreamAudioSourceNode2 =
-    ac2.createMediaStreamSource(mediaStreamDestination1.stream),
-    sp2 = ac2.createScriptProcessor(),
-    resumed = false,
-    suspended = false,
-    countEventOnFirstSP = true,
-    eventReceived = 0;
+    var osc1 = ac1.createOscillator(),
+        mediaStreamDestination1 = ac1.createMediaStreamDestination(),
+        sp1 = ac1.createScriptProcessor();
+
+    var mediaStreamAudioSourceNode2 =
+      ac2.createMediaStreamSource(mediaStreamDestination1.stream),
+      sp2 = ac2.createScriptProcessor(),
+      eventReceived = 0;
 
 
-  osc1.frequency.value = 0.0001;
+    osc1.frequency.value = 0.0001;
 
-  // We keep a first ScriptProcessor to get a periodic callback, since we can't
-  // use setTimeout anymore.
-  sp1.onaudioprocess = function(e) {
-    if (countEventOnFirstSP) {
-      eventReceived++;
-    }
-    if (eventReceived > 3 && suspended) {
-      countEventOnFirstSP = false;
-      eventReceived = 0;
-      ac2.resume().then(function() {
-        resumed = true;
-      });
-    }
-  }
-
-  sp2.onaudioprocess = function(e) {
-    var inputBuffer = e.inputBuffer.getChannelData(0);
-    if (!resumed) {
-      // save the last value of the buffer before suspending.
-      sp2.value = inputBuffer[inputBuffer.length - 1];
-      ac2.suspend().then(function() {
-        suspended = true;
-      });
-    } else {
-      eventReceived++;
-      if (eventReceived == 3) {
+    function checkDiscontinuity(e) {
+      var inputBuffer = e.inputBuffer.getChannelData(0);
+      if (eventReceived++ == 3) {
         var delta = Math.abs(inputBuffer[1] - sp2.value),
             theoreticalIncrement = 2048 * 3 * Math.PI * 2 * osc1.frequency.value / ac1.sampleRate;
         ok(delta >= theoreticalIncrement,
             "Buffering did not occur when the context was suspended (delta:" + delta + " increment: " + theoreticalIncrement+")");
         ac1.close();
         ac2.close();
         sp1.onaudioprocess = null;
         sp2.onaudioprocess = null;
         todo(false, "2");
         finish();
       }
     }
-  }
 
-  osc1.connect(mediaStreamDestination1);
-  osc1.connect(sp1);
+    sp2.onaudioprocess = function(e) {
+      var inputBuffer = e.inputBuffer.getChannelData(0);
+      sp2.value = inputBuffer[inputBuffer.length - 1];
+      ac2.suspend().then(function() {
+          ac2.resume().then(function() {
+            sp2.onaudioprocess = checkDiscontinuity;
+            });
+          });
+    }
 
-  mediaStreamAudioSourceNode2.connect(sp2);
-  osc1.start();
+    osc1.connect(mediaStreamDestination1);
+    osc1.connect(sp1);
+
+    mediaStreamAudioSourceNode2.connect(sp2);
+    osc1.start();
+  }
 }
 
 // Test that ScriptProcessorNode's onaudioprocess don't get called while the
 // context is suspended/closed. It is possible that we get the handler called
 // exactly once after suspend, because the event has already been sent to the
 // event loop.
 function testScriptProcessNodeSuspended() {
   var ac = new AudioContext();