Bug 1265403 - Support chaining AudioParam automation methods. r?smaug draft
authorPaul Adenot <paul@paul.cx>
Mon, 18 Apr 2016 17:49:35 +0200
changeset 352738 7a75c4267acace26e2e5a357940938a6f05d2d89
parent 352734 87fc481e7f861b68fc3b20941d0801e1de16cd3f
child 518719 3505781df7531c9ca2b5c9d467f87a6abe461e6c
push id15770
push userpaul@paul.cx
push dateMon, 18 Apr 2016 15:49:42 +0000
reviewerssmaug
bugs1265403
milestone48.0a1
Bug 1265403 - Support chaining AudioParam automation methods. r?smaug MozReview-Commit-ID: 7Jh5eWtfU4t
dom/media/webaudio/AudioParam.h
dom/media/webaudio/test/mochitest.ini
dom/media/webaudio/test/test_audioParamChaining.html
dom/webidl/AudioParam.webidl
--- a/dom/media/webaudio/AudioParam.h
+++ b/dom/media/webaudio/AudioParam.h
@@ -39,27 +39,31 @@ public:
   {
     return mNode->Context();
   }
 
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // We override SetValueCurveAtTime to convert the Float32Array to the wrapper
   // object.
-  void SetValueCurveAtTime(const Float32Array& aValues, double aStartTime, double aDuration, ErrorResult& aRv)
+  AudioParam* SetValueCurveAtTime(const Float32Array& aValues,
+                                  double aStartTime,
+                                  double aDuration,
+                                  ErrorResult& aRv)
   {
     if (!WebAudioUtils::IsTimeValid(aStartTime)) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-      return;
+      return this;
     }
     aValues.ComputeLengthAndData();
 
     EventInsertionHelper(aRv, AudioTimelineEvent::SetValueCurve,
                          aStartTime, 0.0f, 0.0f, aDuration, aValues.Data(),
                          aValues.Length());
+    return this;
   }
 
   void SetValue(float aValue)
   {
     AudioTimelineEvent event(AudioTimelineEvent::SetValue, 0.0f, aValue);
 
     ErrorResult rv;
     if (!ValidateEvent(event, rv)) {
@@ -68,71 +72,81 @@ public:
       return;
     }
 
     AudioParamTimeline::SetValue(aValue);
 
     SendEventToEngine(event);
   }
 
-  void SetValueAtTime(float aValue, double aStartTime, ErrorResult& aRv)
+  AudioParam* SetValueAtTime(float aValue, double aStartTime, ErrorResult& aRv)
   {
     if (!WebAudioUtils::IsTimeValid(aStartTime)) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-      return;
+      return this;
     }
     EventInsertionHelper(aRv, AudioTimelineEvent::SetValueAtTime,
                          aStartTime, aValue);
+
+    return this;
   }
 
-  void LinearRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
+  AudioParam* LinearRampToValueAtTime(float aValue, double aEndTime,
+                                      ErrorResult& aRv)
   {
     if (!WebAudioUtils::IsTimeValid(aEndTime)) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-      return;
+      return this;
     }
     EventInsertionHelper(aRv, AudioTimelineEvent::LinearRamp, aEndTime, aValue);
+    return this;
   }
 
-  void ExponentialRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
+  AudioParam* ExponentialRampToValueAtTime(float aValue, double aEndTime,
+                                           ErrorResult& aRv)
   {
     if (!WebAudioUtils::IsTimeValid(aEndTime)) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-      return;
+      return this;
     }
     EventInsertionHelper(aRv, AudioTimelineEvent::ExponentialRamp,
                          aEndTime, aValue);
+    return this;
   }
 
-  void SetTargetAtTime(float aTarget, double aStartTime,
-                       double aTimeConstant, ErrorResult& aRv)
+  AudioParam* SetTargetAtTime(float aTarget, double aStartTime,
+                              double aTimeConstant, ErrorResult& aRv)
   {
     if (!WebAudioUtils::IsTimeValid(aStartTime) ||
         !WebAudioUtils::IsTimeValid(aTimeConstant)) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-      return;
+      return this;
     }
     EventInsertionHelper(aRv, AudioTimelineEvent::SetTarget,
                          aStartTime, aTarget,
                          aTimeConstant);
+
+    return this;
   }
 
-  void CancelScheduledValues(double aStartTime, ErrorResult& aRv)
+  AudioParam* CancelScheduledValues(double aStartTime, ErrorResult& aRv)
   {
     if (!WebAudioUtils::IsTimeValid(aStartTime)) {
       aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-      return;
+      return this;
     }
 
     // Remove some events on the main thread copy.
     AudioEventTimeline::CancelScheduledValues(aStartTime);
 
     AudioTimelineEvent event(AudioTimelineEvent::Cancel, aStartTime, 0.0f);
 
     SendEventToEngine(event);
+
+    return this;
   }
 
   uint32_t ParentNodeId()
   {
     return mNode->Id();
   }
 
   void GetName(nsAString& aName)
--- a/dom/media/webaudio/test/mochitest.ini
+++ b/dom/media/webaudio/test/mochitest.ini
@@ -50,16 +50,17 @@ skip-if = (toolkit == 'gonk') || (toolki
 [test_audioBufferSourceNodeRate.html]
 [test_AudioContext.html]
 [test_audioContextSuspendResumeClose.html]
 skip-if = buildapp == 'mulet'
 tags=capturestream
 [test_audioDestinationNode.html]
 [test_AudioListener.html]
 [test_AudioNodeDevtoolsAPI.html]
+[test_audioParamChaining.html]
 [test_AudioParamDevtoolsAPI.html]
 [test_audioParamExponentialRamp.html]
 [test_audioParamGain.html]
 [test_audioParamLinearRamp.html]
 [test_audioParamSetCurveAtTime.html]
 [test_audioParamSetCurveAtTimeTwice.html]
 [test_audioParamSetCurveAtTimeZeroDuration.html]
 [test_audioParamSetTargetAtTime.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/webaudio/test/test_audioParamChaining.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test whether we can create an AudioContext interface</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish()
+
+function frameToTime(frame, rate)
+{
+  return frame / rate;
+}
+
+const RATE = 44100;
+
+var oc = new OfflineAudioContext(1, 44100, RATE);
+// This allows us to have a source that is simply a DC offset.
+var source = oc.createBufferSource();
+var buf = oc.createBuffer(1, 1, RATE);
+buf.getChannelData(0)[0] = 1;
+source.loop = true;
+source.buffer = buf;
+
+source.start(0);
+
+var gain = oc.createGain();
+
+source.connect(gain).connect(oc.destination);
+
+// We chain three uutomation methods, making a gain step.
+var rv = gain.gain.setValueAtTime(0, frameToTime(0, RATE))
+                  .setValueAtTime(0.5, frameToTime(22000, RATE))
+                  .setValueAtTime(1, frameToTime(44000, RATE));
+
+ok(rv instanceof AudioParam);
+ok(rv == gain.gain);
+
+oc.startRendering().then(function(rendered) {
+    console.log(rendered.getChannelData(0));
+    ok(rendered.getChannelData(0)[0] == 0);
+    ok(rendered.getChannelData(0)[22050] == 0.5);
+    ok(rendered.getChannelData(0)[44099] == 1);
+    SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/webidl/AudioParam.webidl
+++ b/dom/webidl/AudioParam.webidl
@@ -12,34 +12,34 @@
 
 interface AudioParam {
 
     attribute float value;
     readonly attribute float defaultValue;
 
     // Parameter automation. 
     [Throws]
-    void setValueAtTime(float value, double startTime);
+    AudioParam setValueAtTime(float value, double startTime);
     [Throws]
-    void linearRampToValueAtTime(float value, double endTime);
+    AudioParam linearRampToValueAtTime(float value, double endTime);
     [Throws]
-    void exponentialRampToValueAtTime(float value, double endTime);
+    AudioParam exponentialRampToValueAtTime(float value, double endTime);
 
     // Exponentially approach the target value with a rate having the given time constant. 
     [Throws]
-    void setTargetAtTime(float target, double startTime, double timeConstant);
+    AudioParam setTargetAtTime(float target, double startTime, double timeConstant);
 
     // Sets an array of arbitrary parameter values starting at time for the given duration. 
     // The number of values will be scaled to fit into the desired duration. 
     [Throws]
-    void setValueCurveAtTime(Float32Array values, double startTime, double duration);
+    AudioParam setValueCurveAtTime(Float32Array values, double startTime, double duration);
 
     // Cancels all scheduled parameter changes with times greater than or equal to startTime. 
     [Throws]
-    void cancelScheduledValues(double startTime);
+    AudioParam cancelScheduledValues(double startTime);
 
 };
 
 // Mozilla extension
 partial interface AudioParam {
   // The ID of the AudioNode this AudioParam belongs to.
   [ChromeOnly]
   readonly attribute unsigned long parentNodeId;