Bug 1265408 - Use IIRFilter from blink; r=padenot
authorDan Minor <dminor@mozilla.com>
Tue, 10 May 2016 10:46:40 -0400
changeset 300884 08ed713fd7bfcf41603d6c7018e062537ab945a3
parent 300883 679f42969fede3669ff2bce80c08ba78d0f42a66
child 300885 d73d8db7877480fa1cec3ffa0b24243781ef9573
push id78119
push userdminor@mozilla.com
push dateTue, 07 Jun 2016 16:03:45 +0000
treeherdermozilla-inbound@021ffc7c02e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1265408
milestone50.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 1265408 - Use IIRFilter from blink; r=padenot MozReview-Commit-ID: 5QUGMFcZ6ZI
dom/media/webaudio/blink/IIRFilter.cpp
dom/media/webaudio/blink/IIRFilter.h
dom/media/webaudio/blink/moz.build
--- a/dom/media/webaudio/blink/IIRFilter.cpp
+++ b/dom/media/webaudio/blink/IIRFilter.cpp
@@ -1,43 +1,42 @@
 // 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 "platform/audio/IIRFilter.h"
+#include "IIRFilter.h"
 
-#include "wtf/MathExtras.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,
     "Internal IIR buffer length must be greater than maximum IIR Filter order.");
 
-IIRFilter::IIRFilter(const AudioDoubleArray* feedforward, const AudioDoubleArray* feedback)
+IIRFilter::IIRFilter(const AudioDoubleArray* feedforwardCoef, const AudioDoubleArray* feedbackCoef)
     : m_bufferIndex(0)
-    , m_feedback(feedback)
-    , m_feedforward(feedforward)
+    , m_feedback(feedbackCoef)
+    , m_feedforward(feedforwardCoef)
 {
-    // These are guaranteed to be zero-initialized.
-    m_xBuffer.allocate(kBufferLength);
-    m_yBuffer.allocate(kBufferLength);
+    m_xBuffer.SetLength(kBufferLength);
+    m_yBuffer.SetLength(kBufferLength);
+    reset();
 }
 
 IIRFilter::~IIRFilter()
 {
 }
 
 void IIRFilter::reset()
 {
-    m_xBuffer.zero();
-    m_yBuffer.zero();
+    memset(m_xBuffer.Elements(), 0, m_xBuffer.Length() * sizeof(double));
+    memset(m_yBuffer.Elements(), 0, m_yBuffer.Length() * sizeof(double));
 }
 
 static std::complex<double> evaluatePolynomial(const double* coef, std::complex<double> z, int order)
 {
     // Use Horner's method to evaluate the polynomial P(z) = sum(coef[k]*z^k, k, 0, order);
     std::complex<double> result = 0;
 
     for (int k = order; k >= 0; --k)
@@ -52,32 +51,32 @@ void IIRFilter::process(const float* sou
     //
     //   y[n] = sum(b[k] * x[n - k], k = 0, M) - sum(a[k] * y[n - k], k = 1, N)
     //
     // where b[k] are the feedforward coefficients and a[k] are the feedback coefficients of the
     // filter.
 
     // This is a Direct Form I implementation of an IIR Filter.  Should we consider doing a
     // different implementation such as Transposed Direct Form II?
-    const double* feedback = m_feedback->data();
-    const double* feedforward = m_feedforward->data();
+    const double* feedback = m_feedback->Elements();
+    const double* feedforward = m_feedforward->Elements();
 
-    ASSERT(feedback);
-    ASSERT(feedforward);
+    MOZ_ASSERT(feedback);
+    MOZ_ASSERT(feedforward);
 
     // Sanity check to see if the feedback coefficients have been scaled appropriately. It must
     // be EXACTLY 1!
-    ASSERT(feedback[0] == 1);
+    MOZ_ASSERT(feedback[0] == 1);
 
-    int feedbackLength = m_feedback->size();
-    int feedforwardLength = m_feedforward->size();
+    int feedbackLength = m_feedback->Length();
+    int feedforwardLength = m_feedforward->Length();
     int minLength = std::min(feedbackLength, feedforwardLength);
 
-    double* xBuffer = m_xBuffer.data();
-    double* yBuffer = m_yBuffer.data();
+    double* xBuffer = m_xBuffer.Elements();
+    double* yBuffer = m_yBuffer.Elements();
 
     for (size_t n = 0; n < framesToProcess; ++n) {
         // To help minimize roundoff, we compute using double's, even though the filter coefficients
         // only have single precision values.
         double yn = feedforward[0] * sourceP[n];
 
         // Run both the feedforward and feedback terms together, when possible.
         for (int k = 1; k < minLength; ++k) {
@@ -114,20 +113,20 @@ void IIRFilter::getFrequencyResponse(int
     //
     // The desired frequency response is H(exp(j*omega)), where omega is in [0, 1).
     //
     // Let P(x) = sum(c[k]*x^k, k, 0, P) be a polynomial of order P.  Then each of the sums in H(z)
     // is equivalent to evaluating a polynomial at the point 1/z.
 
     for (int k = 0; k < nFrequencies; ++k) {
         // zRecip = 1/z = exp(-j*frequency)
-        double omega = -piDouble * frequency[k];
+        double omega = -M_PI * frequency[k];
         std::complex<double> zRecip = std::complex<double>(cos(omega), sin(omega));
 
-        std::complex<double> numerator = evaluatePolynomial(m_feedforward->data(), zRecip, m_feedforward->size() - 1);
-        std::complex<double> denominator = evaluatePolynomial(m_feedback->data(), zRecip, m_feedback->size() - 1);
+        std::complex<double> numerator = evaluatePolynomial(m_feedforward->Elements(), zRecip, m_feedforward->Length() - 1);
+        std::complex<double> denominator = evaluatePolynomial(m_feedback->Elements(), zRecip, m_feedback->Length() - 1);
         std::complex<double> response = numerator / denominator;
         magResponse[k] = static_cast<float>(abs(response));
         phaseResponse[k] = static_cast<float>(atan2(imag(response), real(response)));
     }
 }
 
 } // namespace blink
--- a/dom/media/webaudio/blink/IIRFilter.h
+++ b/dom/media/webaudio/blink/IIRFilter.h
@@ -1,22 +1,20 @@
 // 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.
 
 #ifndef IIRFilter_h
 #define IIRFilter_h
 
-#include "platform/PlatformExport.h"
-#include "platform/audio/AudioArray.h"
-#include "wtf/Vector.h"
+typedef nsTArray<double> AudioDoubleArray;
 
 namespace blink {
 
-class PLATFORM_EXPORT IIRFilter final {
+class IIRFilter final {
 public:
     // The maximum IIR filter order.  This also limits the number of feedforward coefficients.  The
     // maximum number of coefficients is 20 according to the spec.
     const static size_t kMaxOrder = 19;
     IIRFilter(const AudioDoubleArray* feedforwardCoef, const AudioDoubleArray* feedbackCoef);
     ~IIRFilter();
 
     void process(const float* sourceP, float* destP, size_t framesToProcess);
@@ -43,17 +41,16 @@ private:
     AudioDoubleArray m_xBuffer;
     AudioDoubleArray m_yBuffer;
 
     // Index into the xBuffer and yBuffer arrays where the most current x and y values should be
     // stored.  xBuffer[bufferIndex] corresponds to x[n], the current x input value and
     // yBuffer[bufferIndex] is where y[n], the current output value.
     int m_bufferIndex;
 
-    // Coefficients of the IIR filter.  To minimize storage, these point to the arrays given in the
-    // constructor.
+    // Coefficients of the IIR filter.
     const AudioDoubleArray* m_feedback;
     const AudioDoubleArray* m_feedforward;
 };
 
 } // namespace blink
 
 #endif // IIRFilter_h
--- a/dom/media/webaudio/blink/moz.build
+++ b/dom/media/webaudio/blink/moz.build
@@ -9,16 +9,17 @@ UNIFIED_SOURCES += [
     'DynamicsCompressor.cpp',
     'DynamicsCompressorKernel.cpp',
     'FFTConvolver.cpp',
     'HRTFDatabase.cpp',
     'HRTFDatabaseLoader.cpp',
     'HRTFElevation.cpp',
     'HRTFKernel.cpp',
     'HRTFPanner.cpp',
+    'IIRFilter.cpp',
     'PeriodicWave.cpp',
     'Reverb.cpp',
     'ReverbAccumulationBuffer.cpp',
     'ReverbConvolver.cpp',
     'ReverbConvolverStage.cpp',
     'ReverbInputBuffer.cpp',
     'ZeroPole.cpp',
 ]