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
--- 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