Bug 1308436 - Adjust the AudioParam processing algorithm to match the spec. r=karlt
authorPaul Adenot <paul@paul.cx>
Wed, 22 Aug 2018 18:47:03 +0200
changeset 482529 9f2140bc66e3e454984d139dc185f2cf9fd0411d
parent 482528 0a729b75c155246473d1c00a9f5622e8e3607530
child 482530 9ad67bac864379a1784263b61fd084412673ced4
push id232
push userfmarier@mozilla.com
push dateWed, 05 Sep 2018 20:45:54 +0000
reviewerskarlt
bugs1308436
milestone63.0a1
Bug 1308436 - Adjust the AudioParam processing algorithm to match the spec. r=karlt Ramps now take into account the end of the curve as a start value for their automation. Differential Revision: https://phabricator.services.mozilla.com/D3792
dom/media/webaudio/AudioEventTimeline.cpp
--- a/dom/media/webaudio/AudioEventTimeline.cpp
+++ b/dom/media/webaudio/AudioEventTimeline.cpp
@@ -216,46 +216,61 @@ AudioEventTimeline::GetValuesAtTimeHelpe
                                     const AudioTimelineEvent* aPrevious,
                                     const AudioTimelineEvent* aNext)
 {
   // If the requested time is before all of the existing events
   if (!aPrevious) {
      return mValue;
   }
 
+  // If this event is a curve event, this returns the end time of the curve.
+  // Otherwise, this returns the time of the event.
   auto TimeOf = [](const AudioTimelineEvent* aEvent) -> TimeType {
+    if (aEvent->mType == AudioTimelineEvent::SetValueCurve) {
+      return aEvent->template Time<TimeType>() + aEvent->mDuration;
+    }
     return aEvent->template Time<TimeType>();
   };
 
+  // Value for an event. For a ValueCurve event, this is the value of the last
+  // element of the curve.
+  auto ValueOf = [](const AudioTimelineEvent* aEvent) -> float {
+    if (aEvent->mType == AudioTimelineEvent::SetValueCurve) {
+      return aEvent->mCurve[aEvent->mCurveLength - 1];
+    }
+    return aEvent->mValue;
+  };
+
   // SetTarget nodes can be handled no matter what their next node is (if
   // they have one)
   if (aPrevious->mType == AudioTimelineEvent::SetTarget) {
     return ExponentialApproach(TimeOf(aPrevious),
-                               mLastComputedValue, aPrevious->mValue,
+                               mLastComputedValue, ValueOf(aPrevious),
                                aPrevious->mTimeConstant, aTime);
   }
 
   // SetValueCurve events can be handled no matter what their next node is
-  // (if they have one)
-  if (aPrevious->mType == AudioTimelineEvent::SetValueCurve) {
-    return ExtractValueFromCurve(TimeOf(aPrevious),
+  // (if they have one), when aTime is in the curve region.
+  if (aPrevious->mType == AudioTimelineEvent::SetValueCurve &&
+      aTime <= aPrevious->template Time<TimeType>() + aPrevious->mDuration) {
+    return ExtractValueFromCurve(aPrevious->template Time<TimeType>(),
                                  aPrevious->mCurve, aPrevious->mCurveLength,
                                  aPrevious->mDuration, aTime);
   }
 
   // If the requested time is after all of the existing events
   if (!aNext) {
     switch (aPrevious->mType) {
       case AudioTimelineEvent::SetValueAtTime:
       case AudioTimelineEvent::LinearRamp:
       case AudioTimelineEvent::ExponentialRamp:
         // The value will be constant after the last event
         return aPrevious->mValue;
       case AudioTimelineEvent::SetValueCurve:
-        return ExtractValueFromCurve(TimeOf(aPrevious),
+        return ExtractValueFromCurve(aPrevious->template Time<TimeType>(),
                                      aPrevious->mCurve, aPrevious->mCurveLength,
                                      aPrevious->mDuration, aTime);
       case AudioTimelineEvent::SetTarget:
         MOZ_FALLTHROUGH_ASSERT("AudioTimelineEvent::SetTarget");
       case AudioTimelineEvent::SetValue:
       case AudioTimelineEvent::Cancel:
       case AudioTimelineEvent::Stream:
         MOZ_ASSERT(false, "Should have been handled earlier.");
@@ -264,25 +279,25 @@ AudioEventTimeline::GetValuesAtTimeHelpe
   }
 
   // Finally, handle the case where we have both a previous and a next event
 
   // First, handle the case where our range ends up in a ramp event
   switch (aNext->mType) {
   case AudioTimelineEvent::LinearRamp:
     return LinearInterpolate(TimeOf(aPrevious),
-                             aPrevious->mValue,
+                             ValueOf(aPrevious),
                              TimeOf(aNext),
-                             aNext->mValue, aTime);
+                             ValueOf(aNext), aTime);
 
   case AudioTimelineEvent::ExponentialRamp:
     return ExponentialInterpolate(TimeOf(aPrevious),
-                                  aPrevious->mValue,
+                                  ValueOf(aPrevious),
                                   TimeOf(aNext),
-                                  aNext->mValue, aTime);
+                                  ValueOf(aNext), aTime);
 
   case AudioTimelineEvent::SetValueAtTime:
   case AudioTimelineEvent::SetTarget:
   case AudioTimelineEvent::SetValueCurve:
     break;
   case AudioTimelineEvent::SetValue:
   case AudioTimelineEvent::Cancel:
   case AudioTimelineEvent::Stream:
@@ -293,17 +308,17 @@ AudioEventTimeline::GetValuesAtTimeHelpe
   switch (aPrevious->mType) {
   case AudioTimelineEvent::SetValueAtTime:
   case AudioTimelineEvent::LinearRamp:
   case AudioTimelineEvent::ExponentialRamp:
     // If the next event type is neither linear or exponential ramp, the
     // value is constant.
     return aPrevious->mValue;
   case AudioTimelineEvent::SetValueCurve:
-    return ExtractValueFromCurve(TimeOf(aPrevious),
+    return ExtractValueFromCurve(aPrevious->template Time<TimeType>(),
                                  aPrevious->mCurve, aPrevious->mCurveLength,
                                  aPrevious->mDuration, aTime);
   case AudioTimelineEvent::SetTarget:
     MOZ_FALLTHROUGH_ASSERT("AudioTimelineEvent::SetTarget");
   case AudioTimelineEvent::SetValue:
   case AudioTimelineEvent::Cancel:
   case AudioTimelineEvent::Stream:
     MOZ_ASSERT(false, "Should have been handled earlier.");