2011-05-16 Chris Rogers <crogers@google.com>
authorcrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 May 2011 21:34:54 +0000 (21:34 +0000)
committercrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 May 2011 21:34:54 +0000 (21:34 +0000)
        Reviewed by senorblanco@chromium.org.

        Add DynamicsCompressorNode implementation
        https://bugs.webkit.org/show_bug.cgi?id=60682

        No new tests since audio API is not yet implemented.

        * DerivedSources.make:
        * WebCore.gypi:
        * WebCore.xcodeproj/project.pbxproj:
        * platform/audio/DynamicsCompressor.cpp: Added.
        (WebCore::DynamicsCompressor::DynamicsCompressor):
        (WebCore::DynamicsCompressor::initializeParameters):
        (WebCore::DynamicsCompressor::parameterValue):
        (WebCore::DynamicsCompressor::setEmphasisStageParameters):
        (WebCore::DynamicsCompressor::setEmphasisParameters):
        (WebCore::DynamicsCompressor::process):
        (WebCore::DynamicsCompressor::reset):
        * platform/audio/DynamicsCompressor.h: Added.
        (WebCore::DynamicsCompressor::isStereo):
        (WebCore::DynamicsCompressor::sampleRate):
        (WebCore::DynamicsCompressor::nyquist):
        * platform/audio/DynamicsCompressorKernel.cpp: Added.
        (WebCore::saturate):
        (WebCore::DynamicsCompressorKernel::DynamicsCompressorKernel):
        (WebCore::DynamicsCompressorKernel::setPreDelayTime):
        (WebCore::DynamicsCompressorKernel::process):
        (WebCore::DynamicsCompressorKernel::reset):
        * platform/audio/DynamicsCompressorKernel.h: Added.
        (WebCore::DynamicsCompressorKernel::latencyFrames):
        (WebCore::DynamicsCompressorKernel::sampleRate):
        * platform/audio/ZeroPole.cpp: Added.
        (WebCore::ZeroPole::process):
        * platform/audio/ZeroPole.h: Added.
        (WebCore::ZeroPole::ZeroPole):
        (WebCore::ZeroPole::reset):
        (WebCore::ZeroPole::setZero):
        (WebCore::ZeroPole::setPole):
        (WebCore::ZeroPole::zero):
        (WebCore::ZeroPole::pole):
        * webaudio/AudioContext.cpp:
        (WebCore::AudioContext::createDynamicsCompressor):
        * webaudio/AudioContext.h:
        * webaudio/AudioContext.idl:
        * webaudio/AudioNode.h:
        * webaudio/DynamicsCompressorNode.cpp: Added.
        (WebCore::DynamicsCompressorNode::DynamicsCompressorNode):
        (WebCore::DynamicsCompressorNode::~DynamicsCompressorNode):
        (WebCore::DynamicsCompressorNode::process):
        (WebCore::DynamicsCompressorNode::reset):
        (WebCore::DynamicsCompressorNode::initialize):
        (WebCore::DynamicsCompressorNode::uninitialize):
        * webaudio/DynamicsCompressorNode.h: Added.
        (WebCore::DynamicsCompressorNode::create):
        * webaudio/DynamicsCompressorNode.idl: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@86607 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
Source/WebCore/ChangeLog
Source/WebCore/DerivedSources.make
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/audio/DynamicsCompressor.cpp [new file with mode: 0644]
Source/WebCore/platform/audio/DynamicsCompressor.h [new file with mode: 0644]
Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp [new file with mode: 0644]
Source/WebCore/platform/audio/DynamicsCompressorKernel.h [new file with mode: 0644]
Source/WebCore/platform/audio/ZeroPole.cpp [new file with mode: 0644]
Source/WebCore/platform/audio/ZeroPole.h [new file with mode: 0644]
Source/WebCore/webaudio/AudioContext.cpp
Source/WebCore/webaudio/AudioContext.h
Source/WebCore/webaudio/AudioContext.idl
Source/WebCore/webaudio/AudioNode.h
Source/WebCore/webaudio/DynamicsCompressorNode.cpp [new file with mode: 0644]
Source/WebCore/webaudio/DynamicsCompressorNode.h [new file with mode: 0644]
Source/WebCore/webaudio/DynamicsCompressorNode.idl [new file with mode: 0644]

index 41ce477183338741ece2117dbedda5091d298d3c..4659d4b4002e0e8ec5c384256df08fd11cb907b3 100644 (file)
@@ -1,3 +1,61 @@
+2011-05-16  Chris Rogers  <crogers@google.com>
+
+        Reviewed by senorblanco@chromium.org.
+
+        Add DynamicsCompressorNode implementation
+        https://bugs.webkit.org/show_bug.cgi?id=60682
+
+        No new tests since audio API is not yet implemented.
+
+        * DerivedSources.make:
+        * WebCore.gypi:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/audio/DynamicsCompressor.cpp: Added.
+        (WebCore::DynamicsCompressor::DynamicsCompressor):
+        (WebCore::DynamicsCompressor::initializeParameters):
+        (WebCore::DynamicsCompressor::parameterValue):
+        (WebCore::DynamicsCompressor::setEmphasisStageParameters):
+        (WebCore::DynamicsCompressor::setEmphasisParameters):
+        (WebCore::DynamicsCompressor::process):
+        (WebCore::DynamicsCompressor::reset):
+        * platform/audio/DynamicsCompressor.h: Added.
+        (WebCore::DynamicsCompressor::isStereo):
+        (WebCore::DynamicsCompressor::sampleRate):
+        (WebCore::DynamicsCompressor::nyquist):
+        * platform/audio/DynamicsCompressorKernel.cpp: Added.
+        (WebCore::saturate):
+        (WebCore::DynamicsCompressorKernel::DynamicsCompressorKernel):
+        (WebCore::DynamicsCompressorKernel::setPreDelayTime):
+        (WebCore::DynamicsCompressorKernel::process):
+        (WebCore::DynamicsCompressorKernel::reset):
+        * platform/audio/DynamicsCompressorKernel.h: Added.
+        (WebCore::DynamicsCompressorKernel::latencyFrames):
+        (WebCore::DynamicsCompressorKernel::sampleRate):
+        * platform/audio/ZeroPole.cpp: Added.
+        (WebCore::ZeroPole::process):
+        * platform/audio/ZeroPole.h: Added.
+        (WebCore::ZeroPole::ZeroPole):
+        (WebCore::ZeroPole::reset):
+        (WebCore::ZeroPole::setZero):
+        (WebCore::ZeroPole::setPole):
+        (WebCore::ZeroPole::zero):
+        (WebCore::ZeroPole::pole):
+        * webaudio/AudioContext.cpp:
+        (WebCore::AudioContext::createDynamicsCompressor):
+        * webaudio/AudioContext.h:
+        * webaudio/AudioContext.idl:
+        * webaudio/AudioNode.h:
+        * webaudio/DynamicsCompressorNode.cpp: Added.
+        (WebCore::DynamicsCompressorNode::DynamicsCompressorNode):
+        (WebCore::DynamicsCompressorNode::~DynamicsCompressorNode):
+        (WebCore::DynamicsCompressorNode::process):
+        (WebCore::DynamicsCompressorNode::reset):
+        (WebCore::DynamicsCompressorNode::initialize):
+        (WebCore::DynamicsCompressorNode::uninitialize):
+        * webaudio/DynamicsCompressorNode.h: Added.
+        (WebCore::DynamicsCompressorNode::create):
+        * webaudio/DynamicsCompressorNode.idl: Added.
+
 2011-05-16  Yuzo Fujishima  <yuzo@google.com>
 
         Reviewed by Antti Koivisto.
index c4f1bc280e48c2f0ece1efd35db2b82ccb5cbc09..52bc76c0bd9e4a2cbfe684de4d5b0ed72f3541d5 100644 (file)
@@ -69,6 +69,7 @@ DOM_CLASSES = \
     AudioSourceNode \
     ConvolverNode \
     DelayNode \
+    DynamicsCompressorNode \
     HighPass2FilterNode \
     JavaScriptAudioNode \
     LowPass2FilterNode \
index f43bb2571b28ab8c9745c19cfe464aa34ddc776e..67086b9d94071359db50468392e50c14048d813e 100644 (file)
             'webaudio/AudioSourceNode.idl',
             'webaudio/ConvolverNode.idl',
             'webaudio/DelayNode.idl',
+            'webaudio/DynamicsCompressorNode.idl',
             'webaudio/HighPass2FilterNode.idl',
             'webaudio/JavaScriptAudioNode.idl',
             'webaudio/LowPass2FilterNode.idl',
             'platform/audio/DenormalDisabler.h',
             'platform/audio/Distance.cpp',
             'platform/audio/Distance.h',
+            'platform/audio/DynamicsCompressor.cpp',
+            'platform/audio/DynamicsCompressor.h',
+            'platform/audio/DynamicsCompressorKernel.cpp',
+            'platform/audio/DynamicsCompressorKernel.h',
             'platform/audio/EqualPowerPanner.cpp',
             'platform/audio/EqualPowerPanner.h',
             'platform/audio/FFTConvolver.cpp',
             'platform/audio/SincResampler.h',
             'platform/audio/VectorMath.cpp',
             'platform/audio/VectorMath.h',
+            'platform/audio/ZeroPole.cpp',
+            'platform/audio/ZeroPole.h',
             'platform/audio/chromium/AudioBusChromium.cpp',
             'platform/audio/fftw/FFTFrameFFTW.cpp',
             'platform/audio/mac/AudioBusMac.mm',
             'webaudio/DelayNode.h',
             'webaudio/DelayProcessor.cpp',
             'webaudio/DelayProcessor.h',
+            'webaudio/DynamicsCompressorNode.cpp',
+            'webaudio/DynamicsCompressorNode.h',
             'webaudio/HighPass2FilterNode.cpp',
             'webaudio/HighPass2FilterNode.h',
             'webaudio/JavaScriptAudioNode.cpp',
index b423dd4c1ae6f8b33381c971b4dceaba9be25942..f116b2c5f109dd3c3719fa493f586b3df324921a 100644 (file)
                FD3160BE12B0272A00C1A359 /* AudioFileReaderMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD3160B812B0272A00C1A359 /* AudioFileReaderMac.cpp */; };
                FD3160BF12B0272A00C1A359 /* AudioFileReaderMac.h in Headers */ = {isa = PBXBuildFile; fileRef = FD3160B912B0272A00C1A359 /* AudioFileReaderMac.h */; };
                FD3160C012B0272A00C1A359 /* FFTFrameMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD3160BA12B0272A00C1A359 /* FFTFrameMac.cpp */; };
+               FD537352137B651800008DCE /* ZeroPole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD537350137B651800008DCE /* ZeroPole.cpp */; };
+               FD537353137B651800008DCE /* ZeroPole.h in Headers */ = {isa = PBXBuildFile; fileRef = FD537351137B651800008DCE /* ZeroPole.h */; };
+               FD537356137B653B00008DCE /* DynamicsCompressorKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD537354137B653B00008DCE /* DynamicsCompressorKernel.cpp */; };
+               FD537357137B653B00008DCE /* DynamicsCompressorKernel.h in Headers */ = {isa = PBXBuildFile; fileRef = FD537355137B653B00008DCE /* DynamicsCompressorKernel.h */; };
+               FD6ED2C3136B8E42003CF072 /* DynamicsCompressorNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD6ED2C1136B8E42003CF072 /* DynamicsCompressorNode.cpp */; };
+               FD6ED2C4136B8E42003CF072 /* DynamicsCompressorNode.h in Headers */ = {isa = PBXBuildFile; fileRef = FD6ED2C2136B8E42003CF072 /* DynamicsCompressorNode.h */; };
+               FD6ED2C7136B8E66003CF072 /* DynamicsCompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD6ED2C5136B8E66003CF072 /* DynamicsCompressor.cpp */; };
+               FD6ED2C8136B8E66003CF072 /* DynamicsCompressor.h in Headers */ = {isa = PBXBuildFile; fileRef = FD6ED2C6136B8E66003CF072 /* DynamicsCompressor.h */; };
+               FD7868B9136B999200D403DF /* JSDynamicsCompressorNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD7868B7136B999200D403DF /* JSDynamicsCompressorNode.cpp */; };
+               FD7868BA136B999200D403DF /* JSDynamicsCompressorNode.h in Headers */ = {isa = PBXBuildFile; fileRef = FD7868B8136B999200D403DF /* JSDynamicsCompressorNode.h */; };
                FDA15E9D12B03EE1003A583A /* JSAudioBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FDA15E8112B03EE1003A583A /* JSAudioBuffer.cpp */; };
                FDA15E9E12B03EE1003A583A /* JSAudioBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = FDA15E8212B03EE1003A583A /* JSAudioBuffer.h */; };
                FDA15E9F12B03EE1003A583A /* JSAudioBufferSourceNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FDA15E8312B03EE1003A583A /* JSAudioBufferSourceNode.cpp */; };
                FBC220DE1237FBEB00BCF788 /* GraphicsContext3DOpenGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3DOpenGL.cpp; sourceTree = "<group>"; };
                FD06DFA3134A4DEF006F5D7D /* DefaultAudioDestinationNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DefaultAudioDestinationNode.cpp; sourceTree = "<group>"; };
                FD06DFA4134A4DEF006F5D7D /* DefaultAudioDestinationNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultAudioDestinationNode.h; sourceTree = "<group>"; };
-               FD1660A413787C6D001FFA7B /* DenormalDisabler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DenormalDisabler.h; path = webaudio/audio/DenormalDisabler.h; sourceTree = SOURCE_ROOT; };
+               FD1660A413787C6D001FFA7B /* DenormalDisabler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DenormalDisabler.h; sourceTree = "<group>"; };
                FD2DBF0E12B048A300ED98C6 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = /System/Library/Frameworks/Accelerate.framework; sourceTree = "<absolute>"; };
                FD2DBF0F12B048A300ED98C6 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; };
                FD2DBF1012B048A300ED98C6 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = "<absolute>"; };
                FD3160B812B0272A00C1A359 /* AudioFileReaderMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioFileReaderMac.cpp; sourceTree = "<group>"; };
                FD3160B912B0272A00C1A359 /* AudioFileReaderMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioFileReaderMac.h; sourceTree = "<group>"; };
                FD3160BA12B0272A00C1A359 /* FFTFrameMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FFTFrameMac.cpp; sourceTree = "<group>"; };
+               FD537350137B651800008DCE /* ZeroPole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ZeroPole.cpp; sourceTree = "<group>"; };
+               FD537351137B651800008DCE /* ZeroPole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZeroPole.h; sourceTree = "<group>"; };
+               FD537354137B653B00008DCE /* DynamicsCompressorKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicsCompressorKernel.cpp; sourceTree = "<group>"; };
+               FD537355137B653B00008DCE /* DynamicsCompressorKernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicsCompressorKernel.h; sourceTree = "<group>"; };
+               FD6ED2C1136B8E42003CF072 /* DynamicsCompressorNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicsCompressorNode.cpp; sourceTree = "<group>"; };
+               FD6ED2C2136B8E42003CF072 /* DynamicsCompressorNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicsCompressorNode.h; sourceTree = "<group>"; };
+               FD6ED2C5136B8E66003CF072 /* DynamicsCompressor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicsCompressor.cpp; sourceTree = "<group>"; };
+               FD6ED2C6136B8E66003CF072 /* DynamicsCompressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicsCompressor.h; sourceTree = "<group>"; };
+               FD6ED2C9136B8E9D003CF072 /* DynamicsCompressorNode.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DynamicsCompressorNode.idl; sourceTree = "<group>"; };
+               FD7868B7136B999200D403DF /* JSDynamicsCompressorNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDynamicsCompressorNode.cpp; sourceTree = "<group>"; };
+               FD7868B8136B999200D403DF /* JSDynamicsCompressorNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDynamicsCompressorNode.h; sourceTree = "<group>"; };
                FDA15E8112B03EE1003A583A /* JSAudioBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAudioBuffer.cpp; sourceTree = "<group>"; };
                FDA15E8212B03EE1003A583A /* JSAudioBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAudioBuffer.h; sourceTree = "<group>"; };
                FDA15E8312B03EE1003A583A /* JSAudioBufferSourceNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAudioBufferSourceNode.cpp; sourceTree = "<group>"; };
                                FD315FE512B0267600C1A359 /* DelayNode.idl */,
                                FD315FE612B0267600C1A359 /* DelayProcessor.cpp */,
                                FD315FE712B0267600C1A359 /* DelayProcessor.h */,
+                               FD6ED2C1136B8E42003CF072 /* DynamicsCompressorNode.cpp */,
+                               FD6ED2C2136B8E42003CF072 /* DynamicsCompressorNode.h */,
+                               FD6ED2C9136B8E9D003CF072 /* DynamicsCompressorNode.idl */,
                                FD315FE812B0267600C1A359 /* HighPass2FilterNode.cpp */,
                                FD315FE912B0267600C1A359 /* HighPass2FilterNode.h */,
                                FD315FEA12B0267600C1A359 /* HighPass2FilterNode.idl */,
                                FD31605912B026F700C1A359 /* Cone.h */,
                                FD31605A12B026F700C1A359 /* Distance.cpp */,
                                FD31605B12B026F700C1A359 /* Distance.h */,
+                               FD6ED2C5136B8E66003CF072 /* DynamicsCompressor.cpp */,
+                               FD6ED2C6136B8E66003CF072 /* DynamicsCompressor.h */,
+                               FD537354137B653B00008DCE /* DynamicsCompressorKernel.cpp */,
+                               FD537355137B653B00008DCE /* DynamicsCompressorKernel.h */,
                                FD1660A413787C6D001FFA7B /* DenormalDisabler.h */,
                                FD31605C12B026F700C1A359 /* EqualPowerPanner.cpp */,
                                FD31605D12B026F700C1A359 /* EqualPowerPanner.h */,
                                FD31607712B026F700C1A359 /* ReverbInputBuffer.h */,
                                FD31607812B026F700C1A359 /* VectorMath.cpp */,
                                FD31607912B026F700C1A359 /* VectorMath.h */,
+                               FD537350137B651800008DCE /* ZeroPole.cpp */,
+                               FD537351137B651800008DCE /* ZeroPole.h */,
                        );
                        path = audio;
                        sourceTree = "<group>";
                                FDA15EBC12B03F0B003A583A /* JSConvolverNode.h */,
                                FDA15ECF12B03F94003A583A /* JSDelayNode.cpp */,
                                FDA15ED012B03F94003A583A /* JSDelayNode.h */,
+                               FD7868B7136B999200D403DF /* JSDynamicsCompressorNode.cpp */,
+                               FD7868B8136B999200D403DF /* JSDynamicsCompressorNode.h */,
                                FDA15EBF12B03F2D003A583A /* JSHighPass2FilterNode.cpp */,
                                FDA15EC012B03F2D003A583A /* JSHighPass2FilterNode.h */,
                                FDA15ECB12B03F61003A583A /* JSJavaScriptAudioNode.cpp */,
                                93F199ED08245E59001E9ABC /* XSLTProcessor.h in Headers */,
                                E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */,
                                977E2E0F12F0FC9C00C13379 /* XSSFilter.h in Headers */,
+                               FD6ED2C4136B8E42003CF072 /* DynamicsCompressorNode.h in Headers */,
+                               FD6ED2C8136B8E66003CF072 /* DynamicsCompressor.h in Headers */,
+                               FD7868BA136B999200D403DF /* JSDynamicsCompressorNode.h in Headers */,
                                37AFFDF71370A0B800E895C0 /* SharedBufferCRLFLineReader.h in Headers */,
                                379E371713736A6600B9E919 /* QuotedPrintable.h in Headers */,
                                FD1660A513787C6D001FFA7B /* DenormalDisabler.h in Headers */,
                                BCE5644E137A34D6007D2934 /* ConsoleTypes.h in Headers */,
+                               FD537353137B651800008DCE /* ZeroPole.h in Headers */,
+                               FD537357137B653B00008DCE /* DynamicsCompressorKernel.h in Headers */,
                                BCF7E491137CD7C7001DDAE7 /* AdjustViewSizeOrNot.h in Headers */,
                                B1E54593134629C10092A545 /* CallbackTask.h in Headers */,
                        );
                                93F19B0508245E59001E9ABC /* XSLTProcessorLibxslt.cpp in Sources */,
                                E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */,
                                977E2E0E12F0FC9C00C13379 /* XSSFilter.cpp in Sources */,
+                               FD6ED2C3136B8E42003CF072 /* DynamicsCompressorNode.cpp in Sources */,
+                               FD6ED2C7136B8E66003CF072 /* DynamicsCompressor.cpp in Sources */,
+                               FD7868B9136B999200D403DF /* JSDynamicsCompressorNode.cpp in Sources */,
                                37AFFDF61370A0B800E895C0 /* SharedBufferCRLFLineReader.cpp in Sources */,
                                379E371613736A6600B9E919 /* QuotedPrintable.cpp in Sources */,
+                               FD537352137B651800008DCE /* ZeroPole.cpp in Sources */,
+                               FD537356137B653B00008DCE /* DynamicsCompressorKernel.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/Source/WebCore/platform/audio/DynamicsCompressor.cpp b/Source/WebCore/platform/audio/DynamicsCompressor.cpp
new file mode 100644 (file)
index 0000000..15eec9f
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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 "AudioBus.h"
+#include "AudioUtilities.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+using namespace AudioUtilities;
+    
+DynamicsCompressor::DynamicsCompressor(bool isStereo, double sampleRate)
+    : m_isStereo(isStereo)
+    , m_sampleRate(sampleRate)
+    , m_compressor(sampleRate)
+{
+    // Uninitialized state - for parameter recalculation.
+    m_lastFilterStageRatio = -1;
+    m_lastAnchor = -1;
+    m_lastFilterStageGain = -1;
+
+    initializeParameters();
+}
+
+void DynamicsCompressor::initializeParameters()
+{
+    // Initializes compressor to default values.
+    
+    m_parameters[ParamThreshold] = -24; // dB
+    m_parameters[ParamHeadroom] = 21; // dB
+    m_parameters[ParamAttack] = 0.003; // seconds
+    m_parameters[ParamRelease] = 0.250; // seconds
+    m_parameters[ParamPreDelay] = 0.006; // seconds
+
+    // Release zone values 0 -> 1.
+    m_parameters[ParamReleaseZone1] = 0.09;
+    m_parameters[ParamReleaseZone2] = 0.16;
+    m_parameters[ParamReleaseZone3] = 0.42;
+    m_parameters[ParamReleaseZone4] = 0.98;
+
+    m_parameters[ParamFilterStageGain] = 4.4; // dB
+    m_parameters[ParamFilterStageRatio] = 2;
+    m_parameters[ParamFilterAnchor] = 15000 / nyquist();
+    
+    m_parameters[ParamPostGain] = 0; // dB
+
+    // Linear crossfade (0 -> 1).
+    m_parameters[ParamEffectBlend] = 1;
+}
+
+double DynamicsCompressor::parameterValue(unsigned parameterID)
+{
+    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 = exp(-f1 * piDouble);
+    float r2 = exp(-f2 * piDouble);
+
+    // Set pre-filter zero and pole to create an emphasis filter.
+    m_preFilter[stageIndex].setZero(r1);
+    m_preFilter[stageIndex].setPole(r2);
+    m_preFilterR[stageIndex].setZero(r1);
+    m_preFilterR[stageIndex].setPole(r2);
+
+    // Set post-filter with zero and pole reversed to create the de-emphasis filter.
+    // If there were no compressor kernel in between, they would cancel each other out (allpass filter).
+    m_postFilter[stageIndex].setZero(r2);
+    m_postFilter[stageIndex].setPole(r1);
+    m_postFilterR[stageIndex].setZero(r2);
+    m_postFilterR[stageIndex].setPole(r1);
+}
+
+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(AudioBus* sourceBus, AudioBus* destinationBus, unsigned framesToProcess)
+{
+    float* sourceL = sourceBus->channel(0)->data();
+    float* sourceR;
+
+    if (sourceBus->numberOfChannels() > 1)
+        sourceR = sourceBus->channel(1)->data();
+    else
+        sourceR = sourceL;
+
+    ASSERT(destinationBus->numberOfChannels() == 2);
+
+    float* destinationL = destinationBus->channel(0)->data();
+    float* destinationR = destinationBus->channel(1)->data();
+
+    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;
+        m_lastAnchor = anchor;
+
+        setEmphasisParameters(filterStageGain, anchor, filterStageRatio);
+    }
+
+    // Apply pre-emphasis filter.
+    // Note that the final three stages are computed in-place in the destination buffer.
+    m_preFilter[0].process(sourceL, destinationL, framesToProcess);
+    m_preFilter[1].process(destinationL, destinationL, framesToProcess);
+    m_preFilter[2].process(destinationL, destinationL, framesToProcess);
+    m_preFilter[3].process(destinationL, destinationL, framesToProcess);
+
+    if (isStereo()) {
+        m_preFilterR[0].process(sourceR, destinationR, framesToProcess);
+        m_preFilterR[1].process(destinationR, destinationR, framesToProcess);
+        m_preFilterR[2].process(destinationR, destinationR, framesToProcess);
+        m_preFilterR[3].process(destinationR, destinationR, framesToProcess);
+    }
+
+    float dbThreshold = parameterValue(ParamThreshold);
+    float dbHeadroom = parameterValue(ParamHeadroom);
+    float attackTime = parameterValue(ParamAttack);
+    float releaseTime = parameterValue(ParamRelease);
+    float preDelayTime = parameterValue(ParamPreDelay);
+
+    // This is effectively a master volume on the compressed signal (pre-blending).
+    float dbPostGain = parameterValue(ParamPostGain);
+
+    // Linear blending value from dry to completely processed (0 -> 1)
+    // 0 means the signal is completely unprocessed.
+    // 1 mixes in only the compressed signal.
+    float effectBlend = parameterValue(ParamEffectBlend);
+
+    double releaseZone1 = parameterValue(ParamReleaseZone1);
+    double releaseZone2 = parameterValue(ParamReleaseZone2);
+    double releaseZone3 = parameterValue(ParamReleaseZone3);
+    double releaseZone4 = parameterValue(ParamReleaseZone4);
+
+    // Apply compression to the pre-filtered signal.
+    // The processing is performed in place.
+    m_compressor.process(destinationL,
+                         destinationL,
+                         destinationR,
+                         destinationR,
+                         framesToProcess,
+
+                         dbThreshold,
+                         dbHeadroom,
+                         attackTime,
+                         releaseTime,
+                         preDelayTime,
+                         dbPostGain,
+                         effectBlend,
+
+                         releaseZone1,
+                         releaseZone2,
+                         releaseZone3,
+                         releaseZone4
+                         );
+
+    // Apply de-emphasis filter.
+    m_postFilter[0].process(destinationL, destinationL, framesToProcess);
+    m_postFilter[1].process(destinationL, destinationL, framesToProcess);
+    m_postFilter[2].process(destinationL, destinationL, framesToProcess);
+    m_postFilter[3].process(destinationL, destinationL, framesToProcess);
+
+    if (isStereo()) {
+        m_postFilterR[0].process(destinationR, destinationR, framesToProcess);
+        m_postFilterR[1].process(destinationR, destinationR, framesToProcess);
+        m_postFilterR[2].process(destinationR, destinationR, framesToProcess);
+        m_postFilterR[3].process(destinationR, destinationR, framesToProcess);
+    }
+}
+
+void DynamicsCompressor::reset()
+{
+    m_lastFilterStageRatio = -1; // for recalc
+    m_lastAnchor = -1;
+    m_lastFilterStageGain = -1;
+
+    for (unsigned i = 0; i < 4; ++i) {
+        m_preFilter[i].reset();
+        m_preFilterR[i].reset();
+        m_postFilter[i].reset();
+        m_postFilterR[i].reset();
+    }
+
+    m_compressor.reset();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/DynamicsCompressor.h b/Source/WebCore/platform/audio/DynamicsCompressor.h
new file mode 100644 (file)
index 0000000..d0c036f
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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.
+ */
+
+#ifndef DynamicsCompressor_h
+#define DynamicsCompressor_h
+
+#include "AudioArray.h"
+#include "DynamicsCompressorKernel.h"
+#include "ZeroPole.h"
+
+namespace WebCore {
+
+class AudioBus;
+
+// 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:
+    enum {
+        ParamThreshold,
+        ParamHeadroom,
+        ParamAttack,
+        ParamRelease,
+        ParamPreDelay,
+        ParamReleaseZone1,
+        ParamReleaseZone2,
+        ParamReleaseZone3,
+        ParamReleaseZone4,
+        ParamPostGain,
+        ParamFilterStageGain,
+        ParamFilterStageRatio,
+        ParamFilterAnchor,
+        ParamEffectBlend,
+        ParamLast
+    };
+
+    DynamicsCompressor(bool isStereo, double sampleRate);
+
+    void process(AudioBus* sourceBus, AudioBus* destinationBus, unsigned framesToProcess);
+    void reset();
+
+    double parameterValue(unsigned parameterID);
+
+    bool isStereo() const { return m_isStereo; }
+    double sampleRate() const { return m_sampleRate; }
+    double nyquist() const { return 0.5 * m_sampleRate; }
+
+protected:
+    // m_parameters holds the tweakable compressor parameters.
+    // FIXME: expose some of the most important ones (such as threshold, attack, release)
+    // as DynamicsCompressorNode attributes.
+    double m_parameters[ParamLast];
+    void initializeParameters();
+
+    bool m_isStereo;
+    double m_sampleRate;
+
+    // Emphasis filter controls.
+    float m_lastFilterStageRatio;
+    float m_lastAnchor;
+    float m_lastFilterStageGain;
+
+    // Emphasis filters.
+    ZeroPole m_preFilter[4];
+    ZeroPole m_preFilterR[4];
+    ZeroPole m_postFilter[4];
+    ZeroPole m_postFilterR[4];
+
+    void setEmphasisStageParameters(unsigned stageIndex, float gain, float normalizedFrequency /* 0 -> 1 */);
+    void setEmphasisParameters(float gain, float anchorFreq, float filterStageRatio);
+
+    // The core compressor.
+    DynamicsCompressorKernel m_compressor;
+};
+
+} // namespace WebCore
+
+#endif // DynamicsCompressor_h
diff --git a/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp b/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp
new file mode 100644 (file)
index 0000000..a072346
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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 <algorithm>
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace AudioUtilities;
+
+// Metering hits peaks instantly, but releases this fast (in seconds).
+const double meteringReleaseTimeConstant = 0.325;
+    
+// Exponential saturation curve.
+static double saturate(double x, double k)
+{
+    return 1 - exp(-k * x);
+}
+
+DynamicsCompressorKernel::DynamicsCompressorKernel(double sampleRate)
+    : m_sampleRate(sampleRate)
+    , m_lastPreDelayFrames(DefaultPreDelayFrames)
+    , m_preDelayBufferL(MaxPreDelayFrames)
+    , m_preDelayBufferR(MaxPreDelayFrames)
+    , m_preDelayReadIndex(0)
+    , m_preDelayWriteIndex(DefaultPreDelayFrames)
+{
+    // Initializes most member variables
+    reset();
+    
+    m_meteringReleaseK = discreteTimeConstantForSampleRate(meteringReleaseTimeConstant, sampleRate);
+}
+
+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;
+        m_preDelayBufferL.zero();
+        m_preDelayBufferR.zero();
+        m_preDelayReadIndex = 0;
+        m_preDelayWriteIndex = preDelayFrames;
+    }
+}
+
+void DynamicsCompressorKernel::process(float* sourceL,
+                                       float* destinationL,
+                                       float* sourceR, /* stereo-linked */
+                                       float* destinationR,
+                                       unsigned framesToProcess,
+
+                                       float dbThreshold,
+                                       float dbHeadroom,
+                                       float attackTime,
+                                       float releaseTime,
+                                       float preDelayTime,
+                                       float dbPostGain,
+                                       float effectBlend, /* equal power crossfade */
+
+                                       float releaseZone1,
+                                       float releaseZone2,
+                                       float releaseZone3,
+                                       float releaseZone4
+                                       )
+{
+    bool isStereo = destinationR;
+    float sampleRate = this->sampleRate();
+
+    float dryMix = 1 - effectBlend;
+    float wetMix = effectBlend;
+
+    // Threshold and headroom.
+    double linearThreshold = decibelsToLinear(dbThreshold);
+    double linearHeadroom = decibelsToLinear(dbHeadroom);
+
+    // Makeup gain.
+    double maximum = 1.05 * linearHeadroom * linearThreshold;
+    double kk = (maximum - linearThreshold);
+    double inverseKK = 1 / kk;
+
+    double fullRangeGain = (linearThreshold + kk * saturate(1 - linearThreshold, 1));
+    double fullRangeMakeupGain = 1 / fullRangeGain;
+    // Empirical/perceptual tuning.
+    fullRangeMakeupGain = pow(fullRangeMakeupGain, 0.6);
+
+    float masterLinearGain = decibelsToLinear(dbPostGain) * fullRangeMakeupGain;
+
+    // Attack parameters.
+    attackTime = max(0.001f, attackTime);
+    float attackFrames = attackTime * sampleRate;
+
+    // Release parameters.
+    float releaseFrames = sampleRate * releaseTime;
+    
+    // Detector release time.
+    double satReleaseTime = 0.0025;
+    double satReleaseFrames = satReleaseTime * sampleRate;
+
+    // Create a smooth function which passes through four points.
+
+    // Polynomial of the form
+    // y = a + b*x + c*x^2 + d*x^3 + e*x^4;
+
+    double y1 = releaseFrames * releaseZone1;
+    double y2 = releaseFrames * releaseZone2;
+    double y3 = releaseFrames * releaseZone3;
+    double y4 = releaseFrames * releaseZone4;
+
+    // All of these coefficients were derived for 4th order polynomial curve fitting where the y values
+    // match the evenly spaced x values as follows: (y1 : x == 0, y2 : x == 1, y3 : x == 2, y4 : x == 3)
+    double kA = 0.9999999999999998*y1 + 1.8432219684323923e-16*y2 - 1.9373394351676423e-16*y3 + 8.824516011816245e-18*y4;
+    double kB = -1.5788320352845888*y1 + 2.3305837032074286*y2 - 0.9141194204840429*y3 + 0.1623677525612032*y4;
+    double kC = 0.5334142869106424*y1 - 1.272736789213631*y2 + 0.9258856042207512*y3 - 0.18656310191776226*y4;
+    double kD = 0.08783463138207234*y1 - 0.1694162967925622*y2 + 0.08588057951595272*y3 - 0.00429891410546283*y4;
+    double kE = -0.042416883008123074*y1 + 0.1115693827987602*y2 - 0.09764676325265872*y3 + 0.028494263462021576*y4;
+
+    // x ranges from 0 -> 3       0    1    2   3
+    //                           -15  -10  -5   0db
+
+    // y calculates adaptive release frames depending on the amount of compression.
+
+    setPreDelayTime(preDelayTime);
+    
+    const int nDivisionFrames = 32;
+
+    const int nDivisions = framesToProcess / nDivisionFrames;
+
+    for (int i = 0; i < nDivisions; ++i) {
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        // Calculate desired gain
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+        // Fix gremlins.
+        if (isnan(m_detectorAverage))
+            m_detectorAverage = 1;
+        if (isinf(m_detectorAverage))
+            m_detectorAverage = 1;
+
+        float desiredGain = m_detectorAverage;
+
+        // Pre-warp so we get desiredGain after sin() warp below.
+        double scaledDesiredGain = asin(desiredGain) / (0.5 * piDouble);
+
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        // 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.
+        double compressionDiffDb = linearToDecibels(m_compressorGain / scaledDesiredGain);
+
+        if (isReleasing) {
+            // Release mode - compressionDiffDb should be negative dB
+            m_maxAttackCompressionDiffDb = -1;
+
+            // Fix gremlins.
+            if (isnan(compressionDiffDb))
+                compressionDiffDb = -1;
+            if (isinf(compressionDiffDb))
+                compressionDiffDb = -1;
+
+            // Adaptive release - higher compression (lower compressionDiffDb)  releases faster.
+
+            // Contain within range: -12 -> 0 then scale to go from 0 -> 3
+            double x = compressionDiffDb;
+            x = max(-12., x);
+            x = min(0., x);
+            x = 0.25 * (x + 12);
+
+            // Compute adaptive release curve using 4th order polynomial.
+            // Normal values for the polynomial coefficients would create a monotonically increasing function.
+            double x2 = x * x;
+            double x3 = x2 * x;
+            double x4 = x2 * x2;
+            double releaseFrames = kA + kB * x + kC * x2 + kD * x3 + kE * x4;
+
+#define kSpacingDb 5
+            double dbPerFrame = kSpacingDb / releaseFrames;
+
+            envelopeRate = decibelsToLinear(dbPerFrame);
+        } else {
+            // Attack mode - compressionDiffDb should be positive dB
+
+            // Fix gremlins.
+            if (isnan(compressionDiffDb))
+                compressionDiffDb = 1;
+            if (isinf(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;
+
+            double effAttenDiffDb = max(0.5f, m_maxAttackCompressionDiffDb);
+
+            double x = 0.25 / effAttenDiffDb;
+            envelopeRate = 1 - pow(x, double(1 / attackFrames));
+        }
+
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        // Inner loop - calculate shaped power average - apply compression.
+        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+        {
+            float* delayBufferL = m_preDelayBufferL.data();
+            float* delayBufferR = m_preDelayBufferR.data();
+            int preDelayReadIndex = m_preDelayReadIndex;
+            int preDelayWriteIndex = m_preDelayWriteIndex;
+            float detectorAverage = m_detectorAverage;
+            float compressorGain = m_compressorGain;
+
+            int loopFrames = nDivisionFrames;
+            while (loopFrames--) {
+                float compressorInput;
+                float inputL;
+                float inputR = 0;
+
+                // Predelay signal, computing compression amount from un-delayed version.
+                if (isStereo) {
+                    float undelayedL = *sourceL++;
+                    float undelayedR = *sourceR++;
+
+                    compressorInput = 0.5 * (undelayedL + undelayedR);
+
+                    inputL = delayBufferL[preDelayReadIndex];
+                    inputR = delayBufferR[preDelayReadIndex];
+
+                    delayBufferL[preDelayWriteIndex] = undelayedL;
+                    delayBufferR[preDelayWriteIndex] = undelayedR;
+                } else {
+                    compressorInput = *sourceL++;
+
+                    inputL = delayBufferL[preDelayReadIndex];
+                    delayBufferL[preDelayWriteIndex] = compressorInput;
+                }
+
+                preDelayReadIndex = (preDelayReadIndex + 1) & MaxPreDelayFramesMask;
+                preDelayWriteIndex = (preDelayWriteIndex + 1) & MaxPreDelayFramesMask;
+
+                // Calculate shaped power on undelayed input.
+
+                float scaledInput = compressorInput;
+                double absInput = scaledInput > 0 ? scaledInput : -scaledInput;
+
+                // Put through shaping curve.
+                // This is linear up to the threshold, then exponentially approaches the maximum (headroom amount above threshold).
+                // The transition from the threshold to the exponential portion is smooth (1st derivative matched).
+                double shapedInput = absInput < linearThreshold ? absInput : linearThreshold + kk * saturate(absInput - linearThreshold, inverseKK);
+
+                double attenuation = absInput <= 0.0001 ? 1 : shapedInput / absInput;
+
+                double attenuationDb = -linearToDecibels(attenuation);
+                attenuationDb = max(2., attenuationDb);
+
+                double dbPerFrame = attenuationDb / satReleaseFrames;
+
+                double satReleaseRate = decibelsToLinear(dbPerFrame) - 1;
+
+                bool isRelease = (attenuation > detectorAverage);
+                double rate = isRelease ? satReleaseRate : 1;
+
+                detectorAverage += (attenuation - detectorAverage) * rate;
+                detectorAverage = min(1.0f, detectorAverage);
+
+                // Fix gremlins.
+                if (isnan(detectorAverage))
+                    detectorAverage = 1;
+                if (isinf(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.
+                double postWarpCompressorGain = sin(0.5 * piDouble * compressorGain);
+
+                // Calculate total gain using master gain and effect blend.
+                double totalGain = dryMix + wetMix * masterLinearGain * postWarpCompressorGain;
+
+                // Calculate metering.
+                double dbRealGain = 20 * log10(postWarpCompressorGain);
+                if (dbRealGain < m_meteringGain)
+                    m_meteringGain = dbRealGain;
+                else
+                    m_meteringGain += (dbRealGain - m_meteringGain) * m_meteringReleaseK;
+
+                // Apply final gain.
+                if (isStereo) {
+                    float outputL = inputL;
+                    float outputR = inputR;
+
+                    outputL *= totalGain;
+                    outputR *= totalGain;
+
+                    *destinationL++ = outputL;
+                    *destinationR++ = outputR;
+                } else
+                    *destinationL++ = inputL * totalGain;
+            }
+
+            // Locals back to member variables.
+            m_preDelayReadIndex = preDelayReadIndex;
+            m_preDelayWriteIndex = preDelayWriteIndex;
+            m_detectorAverage = detectorAverage;
+            m_compressorGain = compressorGain;
+        }
+    }
+}
+
+void DynamicsCompressorKernel::reset()
+{
+    m_detectorAverage = 0;
+    m_compressorGain = 1;
+    m_meteringGain = 1;
+
+    // Predelay section.
+    m_preDelayBufferL.zero();
+    m_preDelayBufferR.zero();
+    m_preDelayReadIndex = 0;
+    m_preDelayWriteIndex = DefaultPreDelayFrames;
+
+    m_maxAttackCompressionDiffDb = -1; // uninitialized state
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/DynamicsCompressorKernel.h b/Source/WebCore/platform/audio/DynamicsCompressorKernel.h
new file mode 100644 (file)
index 0000000..a6e70d3
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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.
+ */
+
+#ifndef DynamicsCompressorKernel_h
+#define DynamicsCompressorKernel_h
+
+#include "AudioArray.h"
+
+namespace WebCore {
+
+class DynamicsCompressorKernel {
+public:
+    DynamicsCompressorKernel(double sampleRate);
+
+    // Performs stereo-linked compression.
+    void process(float *sourceL,
+                 float *destinationL,
+                 float *sourceR,
+                 float *destinationR,
+                 unsigned framesToProcess,
+
+                 float dbThreshold,
+                 float dbHeadroom,
+                 float attackTime,
+                 float releaseTime,
+                 float preDelayTime,
+                 float dbPostGain,
+                 float effectBlend,
+
+                 float releaseZone1,
+                 float releaseZone2,
+                 float releaseZone3,
+                 float releaseZone4
+                 );
+
+    void reset();
+
+    unsigned latencyFrames() const { return m_lastPreDelayFrames; }
+
+    float sampleRate() const { return m_sampleRate; }
+
+protected:
+    float m_sampleRate;
+    
+    float m_detectorAverage;
+    float m_compressorGain;
+
+    // Metering
+    float m_meteringReleaseK;
+    float m_meteringGain;
+
+    // Lookahead section.
+    enum { MaxPreDelayFrames = 1024 };
+    enum { MaxPreDelayFramesMask = MaxPreDelayFrames - 1 };
+    enum { DefaultPreDelayFrames = 256 }; // setPreDelayTime() will override this initial value
+    unsigned m_lastPreDelayFrames;
+    void setPreDelayTime(float);
+
+    AudioFloatArray m_preDelayBufferL;
+    AudioFloatArray m_preDelayBufferR;
+    int m_preDelayReadIndex;
+    int m_preDelayWriteIndex;
+
+    float m_maxAttackCompressionDiffDb;
+};
+
+} // namespace WebCore
+
+#endif // DynamicsCompressorKernel_h
diff --git a/Source/WebCore/platform/audio/ZeroPole.cpp b/Source/WebCore/platform/audio/ZeroPole.cpp
new file mode 100644 (file)
index 0000000..9d99a4d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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"
+
+namespace WebCore {
+
+void ZeroPole::process(float *source, float *destination, unsigned framesToProcess)
+{
+    float zero = m_zero;
+    float pole = m_pole;
+
+    // Gain compensation to make 0dB @ 0Hz
+    const float k1 = 1 / (1 - zero);
+    const float k2 = 1 - pole;
+    
+    // Member variables to locals.
+    float lastX = m_lastX;
+    float lastY = m_lastY;
+
+    while (framesToProcess--) {
+        float input = *source++;
+
+        // Zero
+        float output1 = k1 * (input - zero * lastX);
+        lastX = input;
+
+        // Pole
+        float output2 = k2 * output1 + pole * lastY;
+        lastY = output2;
+
+        *destination++ = output2;
+    }
+    
+    // Locals to member variables.
+    m_lastX = lastX;
+    m_lastY = lastY;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/ZeroPole.h b/Source/WebCore/platform/audio/ZeroPole.h
new file mode 100644 (file)
index 0000000..93fd0d6
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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.
+ */
+
+#ifndef ZeroPole_h
+#define ZeroPole_h
+
+namespace WebCore {
+
+// ZeroPole is a simple filter with one zero and one pole.
+
+class ZeroPole {
+public:
+    ZeroPole()
+        : m_zero(0)
+        , m_pole(0)
+        , m_lastX(0)
+        , m_lastY(0)
+    {
+    }
+
+    void process(float *source, float *destination, unsigned framesToProcess);
+
+    // Reset filter state.
+    void reset() { m_lastX = 0; m_lastY = 0; }
+    
+    void setZero(float zero) { m_zero = zero; }
+    void setPole(float pole) { m_pole = pole; }
+    
+    float zero() const { return m_zero; }
+    float pole() const { return m_pole; }
+
+private:
+    float m_zero;
+    float m_pole;
+    float m_lastX;
+    float m_lastY;
+};
+
+} // namespace WebCore
+
+#endif // ZeroPole_h
index 0d23cf584e7737e0b6cb74480557b0331513323b..19c706d5c0c467a6e1002d8bb5e30a02db09e61c 100644 (file)
@@ -42,6 +42,7 @@
 #include "DefaultAudioDestinationNode.h"
 #include "DelayNode.h"
 #include "Document.h"
+#include "DynamicsCompressorNode.h"
 #include "FFTFrame.h"
 #include "HRTFDatabaseLoader.h"
 #include "HRTFPanner.h"
@@ -291,6 +292,13 @@ PassRefPtr<ConvolverNode> AudioContext::createConvolver()
     return ConvolverNode::create(this, m_destinationNode->sampleRate());
 }
 
+PassRefPtr<DynamicsCompressorNode> AudioContext::createDynamicsCompressor()
+{
+    ASSERT(isMainThread());
+    lazyInitialize();
+    return DynamicsCompressorNode::create(this, m_destinationNode->sampleRate());
+}
+
 PassRefPtr<RealtimeAnalyserNode> AudioContext::createAnalyser()
 {
     ASSERT(isMainThread());
index 4f89091f5112be98cdab9f68fccfb7c7926c99cb..666a353e165dc975ac391eed73b8a3c7c89a49a0 100644 (file)
@@ -55,6 +55,7 @@ class Document;
 class LowPass2FilterNode;
 class HighPass2FilterNode;
 class ConvolverNode;
+class DynamicsCompressorNode;
 class RealtimeAnalyserNode;
 class JavaScriptAudioNode;
 
@@ -104,6 +105,7 @@ public:
     PassRefPtr<HighPass2FilterNode> createHighPass2Filter();
     PassRefPtr<AudioPannerNode> createPanner();
     PassRefPtr<ConvolverNode> createConvolver();
+    PassRefPtr<DynamicsCompressorNode> createDynamicsCompressor();    
     PassRefPtr<RealtimeAnalyserNode> createAnalyser();
     PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize);
     PassRefPtr<AudioChannelSplitter> createChannelSplitter();
index 44dd3350ad9a14e9b64050ebfa17684d4564c278..f45d94af82170485a82de15a395a2ee2ee75909e 100644 (file)
@@ -62,6 +62,7 @@ module webaudio {
         HighPass2FilterNode createHighPass2Filter();
         AudioPannerNode createPanner();
         ConvolverNode createConvolver();
+        DynamicsCompressorNode createDynamicsCompressor();
         RealtimeAnalyserNode createAnalyser();
         JavaScriptAudioNode createJavaScriptNode(in unsigned long bufferSize);
 
index 069407ddd0cfe34834c057887f856349fe7c86ee..48f59f680c5c7a44d0d9e30d66931e4983d551a3 100644 (file)
@@ -67,6 +67,7 @@ public:
         NodeTypeChannelSplitter,
         NodeTypeChannelMerger,
         NodeTypeAnalyser,
+        NodeTypeDynamicsCompressor,
         NodeTypeEnd
     };
 
diff --git a/Source/WebCore/webaudio/DynamicsCompressorNode.cpp b/Source/WebCore/webaudio/DynamicsCompressorNode.cpp
new file mode 100644 (file)
index 0000000..22e8cdc
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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 "DynamicsCompressorNode.h"
+
+#include "AudioContext.h"
+#include "AudioNodeInput.h"
+#include "AudioNodeOutput.h"
+#include "DynamicsCompressor.h"
+
+namespace WebCore {
+
+DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* context, double sampleRate)
+    : AudioNode(context, sampleRate)
+{
+    addInput(adoptPtr(new AudioNodeInput(this)));
+    addOutput(adoptPtr(new AudioNodeOutput(this, 2)));
+    
+    setType(NodeTypeDynamicsCompressor);
+    
+    initialize();
+}
+
+DynamicsCompressorNode::~DynamicsCompressorNode()
+{
+    uninitialize();
+}
+
+void DynamicsCompressorNode::process(size_t framesToProcess)
+{
+    AudioBus* outputBus = output(0)->bus();
+    ASSERT(outputBus);
+
+    m_dynamicsCompressor->process(input(0)->bus(), outputBus, framesToProcess);
+}
+
+void DynamicsCompressorNode::reset()
+{
+    m_dynamicsCompressor->reset();
+}
+
+void DynamicsCompressorNode::initialize()
+{
+    if (isInitialized())
+        return;
+
+    AudioNode::initialize();    
+    m_dynamicsCompressor = adoptPtr(new DynamicsCompressor(true, sampleRate()));
+}
+
+void DynamicsCompressorNode::uninitialize()
+{
+    if (!isInitialized())
+        return;
+
+    m_dynamicsCompressor.clear();
+    AudioNode::uninitialize();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/webaudio/DynamicsCompressorNode.h b/Source/WebCore/webaudio/DynamicsCompressorNode.h
new file mode 100644 (file)
index 0000000..7ae75ea
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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.
+ */
+
+#ifndef DynamicsCompressorNode_h
+#define DynamicsCompressorNode_h
+
+#include "AudioNode.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class DynamicsCompressor;
+    
+class DynamicsCompressorNode : public AudioNode {
+public:
+    static PassRefPtr<DynamicsCompressorNode> create(AudioContext* context, double sampleRate)
+    {
+        return adoptRef(new DynamicsCompressorNode(context, sampleRate));      
+    }
+    
+    virtual ~DynamicsCompressorNode();
+    
+    // AudioNode
+    virtual void process(size_t framesToProcess);
+    virtual void reset();
+    virtual void initialize();
+    virtual void uninitialize();
+
+private:
+    DynamicsCompressorNode(AudioContext*, double sampleRate);
+
+    OwnPtr<DynamicsCompressor> m_dynamicsCompressor;
+};
+
+} // namespace WebCore
+
+#endif // DynamicsCompressorNode_h
diff --git a/Source/WebCore/webaudio/DynamicsCompressorNode.idl b/Source/WebCore/webaudio/DynamicsCompressorNode.idl
new file mode 100644 (file)
index 0000000..74997ea
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * 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.
+ */
+
+module audio {
+    interface [
+        Conditional=WEB_AUDIO,
+        GenerateToJS
+    ] DynamicsCompressorNode : AudioNode {
+    };
+}