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 265581 3b2aa51abf0811692611f4c9eb7617bafe506fbb
parent 265580 705689bc6b9213eaf2756d0ecfa015d3550afacb
child 265582 bc20a0abec612f7cdb6ce52b6393f7d4232c32f8
push id29465
push usercbook@mozilla.com
push dateFri, 02 Oct 2015 09:56:33 +0000
treeherdermozilla-central@5f16c6c2b969 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1209904
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 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;