Bug 1209904 - Optimize OscillatorNode when its frequency is not changin and it's using ::ComputeCustom. r=karlt
authorPaul Adenot <paul@paul.cx>
Thu, 01 Oct 2015 10:52:28 +0200
changeset 265584 3b2aa51abf0811692611f4c9eb7617bafe506fbb
parent 265583 705689bc6b9213eaf2756d0ecfa015d3550afacb
child 265585 bc20a0abec612f7cdb6ce52b6393f7d4232c32f8
push id15472
push usercbook@mozilla.com
push dateFri, 02 Oct 2015 11:51:34 +0000
treeherderfx-team@2c33ef6b27e0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1209904
milestone44.0a1
Bug 1209904 - Optimize OscillatorNode when its frequency is not changin and it's using ::ComputeCustom. r=karlt
dom/media/webaudio/OscillatorNode.cpp
--- a/dom/media/webaudio/OscillatorNode.cpp
+++ b/dom/media/webaudio/OscillatorNode.cpp
@@ -147,45 +147,53 @@ public:
     mPhase += mPhaseIncrement;
     if (mPhase > twoPiFloat) {
       mPhase -= twoPiFloat;
     } else if (mPhase < -twoPiFloat) {
       mPhase += twoPiFloat;
     }
   }
 
-  void UpdateParametersIfNeeded(StreamTime ticks, size_t count)
+  // Returns true if the final frequency (and thus the phase increment) changed,
+  // false otherwise. This allow some optimizations at callsite.
+  bool UpdateParametersIfNeeded(StreamTime ticks, size_t count)
   {
     double frequency, detune;
 
     // Shortcut if frequency-related AudioParam are not automated, and we
     // already have computed the frequency information and related parameters.
     if (!ParametersMayNeedUpdate()) {
-      return;
+      return false;
     }
 
     bool simpleFrequency = mFrequency.HasSimpleValue();
     bool simpleDetune = mDetune.HasSimpleValue();
 
     if (simpleFrequency) {
       frequency = mFrequency.GetValue();
     } else {
       frequency = mFrequency.GetValueAtTime(ticks, count);
     }
     if (simpleDetune) {
       detune = mDetune.GetValue();
     } else {
       detune = mDetune.GetValueAtTime(ticks, count);
     }
 
-    mFinalFrequency = frequency * pow(2., detune / 1200.);
-    float signalPeriod = mSource->SampleRate() / mFinalFrequency;
+    float finalFrequency = frequency * pow(2., detune / 1200.);
+    float signalPeriod = mSource->SampleRate() / finalFrequency;
     mRecomputeParameters = false;
 
     mPhaseIncrement = 2 * M_PI / signalPeriod;
+
+    if (finalFrequency != mFinalFrequency) {
+      mFinalFrequency = finalFrequency;
+      return true;
+    }
+    return false;
   }
 
   void FillBounds(float* output, StreamTime ticks,
                   uint32_t& start, uint32_t& end)
   {
     MOZ_ASSERT(output);
     static_assert(StreamTime(WEBAUDIO_BLOCK_SIZE) < UINT_MAX,
         "WEBAUDIO_BLOCK_SIZE overflows interator bounds.");
@@ -203,16 +211,18 @@ public:
         output[i] = 0.0;
       }
     }
   }
 
   void ComputeSine(float * aOutput, StreamTime ticks, uint32_t aStart, uint32_t aEnd)
   {
     for (uint32_t i = aStart; i < aEnd; ++i) {
+      // We ignore the return value, changing the frequency has no impact on
+      // performances here.
       UpdateParametersIfNeeded(ticks, i);
 
       aOutput[i] = sin(mPhase);
 
       IncrementPhase();
     }
   }
 
@@ -237,31 +247,33 @@ public:
                "periodicWaveSize must be power of 2");
     float* higherWaveData = nullptr;
     float* lowerWaveData = nullptr;
     float tableInterpolationFactor;
     // Phase increment at frequency of 1 Hz.
     // mPhase runs [0,periodicWaveSize) here instead of [0,2*M_PI).
     float basePhaseIncrement = mPeriodicWave->rateScale();
 
-    UpdateParametersIfNeeded(ticks, aStart);
+    bool needToFetchWaveData = UpdateParametersIfNeeded(ticks, aStart);
 
     bool parametersMayNeedUpdate = ParametersMayNeedUpdate();
     mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency,
                                                    lowerWaveData,
                                                    higherWaveData,
                                                    tableInterpolationFactor);
 
     for (uint32_t i = aStart; i < aEnd; ++i) {
       if (parametersMayNeedUpdate) {
-        mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency,
-                                                       lowerWaveData,
-                                                       higherWaveData,
-                                                       tableInterpolationFactor);
-        UpdateParametersIfNeeded(ticks, i);
+        if (needToFetchWaveData) {
+          mPeriodicWave->waveDataForFundamentalFrequency(mFinalFrequency,
+                                                         lowerWaveData,
+                                                         higherWaveData,
+                                                         tableInterpolationFactor);
+        }
+        needToFetchWaveData = UpdateParametersIfNeeded(ticks, i);
       }
       // Bilinear interpolation between adjacent samples in each table.
       float floorPhase = floorf(mPhase);
       int j1Signed = static_cast<int>(floorPhase);
       uint32_t j1 = j1Signed & indexMask;
       uint32_t j2 = j1 + 1;
       j2 &= indexMask;