Bug 864091 - Part 2: Add the Blink Dynamics Compressor implementation to the build system; r=padenot,glandium
authorEhsan Akhgari <ehsan@mozilla.com>
Sat, 20 Apr 2013 23:12:00 -0400
changeset 140476 c2ead35253b026b9c80209362d801bc1a3c8da72
parent 140475 50ad07904584f2c62f551730bca68dacd1e1d7bc
child 140477 a2f43cd4a75393da9038da02333a53be3d0e41f3
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot, glandium
bugs864091
milestone23.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 864091 - Part 2: Add the Blink Dynamics Compressor implementation to the build system; r=padenot,glandium
content/media/webaudio/WebAudioUtils.h
content/media/webaudio/blink/DenormalDisabler.h
content/media/webaudio/blink/DynamicsCompressor.cpp
content/media/webaudio/blink/DynamicsCompressor.h
content/media/webaudio/blink/DynamicsCompressorKernel.cpp
content/media/webaudio/blink/DynamicsCompressorKernel.h
content/media/webaudio/blink/Makefile.in
content/media/webaudio/blink/ZeroPole.cpp
content/media/webaudio/blink/moz.build
content/media/webaudio/moz.build
layout/build/Makefile.in
--- a/content/media/webaudio/WebAudioUtils.h
+++ b/content/media/webaudio/WebAudioUtils.h
@@ -56,30 +56,43 @@ struct WebAudioUtils {
    * value is 0.
    */
   static float ConvertLinearToDecibels(float aLinearValue, float aMinDecibels)
   {
     return aLinearValue ? 20.0f * std::log10(aLinearValue) : aMinDecibels;
   }
 
   /**
+   * Converts a decibel value to a linear value.
+   */
+  static float ConvertDecibelsToLinear(float aDecibels)
+  {
+    return std::pow(10.0f, 0.05f * aDecibels);
+  }
+
+  /**
    * Converts a decibel to a linear value.
    */
   static float ConvertDecibelToLinear(float aDecibel)
   {
     return std::pow(10.0f, 0.05f * aDecibel);
   }
 
   static void FixNaN(double& aDouble)
   {
     if (MOZ_DOUBLE_IS_NaN(aDouble) || MOZ_DOUBLE_IS_INFINITE(aDouble)) {
       aDouble = 0.0;
     }
   }
 
+  static double DiscreteTimeConstantForSampleRate(double timeConstant, double sampleRate)
+  {
+    return 1.0 - std::exp(-1.0 / (sampleRate * timeConstant));
+  }
+
   /**
    * Convert a stream position into the time coordinate of the destination
    * stream.
    */
   static double StreamPositionToDestinationTime(TrackTicks aSourcePosition,
                                                 AudioNodeStream* aSource,
                                                 AudioNodeStream* aDestination);
 };
--- a/content/media/webaudio/blink/DenormalDisabler.h
+++ b/content/media/webaudio/blink/DenormalDisabler.h
@@ -20,64 +20,66 @@
  * 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.
  */
 
 #ifndef DenormalDisabler_h
 #define DenormalDisabler_h
 
-#include <wtf/MathExtras.h>
+#define _USE_MATH_DEFINES
+#include <cmath>
 
 namespace WebCore {
 
 // Deal with denormals. They can very seriously impact performance on x86.
 
 // Define HAVE_DENORMAL if we support flushing denormals to zero.
-#if OS(WINDOWS) && COMPILER(MSVC)
+#if defined(XP_WIN) && defined(_MSC_VER)
+#include <float.h>
 #define HAVE_DENORMAL
 #endif
 
 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 #define HAVE_DENORMAL
 #endif
 
 #ifdef HAVE_DENORMAL
 class DenormalDisabler {
 public:
     DenormalDisabler()
             : m_savedCSR(0)
     {
-#if OS(WINDOWS) && COMPILER(MSVC)
+#if defined(XP_WIN) && defined(_MSC_VER)
         // Save the current state, and set mode to flush denormals.
         //
         // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s-may-not-restore-control-word-correctly
         _controlfp_s(&m_savedCSR, 0, 0);
         unsigned int unused;
         _controlfp_s(&unused, _DN_FLUSH, _MCW_DN);
 #else
         m_savedCSR = getCSR();
         setCSR(m_savedCSR | 0x8040);
 #endif
     }
 
     ~DenormalDisabler()
     {
-#if OS(WINDOWS) && COMPILER(MSVC)
+#if defined(XP_WIN) && defined(_MSC_VER)
         unsigned int unused;
         _controlfp_s(&unused, m_savedCSR, _MCW_DN);
 #else
         setCSR(m_savedCSR);
 #endif
     }
 
     // This is a nop if we can flush denormals to zero in hardware.
     static inline float flushDenormalFloatToZero(float f)
     {
-#if OS(WINDOWS) && COMPILER(MSVC) && (!_M_IX86_FP)
+#if defined(XP_WIN) && defined(_MSC_VER) && _M_IX86_FP
         // For systems using x87 instead of sse, there's no hardware support
         // to flush denormals automatically. Hence, we need to flush
         // denormals to zero manually.
         return (fabs(f) < FLT_MIN) ? 0.0f : f;
 #else
         return f;
 #endif
     }
--- a/content/media/webaudio/blink/DynamicsCompressor.cpp
+++ b/content/media/webaudio/blink/DynamicsCompressor.cpp
@@ -21,47 +21,44 @@
  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * 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 "config.h"
-
-#if ENABLE(WEB_AUDIO)
+#include "DynamicsCompressor.h"
+#include "AudioSegment.h"
 
-#include "DynamicsCompressor.h"
+#include <cmath>
+#include "AudioNodeEngine.h"
+#include "nsDebug.h"
 
-#include "AudioBus.h"
-#include "AudioUtilities.h"
-#include <wtf/MathExtras.h>
+using mozilla::WEBAUDIO_BLOCK_SIZE;
 
 namespace WebCore {
 
-using namespace AudioUtilities;
-    
 DynamicsCompressor::DynamicsCompressor(float sampleRate, unsigned numberOfChannels)
     : m_numberOfChannels(numberOfChannels)
     , m_sampleRate(sampleRate)
     , m_compressor(sampleRate, numberOfChannels)
 {
     // Uninitialized state - for parameter recalculation.
     m_lastFilterStageRatio = -1;
     m_lastAnchor = -1;
     m_lastFilterStageGain = -1;
 
     setNumberOfChannels(numberOfChannels);
     initializeParameters();
 }
 
 void DynamicsCompressor::setParameterValue(unsigned parameterID, float value)
 {
-    ASSERT(parameterID < ParamLast);
+    MOZ_ASSERT(parameterID < ParamLast);
     if (parameterID < ParamLast)
         m_parameters[parameterID] = value;
 }
 
 void DynamicsCompressor::initializeParameters()
 {
     // Initializes compressor to default values.
     
@@ -86,29 +83,29 @@ void DynamicsCompressor::initializeParam
     m_parameters[ParamReduction] = 0; // dB
 
     // Linear crossfade (0 -> 1).
     m_parameters[ParamEffectBlend] = 1;
 }
 
 float DynamicsCompressor::parameterValue(unsigned parameterID)
 {
-    ASSERT(parameterID < ParamLast);
+    MOZ_ASSERT(parameterID < ParamLast);
     return m_parameters[parameterID];
 }
 
 void DynamicsCompressor::setEmphasisStageParameters(unsigned stageIndex, float gain, float normalizedFrequency /* 0 -> 1 */)
 {
     float gk = 1 - gain / 20;
     float f1 = normalizedFrequency * gk;
     float f2 = normalizedFrequency / gk;
-    float r1 = expf(-f1 * piFloat);
-    float r2 = expf(-f2 * piFloat);
+    float r1 = expf(-f1 * M_PI);
+    float r2 = expf(-f2 * M_PI);
 
-    ASSERT(m_numberOfChannels == m_preFilterPacks.size());
+    MOZ_ASSERT(m_numberOfChannels == m_preFilterPacks.Length());
 
     for (unsigned i = 0; i < m_numberOfChannels; ++i) {
         // Set pre-filter zero and pole to create an emphasis filter.
         ZeroPole& preFilter = m_preFilterPacks[i]->filters[stageIndex];
         preFilter.setZero(r1);
         preFilter.setPole(r2);
 
         // Set post-filter with zero and pole reversed to create the de-emphasis filter.
@@ -122,52 +119,53 @@ void DynamicsCompressor::setEmphasisStag
 void DynamicsCompressor::setEmphasisParameters(float gain, float anchorFreq, float filterStageRatio)
 {
     setEmphasisStageParameters(0, gain, anchorFreq);
     setEmphasisStageParameters(1, gain, anchorFreq / filterStageRatio);
     setEmphasisStageParameters(2, gain, anchorFreq / (filterStageRatio * filterStageRatio));
     setEmphasisStageParameters(3, gain, anchorFreq / (filterStageRatio * filterStageRatio * filterStageRatio));
 }
 
-void DynamicsCompressor::process(const AudioBus* sourceBus, AudioBus* destinationBus, unsigned framesToProcess)
+void DynamicsCompressor::process(const AudioChunk* sourceChunk, AudioChunk* destinationChunk, unsigned framesToProcess)
 {
     // Though numberOfChannels is retrived from destinationBus, we still name it numberOfChannels instead of numberOfDestinationChannels.
     // It's because we internally match sourceChannels's size to destinationBus by channel up/down mix. Thus we need numberOfChannels
     // to do the loop work for both m_sourceChannels and m_destinationChannels.
 
-    unsigned numberOfChannels = destinationBus->numberOfChannels();
-    unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
+    unsigned numberOfChannels = destinationChunk->mChannelData.Length();
+    unsigned numberOfSourceChannels = sourceChunk->mChannelData.Length();
 
-    ASSERT(numberOfChannels == m_numberOfChannels && numberOfSourceChannels);
+    MOZ_ASSERT(numberOfChannels == m_numberOfChannels && numberOfSourceChannels);
 
     if (numberOfChannels != m_numberOfChannels || !numberOfSourceChannels) {
-        destinationBus->zero();
+        destinationChunk->SetNull(WEBAUDIO_BLOCK_SIZE);
         return;
     }
 
     switch (numberOfChannels) {
     case 2: // stereo
-        m_sourceChannels[0] = sourceBus->channel(0)->data();
+        m_sourceChannels[0] = static_cast<const float*>(sourceChunk->mChannelData[0]);
 
         if (numberOfSourceChannels > 1)
-            m_sourceChannels[1] = sourceBus->channel(1)->data();
+            m_sourceChannels[1] = static_cast<const float*>(sourceChunk->mChannelData[1]);
         else
             // Simply duplicate mono channel input data to right channel for stereo processing.
             m_sourceChannels[1] = m_sourceChannels[0];
 
         break;
     default:
         // FIXME : support other number of channels.
-        ASSERT_NOT_REACHED();
-        destinationBus->zero();
+        NS_NOTREACHED("Support other number of channels");
+        destinationChunk->SetNull(WEBAUDIO_BLOCK_SIZE);
         return;
     }
 
     for (unsigned i = 0; i < numberOfChannels; ++i)
-        m_destinationChannels[i] = destinationBus->channel(i)->mutableData();
+        m_destinationChannels[i] = const_cast<float*>(static_cast<const float*>(
+            destinationChunk->mChannelData[i]));
 
     float filterStageGain = parameterValue(ParamFilterStageGain);
     float filterStageRatio = parameterValue(ParamFilterStageRatio);
     float anchor = parameterValue(ParamFilterAnchor);
 
     if (filterStageGain != m_lastFilterStageGain || filterStageRatio != m_lastFilterStageRatio || anchor != m_lastAnchor) {
         m_lastFilterStageGain = filterStageGain;
         m_lastFilterStageRatio = filterStageRatio;
@@ -259,28 +257,26 @@ void DynamicsCompressor::reset()
         }
     }
 
     m_compressor.reset();
 }
 
 void DynamicsCompressor::setNumberOfChannels(unsigned numberOfChannels)
 {
-    if (m_preFilterPacks.size() == numberOfChannels)
+    if (m_preFilterPacks.Length() == numberOfChannels)
         return;
 
-    m_preFilterPacks.clear();
-    m_postFilterPacks.clear();
+    m_preFilterPacks.Clear();
+    m_postFilterPacks.Clear();
     for (unsigned i = 0; i < numberOfChannels; ++i) {
-        m_preFilterPacks.append(adoptPtr(new ZeroPoleFilterPack4()));
-        m_postFilterPacks.append(adoptPtr(new ZeroPoleFilterPack4()));
+        m_preFilterPacks.AppendElement(new ZeroPoleFilterPack4());
+        m_postFilterPacks.AppendElement(new ZeroPoleFilterPack4());
     }
 
-    m_sourceChannels = adoptArrayPtr(new const float* [numberOfChannels]);
-    m_destinationChannels = adoptArrayPtr(new float* [numberOfChannels]);
+    m_sourceChannels = new const float* [numberOfChannels];
+    m_destinationChannels = new float* [numberOfChannels];
 
     m_compressor.setNumberOfChannels(numberOfChannels);
     m_numberOfChannels = numberOfChannels;
 }
 
 } // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
--- a/content/media/webaudio/blink/DynamicsCompressor.h
+++ b/content/media/webaudio/blink/DynamicsCompressor.h
@@ -24,25 +24,29 @@
  * 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.
  */
 
 #ifndef DynamicsCompressor_h
 #define DynamicsCompressor_h
 
-#include "AudioArray.h"
 #include "DynamicsCompressorKernel.h"
 #include "ZeroPole.h"
 
-#include <wtf/OwnArrayPtr.h>
+#include "nsTArray.h"
+#include "nsAutoPtr.h"
+
+namespace mozilla {
+struct AudioChunk;
+}
 
 namespace WebCore {
 
-class AudioBus;
+using mozilla::AudioChunk;
 
 // DynamicsCompressor implements a flexible audio dynamics compression effect such as
 // is commonly used in musical production and game audio. It lowers the volume
 // of the loudest parts of the signal and raises the volume of the softest parts,
 // making the sound richer, fuller, and more controlled.
 
 class DynamicsCompressor {
 public:
@@ -63,17 +67,17 @@ public:
         ParamFilterAnchor,
         ParamEffectBlend,
         ParamReduction,
         ParamLast
     };
 
     DynamicsCompressor(float sampleRate, unsigned numberOfChannels);
 
-    void process(const AudioBus* sourceBus, AudioBus* destinationBus, unsigned framesToProcess);
+    void process(const AudioChunk* sourceChunk, AudioChunk* destinationChunk, unsigned framesToProcess);
     void reset();
     void setNumberOfChannels(unsigned);
 
     void setParameterValue(unsigned parameterID, float value);
     float parameterValue(unsigned parameterID);
 
     float sampleRate() const { return m_sampleRate; }
     float nyquist() const { return m_sampleRate / 2; }
@@ -95,21 +99,21 @@ protected:
     float m_lastAnchor;
     float m_lastFilterStageGain;
 
     typedef struct {
         ZeroPole filters[4];
     } ZeroPoleFilterPack4;
 
     // Per-channel emphasis filters.
-    Vector<OwnPtr<ZeroPoleFilterPack4> > m_preFilterPacks;
-    Vector<OwnPtr<ZeroPoleFilterPack4> > m_postFilterPacks;
+    nsTArray<nsAutoPtr<ZeroPoleFilterPack4> > m_preFilterPacks;
+    nsTArray<nsAutoPtr<ZeroPoleFilterPack4> > m_postFilterPacks;
 
-    OwnArrayPtr<const float*> m_sourceChannels;
-    OwnArrayPtr<float*> m_destinationChannels;
+    nsAutoArrayPtr<const float*> m_sourceChannels;
+    nsAutoArrayPtr<float*> m_destinationChannels;
 
     void setEmphasisStageParameters(unsigned stageIndex, float gain, float normalizedFrequency /* 0 -> 1 */);
     void setEmphasisParameters(float gain, float anchorFreq, float filterStageRatio);
 
     // The core compressor.
     DynamicsCompressorKernel m_compressor;
 };
 
--- a/content/media/webaudio/blink/DynamicsCompressorKernel.cpp
+++ b/content/media/webaudio/blink/DynamicsCompressorKernel.cpp
@@ -21,32 +21,30 @@
  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * 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 "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
 #include "DynamicsCompressorKernel.h"
 
-#include "AudioUtilities.h"
 #include "DenormalDisabler.h"
 #include <algorithm>
-#include <wtf/MathExtras.h>
+
+#include "mozilla/FloatingPoint.h"
+#include "WebAudioUtils.h"
 
 using namespace std;
 
+using mozilla::dom::WebAudioUtils;
+
 namespace WebCore {
 
-using namespace AudioUtilities;
 
 // Metering hits peaks instantly, but releases this fast (in seconds).
 const float meteringReleaseTimeConstant = 0.325f;
 
 const float uninitializedValue = -1;
 
 DynamicsCompressorKernel::DynamicsCompressorKernel(float sampleRate, unsigned numberOfChannels)
     : m_sampleRate(sampleRate)
@@ -63,40 +61,41 @@ DynamicsCompressorKernel::DynamicsCompre
     , m_ykneeThresholdDb(uninitializedValue)
     , m_K(uninitializedValue)
 {
     setNumberOfChannels(numberOfChannels);
 
     // Initializes most member variables
     reset();
 
-    m_meteringReleaseK = static_cast<float>(discreteTimeConstantForSampleRate(meteringReleaseTimeConstant, sampleRate));
+    m_meteringReleaseK =
+        static_cast<float>(WebAudioUtils::DiscreteTimeConstantForSampleRate(meteringReleaseTimeConstant, sampleRate));
 }
 
 void DynamicsCompressorKernel::setNumberOfChannels(unsigned numberOfChannels)
 {
-    if (m_preDelayBuffers.size() == numberOfChannels)
+    if (m_preDelayBuffers.Length() == numberOfChannels)
         return;
 
-    m_preDelayBuffers.clear();
+    m_preDelayBuffers.Clear();
     for (unsigned i = 0; i < numberOfChannels; ++i)
-        m_preDelayBuffers.append(adoptPtr(new AudioFloatArray(MaxPreDelayFrames)));
+        m_preDelayBuffers.AppendElement(new float[MaxPreDelayFrames]);
 }
 
 void DynamicsCompressorKernel::setPreDelayTime(float preDelayTime)
 {
     // Re-configure look-ahead section pre-delay if delay time has changed.
     unsigned preDelayFrames = preDelayTime * sampleRate();
     if (preDelayFrames > MaxPreDelayFrames - 1)
         preDelayFrames = MaxPreDelayFrames - 1;
 
     if (m_lastPreDelayFrames != preDelayFrames) {
         m_lastPreDelayFrames = preDelayFrames;
-        for (unsigned i = 0; i < m_preDelayBuffers.size(); ++i)
-            m_preDelayBuffers[i]->zero();
+        for (unsigned i = 0; i < m_preDelayBuffers.Length(); ++i)
+            memset(m_preDelayBuffers[i], 0, sizeof(float) * MaxPreDelayFrames);
 
         m_preDelayReadIndex = 0;
         m_preDelayWriteIndex = preDelayFrames;
     }
 }
 
 // Exponential curve for the knee.
 // It is 1st derivative matched at m_linearThreshold and asymptotically approaches the value m_linearThreshold + 1 / k.
@@ -113,50 +112,50 @@ float DynamicsCompressorKernel::kneeCurv
 float DynamicsCompressorKernel::saturate(float x, float k)
 {
     float y;
 
     if (x < m_kneeThreshold)
         y = kneeCurve(x, k);
     else {
         // Constant ratio after knee.
-        float xDb = linearToDecibels(x);
+        float xDb = WebAudioUtils::ConvertLinearToDecibels(x, -1000.0f);
         float yDb = m_ykneeThresholdDb + m_slope * (xDb - m_kneeThresholdDb);
 
-        y = decibelsToLinear(yDb);
+        y = WebAudioUtils::ConvertDecibelsToLinear(yDb);
     }
 
     return y;
 }
 
 // Approximate 1st derivative with input and output expressed in dB.
 // This slope is equal to the inverse of the compression "ratio".
 // In other words, a compression ratio of 20 would be a slope of 1/20.
 float DynamicsCompressorKernel::slopeAt(float x, float k)
 {
     if (x < m_linearThreshold)
         return 1;
 
     float x2 = x * 1.001;
 
-    float xDb = linearToDecibels(x);
-    float x2Db = linearToDecibels(x2);
+    float xDb = WebAudioUtils::ConvertLinearToDecibels(x, -1000.0f);
+    float x2Db = WebAudioUtils::ConvertLinearToDecibels(x2, -1000.0f);
 
-    float yDb = linearToDecibels(kneeCurve(x, k));
-    float y2Db = linearToDecibels(kneeCurve(x2, k));
+    float yDb = WebAudioUtils::ConvertLinearToDecibels(kneeCurve(x, k), -1000.0f);
+    float y2Db = WebAudioUtils::ConvertLinearToDecibels(kneeCurve(x2, k), -1000.0f);
 
     float m = (y2Db - yDb) / (x2Db - xDb);
 
     return m;
 }
 
 float DynamicsCompressorKernel::kAtSlope(float desiredSlope)
 {
     float xDb = m_dbThreshold + m_dbKnee;
-    float x = decibelsToLinear(xDb);
+    float x = WebAudioUtils::ConvertDecibelsToLinear(xDb);
 
     // Approximate k given initial values.
     float minK = 0.1;
     float maxK = 10000;
     float k = 5;
 
     for (int i = 0; i < 15; ++i) {
         // A high value for k will more quickly asymptotically approach a slope of 0.
@@ -177,29 +176,29 @@ float DynamicsCompressorKernel::kAtSlope
     return k;
 }
 
 float DynamicsCompressorKernel::updateStaticCurveParameters(float dbThreshold, float dbKnee, float ratio)
 {
     if (dbThreshold != m_dbThreshold || dbKnee != m_dbKnee || ratio != m_ratio) {
         // Threshold and knee.
         m_dbThreshold = dbThreshold;
-        m_linearThreshold = decibelsToLinear(dbThreshold);
+        m_linearThreshold = WebAudioUtils::ConvertDecibelsToLinear(dbThreshold);
         m_dbKnee = dbKnee;
 
         // Compute knee parameters.
         m_ratio = ratio;
         m_slope = 1 / m_ratio;
 
         float k = kAtSlope(1 / m_ratio);
 
         m_kneeThresholdDb = dbThreshold + dbKnee;
-        m_kneeThreshold = decibelsToLinear(m_kneeThresholdDb);
+        m_kneeThreshold = WebAudioUtils::ConvertDecibelsToLinear(m_kneeThresholdDb);
 
-        m_ykneeThresholdDb = linearToDecibels(kneeCurve(m_kneeThreshold, k));
+        m_ykneeThresholdDb = WebAudioUtils::ConvertLinearToDecibels(kneeCurve(m_kneeThreshold, k), -1000.0f);
 
         m_K = k;
     }
     return m_K;
 }
 
 void DynamicsCompressorKernel::process(float* sourceChannels[],
                                        float* destinationChannels[],
@@ -216,33 +215,33 @@ void DynamicsCompressorKernel::process(f
                                        float effectBlend, /* equal power crossfade */
 
                                        float releaseZone1,
                                        float releaseZone2,
                                        float releaseZone3,
                                        float releaseZone4
                                        )
 {
-    ASSERT(m_preDelayBuffers.size() == numberOfChannels);
+    MOZ_ASSERT(m_preDelayBuffers.Length() == numberOfChannels);
 
     float sampleRate = this->sampleRate();
 
     float dryMix = 1 - effectBlend;
     float wetMix = effectBlend;
 
     float k = updateStaticCurveParameters(dbThreshold, dbKnee, ratio);
 
     // Makeup gain.
     float fullRangeGain = saturate(1, k);
     float fullRangeMakeupGain = 1 / fullRangeGain;
 
     // Empirical/perceptual tuning.
     fullRangeMakeupGain = powf(fullRangeMakeupGain, 0.6f);
 
-    float masterLinearGain = decibelsToLinear(dbPostGain) * fullRangeMakeupGain;
+    float masterLinearGain = WebAudioUtils::ConvertDecibelsToLinear(dbPostGain) * fullRangeMakeupGain;
 
     // Attack parameters.
     attackTime = max(0.001f, attackTime);
     float attackFrames = attackTime * sampleRate;
 
     // Release parameters.
     float releaseFrames = sampleRate * releaseTime;
 
@@ -281,47 +280,47 @@ void DynamicsCompressorKernel::process(f
 
     unsigned frameIndex = 0;
     for (int i = 0; i < nDivisions; ++i) {
         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         // Calculate desired gain
         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
         // Fix gremlins.
-        if (std::isnan(m_detectorAverage))
+        if (MOZ_DOUBLE_IS_NaN(m_detectorAverage))
             m_detectorAverage = 1;
-        if (std::isinf(m_detectorAverage))
+        if (MOZ_DOUBLE_IS_INFINITE(m_detectorAverage))
             m_detectorAverage = 1;
 
         float desiredGain = m_detectorAverage;
 
         // Pre-warp so we get desiredGain after sin() warp below.
-        float scaledDesiredGain = asinf(desiredGain) / (0.5f * piFloat);
+        float scaledDesiredGain = asinf(desiredGain) / (0.5f * M_PI);
 
         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         // Deal with envelopes
         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
         // envelopeRate is the rate we slew from current compressor level to the desired level.
         // The exact rate depends on if we're attacking or releasing and by how much.
         float envelopeRate;
 
         bool isReleasing = scaledDesiredGain > m_compressorGain;
 
         // compressionDiffDb is the difference between current compression level and the desired level.
-        float compressionDiffDb = linearToDecibels(m_compressorGain / scaledDesiredGain);
+        float compressionDiffDb = WebAudioUtils::ConvertLinearToDecibels(m_compressorGain / scaledDesiredGain, -1000.0f);
 
         if (isReleasing) {
             // Release mode - compressionDiffDb should be negative dB
             m_maxAttackCompressionDiffDb = -1;
 
             // Fix gremlins.
-            if (std::isnan(compressionDiffDb))
+            if (MOZ_DOUBLE_IS_NaN(compressionDiffDb))
                 compressionDiffDb = -1;
-            if (std::isinf(compressionDiffDb))
+            if (MOZ_DOUBLE_IS_INFINITE(compressionDiffDb))
                 compressionDiffDb = -1;
 
             // Adaptive release - higher compression (lower compressionDiffDb)  releases faster.
 
             // Contain within range: -12 -> 0 then scale to go from 0 -> 3
             float x = compressionDiffDb;
             x = max(-12.0f, x);
             x = min(0.0f, x);
@@ -332,24 +331,24 @@ void DynamicsCompressorKernel::process(f
             float x2 = x * x;
             float x3 = x2 * x;
             float x4 = x2 * x2;
             float releaseFrames = kA + kB * x + kC * x2 + kD * x3 + kE * x4;
 
 #define kSpacingDb 5
             float dbPerFrame = kSpacingDb / releaseFrames;
 
-            envelopeRate = decibelsToLinear(dbPerFrame);
+            envelopeRate = WebAudioUtils::ConvertDecibelsToLinear(dbPerFrame);
         } else {
             // Attack mode - compressionDiffDb should be positive dB
 
             // Fix gremlins.
-            if (std::isnan(compressionDiffDb))
+            if (MOZ_DOUBLE_IS_NaN(compressionDiffDb))
                 compressionDiffDb = 1;
-            if (std::isinf(compressionDiffDb))
+            if (MOZ_DOUBLE_IS_INFINITE(compressionDiffDb))
                 compressionDiffDb = 1;
 
             // As long as we're still in attack mode, use a rate based off
             // the largest compressionDiffDb we've encountered so far.
             if (m_maxAttackCompressionDiffDb == -1 || m_maxAttackCompressionDiffDb < compressionDiffDb)
                 m_maxAttackCompressionDiffDb = compressionDiffDb;
 
             float effAttenDiffDb = max(0.5f, m_maxAttackCompressionDiffDb);
@@ -369,17 +368,17 @@ void DynamicsCompressorKernel::process(f
             float compressorGain = m_compressorGain;
 
             int loopFrames = nDivisionFrames;
             while (loopFrames--) {
                 float compressorInput = 0;
 
                 // Predelay signal, computing compression amount from un-delayed version.
                 for (unsigned i = 0; i < numberOfChannels; ++i) {
-                    float* delayBuffer = m_preDelayBuffers[i]->data();
+                    float* delayBuffer = m_preDelayBuffers[i];
                     float undelayedSource = sourceChannels[i][frameIndex];
                     delayBuffer[preDelayWriteIndex] = undelayedSource;
 
                     float absUndelayedSource = undelayedSource > 0 ? undelayedSource : -undelayedSource;
                     if (compressorInput < absUndelayedSource)
                         compressorInput = absUndelayedSource;
                 }
 
@@ -391,61 +390,61 @@ void DynamicsCompressorKernel::process(f
                 // Put through shaping curve.
                 // This is linear up to the threshold, then enters a "knee" portion followed by the "ratio" portion.
                 // The transition from the threshold to the knee is smooth (1st derivative matched).
                 // The transition from the knee to the ratio portion is smooth (1st derivative matched).
                 float shapedInput = saturate(absInput, k);
 
                 float attenuation = absInput <= 0.0001f ? 1 : shapedInput / absInput;
 
-                float attenuationDb = -linearToDecibels(attenuation);
+                float attenuationDb = -WebAudioUtils::ConvertLinearToDecibels(attenuation, -1000.0f);
                 attenuationDb = max(2.0f, attenuationDb);
 
                 float dbPerFrame = attenuationDb / satReleaseFrames;
 
-                float satReleaseRate = decibelsToLinear(dbPerFrame) - 1;
+                float satReleaseRate = WebAudioUtils::ConvertDecibelsToLinear(dbPerFrame) - 1;
 
                 bool isRelease = (attenuation > detectorAverage);
                 float rate = isRelease ? satReleaseRate : 1;
 
                 detectorAverage += (attenuation - detectorAverage) * rate;
                 detectorAverage = min(1.0f, detectorAverage);
 
                 // Fix gremlins.
-                if (std::isnan(detectorAverage))
+                if (MOZ_DOUBLE_IS_NaN(detectorAverage))
                     detectorAverage = 1;
-                if (std::isinf(detectorAverage))
+                if (MOZ_DOUBLE_IS_INFINITE(detectorAverage))
                     detectorAverage = 1;
 
                 // Exponential approach to desired gain.
                 if (envelopeRate < 1) {
                     // Attack - reduce gain to desired.
                     compressorGain += (scaledDesiredGain - compressorGain) * envelopeRate;
                 } else {
                     // Release - exponentially increase gain to 1.0
                     compressorGain *= envelopeRate;
                     compressorGain = min(1.0f, compressorGain);
                 }
 
                 // Warp pre-compression gain to smooth out sharp exponential transition points.
-                float postWarpCompressorGain = sinf(0.5f * piFloat * compressorGain);
+                float postWarpCompressorGain = sinf(0.5f * M_PI * compressorGain);
 
                 // Calculate total gain using master gain and effect blend.
                 float totalGain = dryMix + wetMix * masterLinearGain * postWarpCompressorGain;
 
                 // Calculate metering.
                 float dbRealGain = 20 * log10(postWarpCompressorGain);
                 if (dbRealGain < m_meteringGain)
                     m_meteringGain = dbRealGain;
                 else
                     m_meteringGain += (dbRealGain - m_meteringGain) * m_meteringReleaseK;
 
                 // Apply final gain.
                 for (unsigned i = 0; i < numberOfChannels; ++i) {
-                    float* delayBuffer = m_preDelayBuffers[i]->data();
+                    float* delayBuffer = m_preDelayBuffers[i];
                     destinationChannels[i][frameIndex] = delayBuffer[preDelayReadIndex] * totalGain;
                 }
 
                 frameIndex++;
                 preDelayReadIndex = (preDelayReadIndex + 1) & MaxPreDelayFramesMask;
                 preDelayWriteIndex = (preDelayWriteIndex + 1) & MaxPreDelayFramesMask;
             }
 
@@ -460,20 +459,18 @@ void DynamicsCompressorKernel::process(f
 
 void DynamicsCompressorKernel::reset()
 {
     m_detectorAverage = 0;
     m_compressorGain = 1;
     m_meteringGain = 1;
 
     // Predelay section.
-    for (unsigned i = 0; i < m_preDelayBuffers.size(); ++i)
-        m_preDelayBuffers[i]->zero();
+    for (unsigned i = 0; i < m_preDelayBuffers.Length(); ++i)
+        memset(m_preDelayBuffers[i], 0, sizeof(float) * MaxPreDelayFrames);
 
     m_preDelayReadIndex = 0;
     m_preDelayWriteIndex = DefaultPreDelayFrames;
 
     m_maxAttackCompressionDiffDb = -1; // uninitialized state
 }
 
 } // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
--- a/content/media/webaudio/blink/DynamicsCompressorKernel.h
+++ b/content/media/webaudio/blink/DynamicsCompressorKernel.h
@@ -24,20 +24,18 @@
  * 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.
  */
 
 #ifndef DynamicsCompressorKernel_h
 #define DynamicsCompressorKernel_h
 
-#include "AudioArray.h"
-
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
+#include "nsTArray.h"
+#include "nsAutoPtr.h"
 
 namespace WebCore {
 
 class DynamicsCompressorKernel {
 public:
     DynamicsCompressorKernel(float sampleRate, unsigned numberOfChannels);
 
     void setNumberOfChannels(unsigned);
@@ -83,17 +81,17 @@ protected:
 
     // Lookahead section.
     enum { MaxPreDelayFrames = 1024 };
     enum { MaxPreDelayFramesMask = MaxPreDelayFrames - 1 };
     enum { DefaultPreDelayFrames = 256 }; // setPreDelayTime() will override this initial value
     unsigned m_lastPreDelayFrames;
     void setPreDelayTime(float);
 
-    Vector<OwnPtr<AudioFloatArray> > m_preDelayBuffers;
+    nsTArray<nsAutoArrayPtr<float> > m_preDelayBuffers;
     int m_preDelayReadIndex;
     int m_preDelayWriteIndex;
 
     float m_maxAttackCompressionDiffDb;
 
     // Static compression curve.
     float kneeCurve(float x, float k);
     float saturate(float x, float k);
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/blink/Makefile.in
@@ -0,0 +1,23 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# 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/.
+
+DEPTH            := @DEPTH@
+topsrcdir        := @top_srcdir@
+srcdir           := @srcdir@
+VPATH            := @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+LIBRARY_NAME   := gkconwebaudio_blink_s
+LIBXUL_LIBRARY := 1
+
+CPPSRCS := \
+  DynamicsCompressor.cpp \
+  DynamicsCompressorKernel.cpp \
+  ZeroPole.cpp \
+  $(NULL)
+
+FORCE_STATIC_LIB := 1
+
+include $(topsrcdir)/config/rules.mk
--- a/content/media/webaudio/blink/ZeroPole.cpp
+++ b/content/media/webaudio/blink/ZeroPole.cpp
@@ -21,20 +21,16 @@
  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * 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 "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
 #include "ZeroPole.h"
 
 #include "DenormalDisabler.h"
 
 namespace WebCore {
 
 void ZeroPole::process(const float *source, float *destination, unsigned framesToProcess)
 {
@@ -65,10 +61,8 @@ void ZeroPole::process(const float *sour
     
     // Locals to member variables. Flush denormals here so we don't
     // slow down the inner loop above.
     m_lastX = DenormalDisabler::flushDenormalFloatToZero(lastX);
     m_lastY = DenormalDisabler::flushDenormalFloatToZero(lastY);
 }
 
 } // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/blink/moz.build
@@ -0,0 +1,8 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# 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/.
+
+MODULE = 'content'
+
--- a/content/media/webaudio/moz.build
+++ b/content/media/webaudio/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # 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/.
 
-PARALLEL_DIRS += ['test']
+PARALLEL_DIRS += ['blink', 'test']
 
 TEST_TOOL_DIRS += ['compiledtest']
 
 MODULE = 'content'
 
 EXPORTS += [
     'AudioParamTimeline.h',
     'MediaBufferDecoder.h',
--- a/layout/build/Makefile.in
+++ b/layout/build/Makefile.in
@@ -40,16 +40,17 @@ SHARED_LIBRARY_LIBS = \
 	../mathml/$(LIB_PREFIX)gkmathml_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/base/src/$(LIB_PREFIX)gkconbase_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/canvas/src/$(LIB_PREFIX)gkconcvs_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/events/src/$(LIB_PREFIX)gkconevents_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/html/content/src/$(LIB_PREFIX)gkconhtmlcon_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/html/document/src/$(LIB_PREFIX)gkconhtmldoc_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/media/$(LIB_PREFIX)gkconmedia_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/media/webaudio/$(LIB_PREFIX)gkconwebaudio_s.$(LIB_SUFFIX) \
+	$(DEPTH)/content/media/webaudio/blink/$(LIB_PREFIX)gkconwebaudio_blink_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/media/webrtc/$(LIB_PREFIX)gkconwebrtc_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/xml/content/src/$(LIB_PREFIX)gkconxmlcon_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/xml/document/src/$(LIB_PREFIX)gkconxmldoc_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/xslt/src/base/$(LIB_PREFIX)txbase_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/xslt/src/xml/$(LIB_PREFIX)txxml_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/xslt/src/xpath/$(LIB_PREFIX)txxpath_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/xslt/src/xslt/$(LIB_PREFIX)txxslt_s.$(LIB_SUFFIX) \
 	$(DEPTH)/content/xbl/src/$(LIB_PREFIX)gkconxbl_s.$(LIB_SUFFIX) \