Bug 1157635 - Use DenormalDisabler.h to automatically flush subnormals; r=karlt
authorDan Minor <dminor@mozilla.com>
Fri, 05 Aug 2016 15:33:08 -0400
changeset 324861 e50bc53ae80c28ccdc96316fc7602a60c7bb21b1
parent 324860 3a542aaed86b9769901bf1262a9be833077a803a
child 324862 cd56360c0615c3484faf23257c5a5b8aba1fc110
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewerskarlt
bugs1157635
milestone53.0a1
Bug 1157635 - Use DenormalDisabler.h to automatically flush subnormals; r=karlt This adds a DenormalDisabler instance at the beginning of each MediaStreamGraph iteration. On supported platforms, this will cause subnormal numbers to be flushed automatically. MozReview-Commit-ID: JGtunsqSirR
dom/media/MediaStreamGraph.cpp
dom/media/webaudio/blink/Biquad.cpp
dom/media/webaudio/blink/DenormalDisabler.h
dom/media/webaudio/blink/IIRFilter.cpp
dom/media/webaudio/blink/ZeroPole.cpp
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -31,16 +31,17 @@
 #include "VideoFrameContainer.h"
 #include "mozilla/Unused.h"
 #include "mozilla/media/MediaUtils.h"
 #ifdef MOZ_WEBRTC
 #include "AudioOutputObserver.h"
 #endif
 #include "mtransport/runnable_utils.h"
 
+#include "webaudio/blink/DenormalDisabler.h"
 #include "webaudio/blink/HRTFDatabaseLoader.h"
 
 using namespace mozilla::layers;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::media;
 
 namespace mozilla {
@@ -1395,16 +1396,18 @@ MediaStreamGraphImpl::UpdateMainThreadSt
 
   SwapMessageQueues();
   return true;
 }
 
 bool
 MediaStreamGraphImpl::OneIteration(GraphTime aStateEnd)
 {
+  WebCore::DenormalDisabler disabler;
+
   // Process graph message from the main thread for this iteration.
   RunMessagesInQueue();
 
   UpdateStreamOrder();
 
   bool switchingFromSystemClockDriver = false;
   {
     MonitorAutoLock mon(mMonitor);
--- a/dom/media/webaudio/blink/Biquad.cpp
+++ b/dom/media/webaudio/blink/Biquad.cpp
@@ -23,16 +23,18 @@
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "Biquad.h"
 
+#include "DenormalDisabler.h"
+
 #include <float.h>
 #include <algorithm>
 #include <math.h>
 
 namespace WebCore {
 
 Biquad::Biquad()
 {
@@ -71,25 +73,26 @@ void Biquad::process(const float* source
         x2 = x1;
         x1 = x;
         y2 = y1;
         y1 = y;
     }
 
     // Avoid introducing a stream of subnormals when input is silent and the
     // tail approaches zero.
-    // TODO: Remove this code when Bug 1157635 is fixed.
     if (x1 == 0.0 && x2 == 0.0 && (y1 != 0.0 || y2 != 0.0) &&
         fabs(y1) < FLT_MIN && fabs(y2) < FLT_MIN) {
       // Flush future values to zero (until there is new input).
       y1 = y2 = 0.0;
       // Flush calculated values.
+      #ifndef HAVE_DENORMAL
       for (int i = framesToProcess; i-- && fabsf(destP[i]) < FLT_MIN; ) {
         destP[i] = 0.0f;
       }
+      #endif
     }
     // Local variables back to member.
     m_x1 = x1;
     m_x2 = x2;
     m_y1 = y1;
     m_y2 = y2;
 }
 
--- a/dom/media/webaudio/blink/DenormalDisabler.h
+++ b/dom/media/webaudio/blink/DenormalDisabler.h
@@ -160,11 +160,9 @@ public:
     {
         return (fabs(f) < FLT_MIN) ? 0.0f : f;
     }
 };
 
 #endif
 
 } // namespace WebCore
-
-#undef HAVE_DENORMAL
 #endif // DenormalDisabler_h
--- a/dom/media/webaudio/blink/IIRFilter.cpp
+++ b/dom/media/webaudio/blink/IIRFilter.cpp
@@ -1,14 +1,18 @@
 // Copyright 2016 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "IIRFilter.h"
 
+#include "DenormalDisabler.h"
+
+#include <mozilla/Assertions.h>
+
 #include <complex>
 
 namespace blink {
 
 // The length of the memory buffers for the IIR filter.  This MUST be a power of two and must be
 // greater than the possible length of the filter coefficients.
 const int kBufferLength = 32;
 static_assert(kBufferLength >= IIRFilter::kMaxOrder + 1,
@@ -94,22 +98,18 @@ void IIRFilter::process(const float* sou
 
         // Save the current input and output values in the memory buffers for the next output.
         m_xBuffer[m_bufferIndex] = sourceP[n];
         m_yBuffer[m_bufferIndex] = yn;
 
         m_bufferIndex = (m_bufferIndex + 1) & (kBufferLength - 1);
 
         // Avoid introducing a stream of subnormals
-        // TODO: Remove this code when Bug 1157635 is fixed.
-        if (fabs(yn) >= FLT_MIN) {
-            destP[n] = yn;
-        } else {
-            destP[n] = 0.0;
-        }
+        destP[n] = WebCore::DenormalDisabler::flushDenormalFloatToZero(yn);
+        MOZ_ASSERT(destP[n] == 0.0 || fabs(destP[n]) > FLT_MIN, "output should not be subnormal");
     }
 }
 
 void IIRFilter::getFrequencyResponse(int nFrequencies, const float* frequency, float* magResponse, float* phaseResponse)
 {
     // Evaluate the z-transform of the filter at the given normalized frequencies from 0 to 1. (One
     // corresponds to the Nyquist frequency.)
     //
--- a/dom/media/webaudio/blink/ZeroPole.cpp
+++ b/dom/media/webaudio/blink/ZeroPole.cpp
@@ -23,16 +23,18 @@
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "ZeroPole.h"
 
+#include "DenormalDisabler.h"
+
 #include <cmath>
 #include <float.h>
 
 namespace WebCore {
 
 void ZeroPole::process(const float *source, float *destination, int framesToProcess)
 {
     float zero = m_zero;
@@ -57,22 +59,25 @@ void ZeroPole::process(const float *sour
         float output2 = k2 * output1 + pole * lastY;
         lastY = output2;
 
         destination[i] = output2;
     }
     
     // Locals to member variables. Flush denormals here so we don't
     // slow down the inner loop above.
+    #ifndef HAVE_DENORMAL
     if (lastX == 0.0f && lastY != 0.0f && fabsf(lastY) < FLT_MIN) {
         // Flush future values to zero (until there is new input).
         lastY = 0.0;
+
         // Flush calculated values.
         for (int i = framesToProcess; i-- && fabsf(destination[i]) < FLT_MIN; ) {
             destination[i] = 0.0f;
         }
     }
+    #endif
 
     m_lastX = lastX;
     m_lastY = lastY;
 }
 
 } // namespace WebCore