Bug 1069825 - Check if we compare two automation curves occuring at the same time during overlap checking. r=padenot
authorBaptiste Emmanuel <baptiste.em@gmail.com>
Mon, 01 Jun 2015 20:01:48 +0200
changeset 267288 22f39dd335cc5b62373e74ebbf07accd28208281
parent 267287 5978282a3c0a9b544e615b61eaa3e519d22aeafa
child 267289 faa66615c0a193cf79bae74e8b5b0b416d8f212c
push id29512
push userkwierso@gmail.com
push dateMon, 12 Oct 2015 18:07:18 +0000
treeherdermozilla-central@f8283eaf5aad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1069825
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1069825 - Check if we compare two automation curves occuring at the same time during overlap checking. r=padenot
dom/media/webaudio/AudioEventTimeline.h
dom/media/webaudio/compiledtest/TestAudioEventTimeline.cpp
dom/media/webaudio/test/mochitest.ini
dom/media/webaudio/test/test_audioParamSetCurveAtTimeTwice.html
--- a/dom/media/webaudio/AudioEventTimeline.h
+++ b/dom/media/webaudio/AudioEventTimeline.h
@@ -204,27 +204,34 @@ public:
       aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
       return false;
     }
 
     // Make sure that non-curve events don't fall within the duration of a
     // curve event.
     for (unsigned i = 0; i < mEvents.Length(); ++i) {
       if (mEvents[i].mType == AudioTimelineEvent::SetValueCurve &&
+          !(aEvent.mType == AudioTimelineEvent::SetValueCurve &&
+            aEvent.template Time<double>() == mEvents[i].template Time<double>()) &&
           mEvents[i].template Time<double>() <= aEvent.template Time<double>() &&
           (mEvents[i].template Time<double>() + mEvents[i].mDuration) >= aEvent.template Time<double>()) {
         aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
         return false;
       }
     }
 
     // Make sure that curve events don't fall in a range which includes other
     // events.
     if (aEvent.mType == AudioTimelineEvent::SetValueCurve) {
       for (unsigned i = 0; i < mEvents.Length(); ++i) {
+        // In case we have two curve at the same time
+        if (mEvents[i].mType == AudioTimelineEvent::SetValueCurve &&
+            mEvents[i].template Time<double>() == aEvent.template Time<double>()) {
+          continue;
+        }
         if (mEvents[i].template Time<double>() > aEvent.template Time<double>() &&
             mEvents[i].template Time<double>() < (aEvent.template Time<double>() + aEvent.mDuration)) {
           aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
           return false;
         }
       }
     }
 
--- a/dom/media/webaudio/compiledtest/TestAudioEventTimeline.cpp
+++ b/dom/media/webaudio/compiledtest/TestAudioEventTimeline.cpp
@@ -427,16 +427,29 @@ void TestExponentialInvalidPreviousZeroV
   is(rv, NS_ERROR_DOM_SYNTAX_ERR, "Correct error code returned");
   timeline.CancelScheduledValues(0.0);
   is(timeline.GetEventCount(), 0u, "Should have no events scheduled");
   rv = NS_OK;
   timeline.ExponentialRampToValueAtTime(1.f, 1.0, rv);
   is(rv, NS_OK, "Should succeed this time");
 }
 
+void
+TestSettingValueCurveTwice()
+{
+  Timeline timeline(0.f);
+  float curve[] = { -1.0f, 0.0f, 1.0f };
+
+  ErrorResultMock rv;
+
+  timeline.SetValueCurveAtTime(curve, ArrayLength(curve), 0.0f, 0.3f, rv);
+  timeline.SetValueCurveAtTime(curve, ArrayLength(curve), 0.0f, 0.3f, rv);
+  is(rv, NS_OK, "SetValueCurveAtTime succeeded");
+}
+
 int main()
 {
   ScopedXPCOM xpcom("TestAudioEventTimeline");
   if (xpcom.failed()) {
     return 1;
   }
 
   TestSpecExample();
@@ -452,12 +465,13 @@ int main()
   TestAfterLastTargetValueEventWithValueSet();
   TestValue();
   TestLinearRampAtZero();
   TestExponentialRampAtZero();
   TestLinearRampAtSameTime();
   TestExponentialRampAtSameTime();
   TestSetTargetZeroTimeConstant();
   TestExponentialInvalidPreviousZeroValue();
+  TestSettingValueCurveTwice();
 
   return gFailCount > 0;
 }
 
--- a/dom/media/webaudio/test/mochitest.ini
+++ b/dom/media/webaudio/test/mochitest.ini
@@ -52,16 +52,17 @@ skip-if = android_version == '10' # bug 
 [test_audioContextSuspendResumeClose.html]
 tags=capturestream
 [test_audioDestinationNode.html]
 [test_AudioListener.html]
 [test_audioParamExponentialRamp.html]
 [test_audioParamGain.html]
 [test_audioParamLinearRamp.html]
 [test_audioParamSetCurveAtTime.html]
+[test_audioParamSetCurveAtTimeTwice.html]
 [test_audioParamSetCurveAtTimeZeroDuration.html]
 [test_audioParamSetTargetAtTime.html]
 [test_audioParamSetValueAtTime.html]
 [test_audioParamTimelineDestinationOffset.html]
 [test_badConnect.html]
 [test_biquadFilterNode.html]
 [test_biquadFilterNodePassThrough.html]
 [test_biquadFilterNodeWithGain.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/webaudio/test/test_audioParamSetCurveAtTimeTwice.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test AudioParam.linearRampToValue</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="webaudio.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var T0 = 0;
+
+var gTest = {
+  length: 2048,
+  numberOfChannels: 1,
+  createGraph: function(context) {
+    var sourceBuffer = context.createBuffer(1, 2048, context.sampleRate);
+    for (var i = 0; i < 2048; ++i) {
+      sourceBuffer.getChannelData(0)[i] = 1;
+    }
+
+    var curve2 = new Float32Array(100);
+    for (var i = 0; i < 100; ++i) {
+      curve2[i] = Math.sin(220 * 6 * Math.PI * i / context.sampleRate);
+    }
+
+    var source = context.createBufferSource();
+    source.buffer = sourceBuffer;
+
+    var gain = context.createGain();
+    gain.gain.setValueCurveAtTime(curve2, T0, this.duration/2);
+    //Set a diffrent curve from the first one
+    gain.gain.setValueCurveAtTime(this.curve, T0, this.duration);
+
+    source.connect(gain);
+
+    source.start(0);
+    return gain;
+  },
+  createExpectedBuffers: function(context) {
+    this.duration = 1024 / context.sampleRate;
+    this.curve = new Float32Array(100);
+    for (var i = 0; i < 100; ++i) {
+      this.curve[i] = Math.sin(440 * 2 * Math.PI * i / context.sampleRate);
+    }
+    var expectedBuffer = context.createBuffer(1, 2048, context.sampleRate);
+    for (var i = 0; i < 2048; ++i) {
+      var t = i / context.sampleRate;
+      expectedBuffer.getChannelData(0)[i] = this.curve[Math.min(99, Math.floor(100 * Math.min(1.0, (t - T0) / this.duration)))];
+    }
+    return expectedBuffer;
+  },
+};
+
+runTest();
+
+</script>
+</pre>
+</body>
+</html>