b=898291 skip HRTF panner processing when input has been null long enough for output to be null r=ehsan
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 25 Oct 2013 14:05:43 +1300
changeset 165865 578c80c21547cdaab10b80426246dca7e18d0b68
parent 165864 52abf1613764f10208513fcdbb8f4ad34e08a1fa
child 165866 d5fa4120ce92b63bfd589b54b57181c99d34fbd6
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs898291
milestone27.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
b=898291 skip HRTF panner processing when input has been null long enough for output to be null r=ehsan
content/media/webaudio/PannerNode.cpp
content/media/webaudio/blink/HRTFPanner.cpp
content/media/webaudio/blink/HRTFPanner.h
--- a/content/media/webaudio/PannerNode.cpp
+++ b/content/media/webaudio/PannerNode.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PannerNode.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "AudioListener.h"
 #include "AudioBufferSourceNode.h"
+#include "PlayingRefChangeHandler.h"
 #include "blink/HRTFPanner.h"
 #include "blink/HRTFDatabaseLoader.h"
 
 using WebCore::HRTFDatabaseLoader;
 using WebCore::HRTFPanner;
 
 namespace mozilla {
 namespace dom {
@@ -53,16 +54,17 @@ public:
     , mRolloffFactor(1.)
     , mConeInnerAngle(360.)
     , mConeOuterAngle(360.)
     , mConeOuterGain(0.)
     // These will be initialized when a PannerNode is created, so just initialize them
     // to some dummy values here.
     , mListenerDopplerFactor(0.)
     , mListenerSpeedOfSound(0.)
+    , mLeftOverData(INT_MIN)
   {
     // HRTFDatabaseLoader needs to be fetched on the main thread.
     TemporaryRef<HRTFDatabaseLoader> loader =
       HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(aNode->Context()->SampleRate());
     mHRTFPanner = new HRTFPanner(aNode->Context()->SampleRate(), loader);
   }
 
   virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam) MOZ_OVERRIDE
@@ -131,16 +133,45 @@ public:
     }
   }
 
   virtual void ProduceAudioBlock(AudioNodeStream* aStream,
                                  const AudioChunk& aInput,
                                  AudioChunk* aOutput,
                                  bool *aFinished) MOZ_OVERRIDE
   {
+    if (aInput.IsNull()) {
+      // mLeftOverData != INT_MIN means that the panning model was HRTF and a
+      // tail-time reference was added.  Even if the model is now equalpower,
+      // the reference will need to be removed.
+      if (mLeftOverData > 0) {
+        mLeftOverData -= WEBAUDIO_BLOCK_SIZE;
+      } else {
+        if (mLeftOverData != INT_MIN) {
+          mLeftOverData = INT_MIN;
+          mHRTFPanner->reset();
+
+          nsRefPtr<PlayingRefChangeHandler> refchanged =
+            new PlayingRefChangeHandler(aStream, PlayingRefChangeHandler::RELEASE);
+          aStream->Graph()->
+            DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
+        }
+        *aOutput = aInput;
+        return;
+      }
+    } else if (mPanningModelFunction == &PannerNodeEngine::HRTFPanningFunction) {
+      if (mLeftOverData == INT_MIN) {
+        nsRefPtr<PlayingRefChangeHandler> refchanged =
+          new PlayingRefChangeHandler(aStream, PlayingRefChangeHandler::ADDREF);
+        aStream->Graph()->
+          DispatchToMainThreadAfterStreamStateUpdate(refchanged.forget());
+      }
+      mLeftOverData = mHRTFPanner->maxTailFrames();
+    }
+
     (this->*mPanningModelFunction)(aInput, aOutput);
   }
 
   void ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation);
   void DistanceAndConeGain(AudioChunk* aChunk, float aGain);
   float ComputeConeGain();
   // Compute how much the distance contributes to the gain reduction.
   float ComputeDistanceGain();
@@ -172,16 +203,17 @@ public:
   double mConeOuterAngle;
   double mConeOuterGain;
   ThreeDPoint mListenerPosition;
   ThreeDPoint mListenerFrontVector;
   ThreeDPoint mListenerRightVector;
   ThreeDPoint mListenerVelocity;
   double mListenerDopplerFactor;
   double mListenerSpeedOfSound;
+  int mLeftOverData;
 };
 
 PannerNode::PannerNode(AudioContext* aContext)
   : AudioNode(aContext,
               2,
               ChannelCountMode::Clamped_max,
               ChannelInterpretation::Speakers)
   // Please keep these default values consistent with PannerNodeEngine::PannerNodeEngine above.
@@ -272,21 +304,16 @@ PannerNodeEngine::HRTFPanningFunction(co
 
   mHRTFPanner->pan(azimuth, elevation, &input, aOutput, WEBAUDIO_BLOCK_SIZE);
 }
 
 void
 PannerNodeEngine::EqualPowerPanningFunction(const AudioChunk& aInput,
                                             AudioChunk* aOutput)
 {
-  if (aInput.IsNull()) {
-    *aOutput = aInput;
-    return;
-  }
-
   float azimuth, elevation, gainL, gainR, normalizedAzimuth, distanceGain, coneGain;
   int inputChannels = aInput.mChannelData.Length();
 
   // If both the listener are in the same spot, and no cone gain is specified,
   // this node is noop.
   if (mListenerPosition == mPosition &&
       mConeInnerAngle == 360 &&
       mConeOuterAngle == 360) {
--- a/content/media/webaudio/blink/HRTFPanner.cpp
+++ b/content/media/webaudio/blink/HRTFPanner.cpp
@@ -285,24 +285,21 @@ void HRTFPanner::pan(double desiredAzimu
                 m_crossfadeSelection = CrossfadeSelection1;
                 m_crossfadeX = 0;
                 m_crossfadeIncr = 0;
             }
         }
     }
 }
 
-double HRTFPanner::tailTime() const
+int HRTFPanner::maxTailFrames() const
 {
-    // Because HRTFPanner is implemented with a DelayKernel and a FFTConvolver, the tailTime of the HRTFPanner
-    // is the sum of the tailTime of the DelayKernel and the tailTime of the FFTConvolver, which is MaxDelayTimeSeconds
-    // and fftSize() / 2, respectively.
-    return MaxDelayTimeSeconds + (fftSize() / 2) / static_cast<double>(sampleRate());
-}
-
-double HRTFPanner::latencyTime() const
-{
-    // The latency of a FFTConvolver is also fftSize() / 2, and is in addition to its tailTime of the
-    // same value.
-    return (fftSize() / 2) / static_cast<double>(sampleRate());
+    // Although the ideal tail time would be the length of the impulse
+    // response, there is additional tail time from the approximations in the
+    // implementation.  Because HRTFPanner is implemented with a DelayKernel
+    // and a FFTConvolver, the tailTime of the HRTFPanner is the sum of the
+    // tailTime of the DelayKernel and the tailTime of the FFTConvolver.
+    // The FFTConvolver has a tail time of fftSize(), including latency of
+    // fftSize()/2.
+    return m_delayLineL.MaxDelayFrames() + fftSize();
 }
 
 } // namespace WebCore
--- a/content/media/webaudio/blink/HRTFPanner.h
+++ b/content/media/webaudio/blink/HRTFPanner.h
@@ -46,18 +46,17 @@ public:
     // framesToProcess must be a power of 2 and greater than 128
     void pan(double azimuth, double elevation, const AudioChunk* inputBus, AudioChunk* outputBus, mozilla::TrackTicks framesToProcess);
     void reset();
 
     size_t fftSize() const { return m_convolverL1.fftSize(); }
 
     float sampleRate() const { return m_sampleRate; }
 
-    double tailTime() const;
-    double latencyTime() const;
+    int maxTailFrames() const;
 
 private:
     // Given an azimuth angle in the range -180 -> +180, returns the corresponding azimuth index for the database,
     // and azimuthBlend which is an interpolation value from 0 -> 1.
     int calculateDesiredAzimuthIndexAndBlend(double azimuth, double& azimuthBlend);
 
     mozilla::RefPtr<HRTFDatabaseLoader> m_databaseLoader;