Title: [111227] trunk
Revision
111227
Author
[email protected]
Date
2012-03-19 13:19:46 -0700 (Mon, 19 Mar 2012)

Log Message

ConvolverNode should not incur processing latency
https://bugs.webkit.org/show_bug.cgi?id=75564

Patch by Xingnan Wang <[email protected]> on 2012-03-19
Reviewed by Chris Rogers.

Source/WebCore:

Add the DirectConvolver instead of FFTConvolver for the processing of the leading portion of impulse response.

* WebCore.gypi:
* platform/audio/DirectConvolver.cpp: Added.
(WebCore):
(WebCore::DirectConvolver::DirectConvolver):
(WebCore::DirectConvolver::process):
(WebCore::DirectConvolver::reset):
* platform/audio/DirectConvolver.h: Added.
(WebCore):
(DirectConvolver):
(WebCore::DirectConvolver::convolveSize):
* platform/audio/ReverbConvolver.cpp:
(WebCore::ReverbConvolver::ReverbConvolver):
* platform/audio/ReverbConvolver.h:
* platform/audio/ReverbConvolverStage.cpp:
(WebCore::ReverbConvolverStage::ReverbConvolverStage):
(WebCore::ReverbConvolverStage::process):
(WebCore::ReverbConvolverStage::reset):
* platform/audio/ReverbConvolverStage.h:
(WebCore):
(ReverbConvolverStage):

LayoutTests:

No need to check the initial silent part because the latency issue of ConvolverNode is fixed.

* webaudio/convolution-mono-mono-expected.txt:
* webaudio/resources/convolution-testing.js:
(checkTriangularPulse):
(checkTail1):
(checkConvolvedResult.return.var):
(checkConvolvedResult):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (111226 => 111227)


--- trunk/LayoutTests/ChangeLog	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/LayoutTests/ChangeLog	2012-03-19 20:19:46 UTC (rev 111227)
@@ -1,3 +1,19 @@
+2012-03-19  Xingnan Wang  <[email protected]>
+
+        ConvolverNode should not incur processing latency
+        https://bugs.webkit.org/show_bug.cgi?id=75564
+
+        Reviewed by Chris Rogers.
+
+        No need to check the initial silent part because the latency issue of ConvolverNode is fixed.
+
+        * webaudio/convolution-mono-mono-expected.txt:
+        * webaudio/resources/convolution-testing.js:
+        (checkTriangularPulse):
+        (checkTail1):
+        (checkConvolvedResult.return.var):
+        (checkConvolvedResult):
+
 2012-03-19  Joshua Bell  <[email protected]>
 
         IndexedDB: Test cleanup - don't create transactions w/in transaction callback

Modified: trunk/LayoutTests/webaudio/convolution-mono-mono-expected.txt (111226 => 111227)


--- trunk/LayoutTests/webaudio/convolution-mono-mono-expected.txt	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/LayoutTests/webaudio/convolution-mono-mono-expected.txt	2012-03-19 20:19:46 UTC (rev 111227)
@@ -2,7 +2,6 @@
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
-PASS Initial latency of convolver is silent.
 PASS Triangular portion of convolution is correct.
 PASS First part of tail of convolution is sufficiently small.
 PASS Rendered signal after tail of convolution is silent.

Modified: trunk/LayoutTests/webaudio/resources/convolution-testing.js (111226 => 111227)


--- trunk/LayoutTests/webaudio/resources/convolution-testing.js	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/LayoutTests/webaudio/resources/convolution-testing.js	2012-03-19 20:19:46 UTC (rev 111227)
@@ -4,11 +4,6 @@
 var pulseLengthSeconds = 1;
 var pulseLengthFrames = pulseLengthSeconds * sampleRate;
 
-// The convolver has a latency of 128 samples in the implementation.
-// We need to take this into account when verifying the output of the
-// convolver. See https://bugs.webkit.org/show_bug.cgi?id=75564.
-var convolveDelaySamples = 128;
-
 function createSquarePulseBuffer(context, sampleFrameLength) {
     var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
 
@@ -41,27 +36,6 @@
     return audioBuffer;
 }
 
-// Verify that the initial latency of the convolver is exactly zero.
-// Return true if so.
-function checkLatency(data) {
-    var isZero = true;
-
-    for (var i = 0; i < convolveDelaySamples; ++i) {
-        if (data[i] != 0) {
-            isZero = false;
-            break;
-        }
-    }
-
-    if (isZero) {
-        testPassed("Initial latency of convolver is silent.");
-    } else {
-        testFailed("Initial latency of convolver is not silent.");
-    }
-
-    return isZero;
-}
-
 function log10(x) {
   return Math.log(x)/Math.LN10;
 }
@@ -79,7 +53,7 @@
     var maxDeltaIndex = 0;
 
     for (var i = 0; i < reference.length; ++i) {
-        var diff = rendered[i + convolveDelaySamples] - reference[i];
+        var diff = rendered[i] - reference[i];
         var x = Math.abs(diff);
         if (x > maxDelta) {
             maxDelta = x;
@@ -111,7 +85,7 @@
     var isZero = true;
     var tail1Max = 0;
 
-    for (var i = reference.length + convolveDelaySamples; i < reference.length + breakpoint; ++i) {
+    for (var i = reference.length; i < reference.length + breakpoint; ++i) {
         var mag = Math.abs(data[i]);
         if (mag > tail1Max) {
             tail1Max = mag;
@@ -173,11 +147,6 @@
     
         var success = true;
     
-        // Verify the initial part is exactly zero because of the
-        // latency in the convolver.
-
-        success = success && checkLatency(renderedData);
-
         // Verify the triangular pulse is actually triangular.
 
         success = success && checkTriangularPulse(renderedData, referenceData);

Modified: trunk/Source/WebCore/ChangeLog (111226 => 111227)


--- trunk/Source/WebCore/ChangeLog	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/ChangeLog	2012-03-19 20:19:46 UTC (rev 111227)
@@ -1,3 +1,33 @@
+2012-03-19  Xingnan Wang  <[email protected]>
+
+        ConvolverNode should not incur processing latency
+        https://bugs.webkit.org/show_bug.cgi?id=75564
+
+        Reviewed by Chris Rogers.
+
+        Add the DirectConvolver instead of FFTConvolver for the processing of the leading portion of impulse response.
+
+        * WebCore.gypi:
+        * platform/audio/DirectConvolver.cpp: Added.
+        (WebCore):
+        (WebCore::DirectConvolver::DirectConvolver):
+        (WebCore::DirectConvolver::process):
+        (WebCore::DirectConvolver::reset):
+        * platform/audio/DirectConvolver.h: Added.
+        (WebCore):
+        (DirectConvolver):
+        (WebCore::DirectConvolver::convolveSize):
+        * platform/audio/ReverbConvolver.cpp:
+        (WebCore::ReverbConvolver::ReverbConvolver):
+        * platform/audio/ReverbConvolver.h:
+        * platform/audio/ReverbConvolverStage.cpp:
+        (WebCore::ReverbConvolverStage::ReverbConvolverStage):
+        (WebCore::ReverbConvolverStage::process):
+        (WebCore::ReverbConvolverStage::reset):
+        * platform/audio/ReverbConvolverStage.h:
+        (WebCore):
+        (ReverbConvolverStage):
+
 2012-03-19  Anders Carlsson  <[email protected]>
 
         Find in page highlights get out of place when scrolling

Modified: trunk/Source/WebCore/GNUmakefile.list.am (111226 => 111227)


--- trunk/Source/WebCore/GNUmakefile.list.am	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2012-03-19 20:19:46 UTC (rev 111227)
@@ -5481,6 +5481,8 @@
 	Source/WebCore/platform/audio/Cone.cpp \
 	Source/WebCore/platform/audio/Cone.h \
 	Source/WebCore/platform/audio/DenormalDisabler.h \
+	Source/WebCore/platform/audio/DirectConvolver.cpp \
+	Source/WebCore/platform/audio/DirectConvolver.h \
 	Source/WebCore/platform/audio/Distance.cpp \
 	Source/WebCore/platform/audio/Distance.h \
 	Source/WebCore/platform/audio/DynamicsCompressor.h \

Modified: trunk/Source/WebCore/WebCore.gypi (111226 => 111227)


--- trunk/Source/WebCore/WebCore.gypi	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/WebCore.gypi	2012-03-19 20:19:46 UTC (rev 111227)
@@ -3052,6 +3052,8 @@
             'platform/audio/Cone.cpp',
             'platform/audio/Cone.h',
             'platform/audio/DenormalDisabler.h',
+            'platform/audio/DirectConvolver.cpp',
+            'platform/audio/DirectConvolver.h',
             'platform/audio/Distance.cpp',
             'platform/audio/Distance.h',
             'platform/audio/DynamicsCompressor.cpp',

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (111226 => 111227)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2012-03-19 20:19:46 UTC (rev 111227)
@@ -6289,6 +6289,8 @@
 		FDA3E95A134A49EF008D4B5A /* OfflineAudioCompletionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = FDA3E956134A49EF008D4B5A /* OfflineAudioCompletionEvent.h */; };
 		FDA3E95B134A49EF008D4B5A /* OfflineAudioDestinationNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FDA3E957134A49EF008D4B5A /* OfflineAudioDestinationNode.cpp */; };
 		FDA3E95C134A49EF008D4B5A /* OfflineAudioDestinationNode.h in Headers */ = {isa = PBXBuildFile; fileRef = FDA3E958134A49EF008D4B5A /* OfflineAudioDestinationNode.h */; };
+		FDAF19981513D131008DB0C3 /* DirectConvolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FDAF19961513D131008DB0C3 /* DirectConvolver.cpp */; };
+		FDAF19991513D131008DB0C3 /* DirectConvolver.h in Headers */ = {isa = PBXBuildFile; fileRef = FDAF19971513D131008DB0C3 /* DirectConvolver.h */; };
 		FDB1700514A2BAB200A2B5D9 /* MultiChannelResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FDB1700314A2BAB200A2B5D9 /* MultiChannelResampler.cpp */; };
 		FDB1700614A2BAB200A2B5D9 /* MultiChannelResampler.h in Headers */ = {isa = PBXBuildFile; fileRef = FDB1700414A2BAB200A2B5D9 /* MultiChannelResampler.h */; };
 		FDC54F041399B0DA008D9117 /* BiquadFilterNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FDC54F011399B0DA008D9117 /* BiquadFilterNode.cpp */; };
@@ -13448,6 +13450,8 @@
 		FDA3E957134A49EF008D4B5A /* OfflineAudioDestinationNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OfflineAudioDestinationNode.cpp; sourceTree = "<group>"; };
 		FDA3E958134A49EF008D4B5A /* OfflineAudioDestinationNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OfflineAudioDestinationNode.h; sourceTree = "<group>"; };
 		FDA3E95D134A49FF008D4B5A /* OfflineAudioCompletionEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = OfflineAudioCompletionEvent.idl; sourceTree = "<group>"; };
+		FDAF19961513D131008DB0C3 /* DirectConvolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DirectConvolver.cpp; sourceTree = "<group>"; };
+		FDAF19971513D131008DB0C3 /* DirectConvolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectConvolver.h; sourceTree = "<group>"; };
 		FDB1700314A2BAB200A2B5D9 /* MultiChannelResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiChannelResampler.cpp; sourceTree = "<group>"; };
 		FDB1700414A2BAB200A2B5D9 /* MultiChannelResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MultiChannelResampler.h; sourceTree = "<group>"; };
 		FDC54F011399B0DA008D9117 /* BiquadFilterNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BiquadFilterNode.cpp; sourceTree = "<group>"; };
@@ -21288,6 +21292,8 @@
 				FD31605812B026F700C1A359 /* Cone.cpp */,
 				FD31605912B026F700C1A359 /* Cone.h */,
 				FD1660A413787C6D001FFA7B /* DenormalDisabler.h */,
+				FDAF19961513D131008DB0C3 /* DirectConvolver.cpp */,
+				FDAF19971513D131008DB0C3 /* DirectConvolver.h */,
 				FD31605A12B026F700C1A359 /* Distance.cpp */,
 				FD31605B12B026F700C1A359 /* Distance.h */,
 				FD6ED2C5136B8E66003CF072 /* DynamicsCompressor.cpp */,
@@ -21789,6 +21795,7 @@
 				59309A1311F4AE6A00250603 /* DeviceOrientationClientMock.h in Headers */,
 				59A8F1D611A69513001AC34A /* DeviceOrientationController.h in Headers */,
 				59A85EA4119D68EC00DEF1EF /* DeviceOrientationEvent.h in Headers */,
+				FDAF19991513D131008DB0C3 /* DirectConvolver.h in Headers */,
 				89878553122CA064003AABDA /* DirectoryEntry.h in Headers */,
 				893C48011248BD3A002B3D86 /* DirectoryEntrySync.h in Headers */,
 				89878555122CA064003AABDA /* DirectoryReader.h in Headers */,
@@ -25228,6 +25235,7 @@
 				59309A1111F4AE5800250603 /* DeviceOrientationClientMock.cpp in Sources */,
 				59A8F1D411A69508001AC34A /* DeviceOrientationController.cpp in Sources */,
 				59A85EA2119D68D900DEF1EF /* DeviceOrientationEvent.cpp in Sources */,
+				FDAF19981513D131008DB0C3 /* DirectConvolver.cpp in Sources */,
 				89878552122CA064003AABDA /* DirectoryEntry.cpp in Sources */,
 				893C48001248BD3A002B3D86 /* DirectoryEntrySync.cpp in Sources */,
 				89878554122CA064003AABDA /* DirectoryReader.cpp in Sources */,

Added: trunk/Source/WebCore/platform/audio/DirectConvolver.cpp (0 => 111227)


--- trunk/Source/WebCore/platform/audio/DirectConvolver.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/audio/DirectConvolver.cpp	2012-03-19 20:19:46 UTC (rev 111227)
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2012 Intel 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 "DirectConvolver.h"
+
+#include "VectorMath.h"
+
+namespace WebCore {
+
+using namespace VectorMath;
+    
+DirectConvolver::DirectConvolver(size_t inputBlockSize)
+    : m_inputBlockSize(inputBlockSize)
+    , m_inputBuffer(inputBlockSize * 2)
+{
+}
+
+void DirectConvolver::process(AudioFloatArray* convolutionKernel, const float* sourceP, float* destP, size_t framesToProcess)
+{
+    // FIXME: Optimize for IPP, reverb function in IPP library can be used here.
+    // https://bugs.webkit.org/show_bug.cgi?id=80255
+    // FIXME: Optimize for DARWIN, conv() function in Accelerate.framework can be used here.
+    // https://bugs.webkit.org/show_bug.cgi?id=80256
+
+    ASSERT(framesToProcess == m_inputBlockSize);
+    if (framesToProcess != m_inputBlockSize)
+        return;
+
+    // Only support kernelSize <= m_inputBlockSize
+    size_t kernelSize = convolutionKernel->size();
+    ASSERT(kernelSize <= m_inputBlockSize);
+    if (kernelSize > m_inputBlockSize)
+        return;
+
+    float* kernelP = convolutionKernel->data();
+
+    float* inputP = m_inputBuffer.data() + m_inputBlockSize;
+
+    // Sanity check
+    bool isCopyGood = kernelP && sourceP && destP && m_inputBuffer.data();
+    ASSERT(isCopyGood);
+    if (!isCopyGood)
+        return;
+
+    // Copy samples to 2nd half of input buffer.
+    memcpy(inputP, sourceP, sizeof(float) * framesToProcess);
+
+    // FIXME: The macro can be further optimized to avoid pipeline stalls. One possibility is to maintain 4 separate sums and change the macro to CONVOLVE_FOUR_SAMPLES.
+#define CONVOLVE_ONE_SAMPLE             \
+    sum += inputP[i - j] * kernelP[j];  \
+    j++;
+
+    size_t i = 0;
+    while (i < framesToProcess) {
+        size_t j = 0;
+        float sum = 0;
+        
+        // FIXME: SSE optimization may be applied here.
+        if (kernelSize == 32) {
+            CONVOLVE_ONE_SAMPLE // 1
+            CONVOLVE_ONE_SAMPLE // 2
+            CONVOLVE_ONE_SAMPLE // 3
+            CONVOLVE_ONE_SAMPLE // 4
+            CONVOLVE_ONE_SAMPLE // 5
+            CONVOLVE_ONE_SAMPLE // 6
+            CONVOLVE_ONE_SAMPLE // 7
+            CONVOLVE_ONE_SAMPLE // 8
+            CONVOLVE_ONE_SAMPLE // 9
+            CONVOLVE_ONE_SAMPLE // 10
+
+            CONVOLVE_ONE_SAMPLE // 11
+            CONVOLVE_ONE_SAMPLE // 12
+            CONVOLVE_ONE_SAMPLE // 13
+            CONVOLVE_ONE_SAMPLE // 14
+            CONVOLVE_ONE_SAMPLE // 15
+            CONVOLVE_ONE_SAMPLE // 16
+            CONVOLVE_ONE_SAMPLE // 17
+            CONVOLVE_ONE_SAMPLE // 18
+            CONVOLVE_ONE_SAMPLE // 19
+            CONVOLVE_ONE_SAMPLE // 20
+
+            CONVOLVE_ONE_SAMPLE // 21
+            CONVOLVE_ONE_SAMPLE // 22
+            CONVOLVE_ONE_SAMPLE // 23
+            CONVOLVE_ONE_SAMPLE // 24
+            CONVOLVE_ONE_SAMPLE // 25
+            CONVOLVE_ONE_SAMPLE // 26
+            CONVOLVE_ONE_SAMPLE // 27
+            CONVOLVE_ONE_SAMPLE // 28
+            CONVOLVE_ONE_SAMPLE // 29
+            CONVOLVE_ONE_SAMPLE // 30
+
+            CONVOLVE_ONE_SAMPLE // 31
+            CONVOLVE_ONE_SAMPLE // 32
+
+        } else if (kernelSize == 64) {
+            CONVOLVE_ONE_SAMPLE // 1
+            CONVOLVE_ONE_SAMPLE // 2
+            CONVOLVE_ONE_SAMPLE // 3
+            CONVOLVE_ONE_SAMPLE // 4
+            CONVOLVE_ONE_SAMPLE // 5
+            CONVOLVE_ONE_SAMPLE // 6
+            CONVOLVE_ONE_SAMPLE // 7
+            CONVOLVE_ONE_SAMPLE // 8
+            CONVOLVE_ONE_SAMPLE // 9
+            CONVOLVE_ONE_SAMPLE // 10
+
+            CONVOLVE_ONE_SAMPLE // 11
+            CONVOLVE_ONE_SAMPLE // 12
+            CONVOLVE_ONE_SAMPLE // 13
+            CONVOLVE_ONE_SAMPLE // 14
+            CONVOLVE_ONE_SAMPLE // 15
+            CONVOLVE_ONE_SAMPLE // 16
+            CONVOLVE_ONE_SAMPLE // 17
+            CONVOLVE_ONE_SAMPLE // 18
+            CONVOLVE_ONE_SAMPLE // 19
+            CONVOLVE_ONE_SAMPLE // 20
+
+            CONVOLVE_ONE_SAMPLE // 21
+            CONVOLVE_ONE_SAMPLE // 22
+            CONVOLVE_ONE_SAMPLE // 23
+            CONVOLVE_ONE_SAMPLE // 24
+            CONVOLVE_ONE_SAMPLE // 25
+            CONVOLVE_ONE_SAMPLE // 26
+            CONVOLVE_ONE_SAMPLE // 27
+            CONVOLVE_ONE_SAMPLE // 28
+            CONVOLVE_ONE_SAMPLE // 29
+            CONVOLVE_ONE_SAMPLE // 30
+
+            CONVOLVE_ONE_SAMPLE // 31
+            CONVOLVE_ONE_SAMPLE // 32
+            CONVOLVE_ONE_SAMPLE // 33
+            CONVOLVE_ONE_SAMPLE // 34
+            CONVOLVE_ONE_SAMPLE // 35
+            CONVOLVE_ONE_SAMPLE // 36
+            CONVOLVE_ONE_SAMPLE // 37
+            CONVOLVE_ONE_SAMPLE // 38
+            CONVOLVE_ONE_SAMPLE // 39
+            CONVOLVE_ONE_SAMPLE // 40
+
+            CONVOLVE_ONE_SAMPLE // 41
+            CONVOLVE_ONE_SAMPLE // 42
+            CONVOLVE_ONE_SAMPLE // 43
+            CONVOLVE_ONE_SAMPLE // 44
+            CONVOLVE_ONE_SAMPLE // 45
+            CONVOLVE_ONE_SAMPLE // 46
+            CONVOLVE_ONE_SAMPLE // 47
+            CONVOLVE_ONE_SAMPLE // 48
+            CONVOLVE_ONE_SAMPLE // 49
+            CONVOLVE_ONE_SAMPLE // 50
+
+            CONVOLVE_ONE_SAMPLE // 51
+            CONVOLVE_ONE_SAMPLE // 52
+            CONVOLVE_ONE_SAMPLE // 53
+            CONVOLVE_ONE_SAMPLE // 54
+            CONVOLVE_ONE_SAMPLE // 55
+            CONVOLVE_ONE_SAMPLE // 56
+            CONVOLVE_ONE_SAMPLE // 57
+            CONVOLVE_ONE_SAMPLE // 58
+            CONVOLVE_ONE_SAMPLE // 59
+            CONVOLVE_ONE_SAMPLE // 60
+
+            CONVOLVE_ONE_SAMPLE // 61
+            CONVOLVE_ONE_SAMPLE // 62
+            CONVOLVE_ONE_SAMPLE // 63
+            CONVOLVE_ONE_SAMPLE // 64
+
+        } else if (kernelSize == 128) {
+            CONVOLVE_ONE_SAMPLE // 1
+            CONVOLVE_ONE_SAMPLE // 2
+            CONVOLVE_ONE_SAMPLE // 3
+            CONVOLVE_ONE_SAMPLE // 4
+            CONVOLVE_ONE_SAMPLE // 5
+            CONVOLVE_ONE_SAMPLE // 6
+            CONVOLVE_ONE_SAMPLE // 7
+            CONVOLVE_ONE_SAMPLE // 8
+            CONVOLVE_ONE_SAMPLE // 9
+            CONVOLVE_ONE_SAMPLE // 10
+
+            CONVOLVE_ONE_SAMPLE // 11
+            CONVOLVE_ONE_SAMPLE // 12
+            CONVOLVE_ONE_SAMPLE // 13
+            CONVOLVE_ONE_SAMPLE // 14
+            CONVOLVE_ONE_SAMPLE // 15
+            CONVOLVE_ONE_SAMPLE // 16
+            CONVOLVE_ONE_SAMPLE // 17
+            CONVOLVE_ONE_SAMPLE // 18
+            CONVOLVE_ONE_SAMPLE // 19
+            CONVOLVE_ONE_SAMPLE // 20
+
+            CONVOLVE_ONE_SAMPLE // 21
+            CONVOLVE_ONE_SAMPLE // 22
+            CONVOLVE_ONE_SAMPLE // 23
+            CONVOLVE_ONE_SAMPLE // 24
+            CONVOLVE_ONE_SAMPLE // 25
+            CONVOLVE_ONE_SAMPLE // 26
+            CONVOLVE_ONE_SAMPLE // 27
+            CONVOLVE_ONE_SAMPLE // 28
+            CONVOLVE_ONE_SAMPLE // 29
+            CONVOLVE_ONE_SAMPLE // 30
+
+            CONVOLVE_ONE_SAMPLE // 31
+            CONVOLVE_ONE_SAMPLE // 32
+            CONVOLVE_ONE_SAMPLE // 33
+            CONVOLVE_ONE_SAMPLE // 34
+            CONVOLVE_ONE_SAMPLE // 35
+            CONVOLVE_ONE_SAMPLE // 36
+            CONVOLVE_ONE_SAMPLE // 37
+            CONVOLVE_ONE_SAMPLE // 38
+            CONVOLVE_ONE_SAMPLE // 39
+            CONVOLVE_ONE_SAMPLE // 40
+
+            CONVOLVE_ONE_SAMPLE // 41
+            CONVOLVE_ONE_SAMPLE // 42
+            CONVOLVE_ONE_SAMPLE // 43
+            CONVOLVE_ONE_SAMPLE // 44
+            CONVOLVE_ONE_SAMPLE // 45
+            CONVOLVE_ONE_SAMPLE // 46
+            CONVOLVE_ONE_SAMPLE // 47
+            CONVOLVE_ONE_SAMPLE // 48
+            CONVOLVE_ONE_SAMPLE // 49
+            CONVOLVE_ONE_SAMPLE // 50
+
+            CONVOLVE_ONE_SAMPLE // 51
+            CONVOLVE_ONE_SAMPLE // 52
+            CONVOLVE_ONE_SAMPLE // 53
+            CONVOLVE_ONE_SAMPLE // 54
+            CONVOLVE_ONE_SAMPLE // 55
+            CONVOLVE_ONE_SAMPLE // 56
+            CONVOLVE_ONE_SAMPLE // 57
+            CONVOLVE_ONE_SAMPLE // 58
+            CONVOLVE_ONE_SAMPLE // 59
+            CONVOLVE_ONE_SAMPLE // 60
+
+            CONVOLVE_ONE_SAMPLE // 61
+            CONVOLVE_ONE_SAMPLE // 62
+            CONVOLVE_ONE_SAMPLE // 63
+            CONVOLVE_ONE_SAMPLE // 64
+            CONVOLVE_ONE_SAMPLE // 65
+            CONVOLVE_ONE_SAMPLE // 66
+            CONVOLVE_ONE_SAMPLE // 67
+            CONVOLVE_ONE_SAMPLE // 68
+            CONVOLVE_ONE_SAMPLE // 69
+            CONVOLVE_ONE_SAMPLE // 70
+
+            CONVOLVE_ONE_SAMPLE // 71
+            CONVOLVE_ONE_SAMPLE // 72
+            CONVOLVE_ONE_SAMPLE // 73
+            CONVOLVE_ONE_SAMPLE // 74
+            CONVOLVE_ONE_SAMPLE // 75
+            CONVOLVE_ONE_SAMPLE // 76
+            CONVOLVE_ONE_SAMPLE // 77
+            CONVOLVE_ONE_SAMPLE // 78
+            CONVOLVE_ONE_SAMPLE // 79
+            CONVOLVE_ONE_SAMPLE // 80
+
+            CONVOLVE_ONE_SAMPLE // 81
+            CONVOLVE_ONE_SAMPLE // 82
+            CONVOLVE_ONE_SAMPLE // 83
+            CONVOLVE_ONE_SAMPLE // 84
+            CONVOLVE_ONE_SAMPLE // 85
+            CONVOLVE_ONE_SAMPLE // 86
+            CONVOLVE_ONE_SAMPLE // 87
+            CONVOLVE_ONE_SAMPLE // 88
+            CONVOLVE_ONE_SAMPLE // 89
+            CONVOLVE_ONE_SAMPLE // 90
+
+            CONVOLVE_ONE_SAMPLE // 91
+            CONVOLVE_ONE_SAMPLE // 92
+            CONVOLVE_ONE_SAMPLE // 93
+            CONVOLVE_ONE_SAMPLE // 94
+            CONVOLVE_ONE_SAMPLE // 95
+            CONVOLVE_ONE_SAMPLE // 96
+            CONVOLVE_ONE_SAMPLE // 97
+            CONVOLVE_ONE_SAMPLE // 98
+            CONVOLVE_ONE_SAMPLE // 99
+            CONVOLVE_ONE_SAMPLE // 100
+
+            CONVOLVE_ONE_SAMPLE // 101
+            CONVOLVE_ONE_SAMPLE // 102
+            CONVOLVE_ONE_SAMPLE // 103
+            CONVOLVE_ONE_SAMPLE // 104
+            CONVOLVE_ONE_SAMPLE // 105
+            CONVOLVE_ONE_SAMPLE // 106
+            CONVOLVE_ONE_SAMPLE // 107
+            CONVOLVE_ONE_SAMPLE // 108
+            CONVOLVE_ONE_SAMPLE // 109
+            CONVOLVE_ONE_SAMPLE // 110
+
+            CONVOLVE_ONE_SAMPLE // 111
+            CONVOLVE_ONE_SAMPLE // 112
+            CONVOLVE_ONE_SAMPLE // 113
+            CONVOLVE_ONE_SAMPLE // 114
+            CONVOLVE_ONE_SAMPLE // 115
+            CONVOLVE_ONE_SAMPLE // 116
+            CONVOLVE_ONE_SAMPLE // 117
+            CONVOLVE_ONE_SAMPLE // 118
+            CONVOLVE_ONE_SAMPLE // 119
+            CONVOLVE_ONE_SAMPLE // 120
+
+            CONVOLVE_ONE_SAMPLE // 121
+            CONVOLVE_ONE_SAMPLE // 122
+            CONVOLVE_ONE_SAMPLE // 123
+            CONVOLVE_ONE_SAMPLE // 124
+            CONVOLVE_ONE_SAMPLE // 125
+            CONVOLVE_ONE_SAMPLE // 126
+            CONVOLVE_ONE_SAMPLE // 127
+            CONVOLVE_ONE_SAMPLE // 128
+        } else {
+            while (j < kernelSize) {
+                // Non-optimized using actual while loop.
+                CONVOLVE_ONE_SAMPLE
+            }
+        }
+        destP[i++] = sum;
+    }
+
+    // Copy 2nd half of input buffer to 1st half.
+    memcpy(m_inputBuffer.data(), inputP, sizeof(float) * framesToProcess);
+}
+
+void DirectConvolver::reset()
+{
+    m_inputBuffer.zero();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)

Added: trunk/Source/WebCore/platform/audio/DirectConvolver.h (0 => 111227)


--- trunk/Source/WebCore/platform/audio/DirectConvolver.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/audio/DirectConvolver.h	2012-03-19 20:19:46 UTC (rev 111227)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Intel 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 DirectConvolver_h
+#define DirectConvolver_h
+
+#include "AudioArray.h"
+
+namespace WebCore {
+
+class DirectConvolver {
+public:
+    DirectConvolver(size_t inputBlockSize);
+
+    void process(AudioFloatArray* convolutionKernel, const float* sourceP, float* destP, size_t framesToProcess);
+
+    void reset();
+
+private:
+    size_t m_inputBlockSize;
+
+    AudioFloatArray m_inputBuffer;
+};
+
+} // namespace WebCore
+
+#endif // DirectConvolver_h

Modified: trunk/Source/WebCore/platform/audio/FFTConvolver.cpp (111226 => 111227)


--- trunk/Source/WebCore/platform/audio/FFTConvolver.cpp	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/platform/audio/FFTConvolver.cpp	2012-03-19 20:19:46 UTC (rev 111227)
@@ -49,53 +49,63 @@
 
 void FFTConvolver::process(FFTFrame* fftKernel, const float* sourceP, float* destP, size_t framesToProcess)
 {
-    // FIXME: make so framesToProcess is not required to fit evenly into fftSize/2
+    size_t halfSize = fftSize() / 2;
 
-    // Copy samples to input buffer (note contraint above!)
-    float* inputP = m_inputBuffer.data();
-
-    // Sanity check
-    bool isCopyGood1 = sourceP && inputP && m_readWriteIndex + framesToProcess <= m_inputBuffer.size();
-    ASSERT(isCopyGood1);
-    if (!isCopyGood1)
+    // framesToProcess must be an exact multiple of halfSize,
+    // or halfSize is a multiple of framesToProcess when halfSize > framesToProcess.
+    bool isGood = !(halfSize % framesToProcess && framesToProcess % halfSize);
+    ASSERT(isGood);
+    if (!isGood)
         return;
-    
-    memcpy(inputP + m_readWriteIndex, sourceP, sizeof(float) * framesToProcess);
 
-    // Copy samples from output buffer
-    float* outputP = m_outputBuffer.data();
+    size_t numberOfDivisions = halfSize <= framesToProcess ? (framesToProcess / halfSize) : 1;
+    size_t divisionSize = numberOfDivisions == 1 ? framesToProcess : halfSize;
 
-    // Sanity check
-    bool isCopyGood2 = destP && outputP && m_readWriteIndex + framesToProcess <= m_outputBuffer.size();
-    ASSERT(isCopyGood2);
-    if (!isCopyGood2)
-        return;
+    for (size_t i = 0; i < numberOfDivisions; ++i, sourceP += divisionSize, destP += divisionSize) {
+        // Copy samples to input buffer (note contraint above!)
+        float* inputP = m_inputBuffer.data();
 
-    memcpy(destP, outputP + m_readWriteIndex, sizeof(float) * framesToProcess);
-    m_readWriteIndex += framesToProcess;
+        // Sanity check
+        bool isCopyGood1 = sourceP && inputP && m_readWriteIndex + divisionSize <= m_inputBuffer.size();
+        ASSERT(isCopyGood1);
+        if (!isCopyGood1)
+            return;
 
+        memcpy(inputP + m_readWriteIndex, sourceP, sizeof(float) * divisionSize);
 
-    // Check if it's time to perform the next FFT
-    size_t halfSize = fftSize() / 2;
-    if (m_readWriteIndex == halfSize) {
-        // The input buffer is now filled (get frequency-domain version)
-        m_frame.doFFT(m_inputBuffer.data());
-        m_frame.multiply(*fftKernel);
-        m_frame.doInverseFFT(m_outputBuffer.data());
+        // Copy samples from output buffer
+        float* outputP = m_outputBuffer.data();
 
-        // Overlap-add 1st half from previous time
-        vadd(m_outputBuffer.data(), 1, m_lastOverlapBuffer.data(), 1, m_outputBuffer.data(), 1, halfSize);
-
-        // Finally, save 2nd half of result
-        bool isCopyGood3 = m_outputBuffer.size() == 2 * halfSize && m_lastOverlapBuffer.size() == halfSize;
-        ASSERT(isCopyGood3);
-        if (!isCopyGood3)
+        // Sanity check
+        bool isCopyGood2 = destP && outputP && m_readWriteIndex + divisionSize <= m_outputBuffer.size();
+        ASSERT(isCopyGood2);
+        if (!isCopyGood2)
             return;
-        
-        memcpy(m_lastOverlapBuffer.data(), m_outputBuffer.data() + halfSize, sizeof(float) * halfSize);
 
-        // Reset index back to start for next time
-        m_readWriteIndex = 0;
+        memcpy(destP, outputP + m_readWriteIndex, sizeof(float) * divisionSize);
+        m_readWriteIndex += divisionSize;
+
+        // Check if it's time to perform the next FFT
+        if (m_readWriteIndex == halfSize) {
+            // The input buffer is now filled (get frequency-domain version)
+            m_frame.doFFT(m_inputBuffer.data());
+            m_frame.multiply(*fftKernel);
+            m_frame.doInverseFFT(m_outputBuffer.data());
+
+            // Overlap-add 1st half from previous time
+            vadd(m_outputBuffer.data(), 1, m_lastOverlapBuffer.data(), 1, m_outputBuffer.data(), 1, halfSize);
+
+            // Finally, save 2nd half of result
+            bool isCopyGood3 = m_outputBuffer.size() == 2 * halfSize && m_lastOverlapBuffer.size() == halfSize;
+            ASSERT(isCopyGood3);
+            if (!isCopyGood3)
+                return;
+
+            memcpy(m_lastOverlapBuffer.data(), m_outputBuffer.data() + halfSize, sizeof(float) * halfSize);
+
+            // Reset index back to start for next time
+            m_readWriteIndex = 0;
+        }
     }
 }
 

Modified: trunk/Source/WebCore/platform/audio/ReverbConvolver.cpp (111226 => 111227)


--- trunk/Source/WebCore/platform/audio/ReverbConvolver.cpp	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/platform/audio/ReverbConvolver.cpp	2012-03-19 20:19:46 UTC (rev 111227)
@@ -50,7 +50,7 @@
 // tuned for individual platforms if this assumption is found to be incorrect.
 const size_t RealtimeFrameLimit = 8192  + 4096; // ~278msec @ 44.1KHz
 
-const size_t MinFFTSize = 256;
+const size_t MinFFTSize = 128;
 const size_t MaxRealtimeFFTSize = 2048;
 
 static void backgroundThreadEntry(void* threadData)
@@ -84,8 +84,8 @@
     const float* response = impulseResponse->data();
     size_t totalResponseLength = impulseResponse->length();
 
-    // Because we're not using direct-convolution in the leading portion, the reverb has an overall latency of half the first-stage FFT size
-    size_t reverbTotalLatency = m_minFFTSize / 2;
+    // The total latency is zero because the direct-convolution is used in the leading portion.
+    size_t reverbTotalLatency = 0;
 
     size_t stageOffset = 0;
     int i = 0;
@@ -101,8 +101,10 @@
         // This "staggers" the time when each FFT happens so they don't all happen at the same time
         int renderPhase = convolverRenderPhase + i * renderSliceSize;
 
-        OwnPtr<ReverbConvolverStage> stage = adoptPtr(new ReverbConvolverStage(response, totalResponseLength, reverbTotalLatency, stageOffset, stageSize, fftSize, renderPhase, renderSliceSize, &m_accumulationBuffer));
+        bool useDirectConvolver = !stageOffset;
 
+        OwnPtr<ReverbConvolverStage> stage = adoptPtr(new ReverbConvolverStage(response, totalResponseLength, reverbTotalLatency, stageOffset, stageSize, fftSize, renderPhase, renderSliceSize, &m_accumulationBuffer, useDirectConvolver));
+
         bool isBackgroundStage = false;
 
         if (this->useBackgroundThreads() && stageOffset > RealtimeFrameLimit) {
@@ -114,8 +116,11 @@
         stageOffset += stageSize;
         ++i;
 
-        // Figure out next FFT size
-        fftSize *= 2;
+        if (!useDirectConvolver) {
+            // Figure out next FFT size
+            fftSize *= 2;
+        }
+
         if (hasRealtimeConstraint && !isBackgroundStage && fftSize > m_maxRealtimeFFTSize)
             fftSize = m_maxRealtimeFFTSize;
         if (fftSize > m_maxFFTSize)

Modified: trunk/Source/WebCore/platform/audio/ReverbConvolver.h (111226 => 111227)


--- trunk/Source/WebCore/platform/audio/ReverbConvolver.h	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/platform/audio/ReverbConvolver.h	2012-03-19 20:19:46 UTC (rev 111227)
@@ -30,6 +30,7 @@
 #define ReverbConvolver_h
 
 #include "AudioArray.h"
+#include "DirectConvolver.h"
 #include "FFTConvolver.h"
 #include "ReverbAccumulationBuffer.h"
 #include "ReverbConvolverStage.h"

Modified: trunk/Source/WebCore/platform/audio/ReverbConvolverStage.cpp (111226 => 111227)


--- trunk/Source/WebCore/platform/audio/ReverbConvolverStage.cpp	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/platform/audio/ReverbConvolverStage.cpp	2012-03-19 20:19:46 UTC (rev 111227)
@@ -44,18 +44,25 @@
 using namespace VectorMath;
 
 ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
-                                           size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer)
-    : m_fftKernel(fftSize)
-    , m_accumulationBuffer(accumulationBuffer)
+                                           size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer, bool directMode)
+    : m_accumulationBuffer(accumulationBuffer)
     , m_accumulationReadIndex(0)
     , m_inputReadIndex(0)
     , m_impulseResponseLength(responseLength)
+    , m_directMode(directMode)
 {
     ASSERT(impulseResponse);
     ASSERT(accumulationBuffer);
-    
-    m_fftKernel.doPaddedFFT(impulseResponse + stageOffset, stageLength);
-    m_convolver = adoptPtr(new FFTConvolver(fftSize));
+
+    if (!m_directMode) {
+        m_fftKernel = adoptPtr(new FFTFrame(fftSize));
+        m_fftKernel->doPaddedFFT(impulseResponse + stageOffset, stageLength);
+        m_fftConvolver = adoptPtr(new FFTConvolver(fftSize));
+    } else {
+        m_directKernel = adoptPtr(new AudioFloatArray(fftSize / 2));
+        m_directKernel->copyToRange(impulseResponse + stageOffset, 0, fftSize / 2);
+        m_directConvolver = adoptPtr(new DirectConvolver(renderSliceSize));
+    }
     m_temporaryBuffer.allocate(renderSliceSize);
 
     // The convolution stage at offset stageOffset needs to have a corresponding delay to cancel out the offset.
@@ -78,7 +85,9 @@
     m_preReadWriteIndex = 0;
     m_framesProcessed = 0; // total frames processed so far
 
-    m_preDelayBuffer.allocate(m_preDelayLength < fftSize ? fftSize : m_preDelayLength);
+    size_t delayBufferSize = m_preDelayLength < fftSize ? fftSize : m_preDelayLength;
+    delayBufferSize = delayBufferSize < renderSliceSize ? renderSliceSize : delayBufferSize;
+    m_preDelayBuffer.allocate(delayBufferSize);
 }
 
 void ReverbConvolverStage::processInBackground(ReverbConvolver* convolver, size_t framesToProcess)
@@ -133,7 +142,10 @@
         // Now, run the convolution (into the delay buffer).
         // An expensive FFT will happen every fftSize / 2 frames.
         // We process in-place here...
-        m_convolver->process(&m_fftKernel, preDelayedSource, temporaryBuffer, framesToProcess);
+        if (!m_directMode)
+            m_fftConvolver->process(m_fftKernel.get(), preDelayedSource, temporaryBuffer, framesToProcess);
+        else
+            m_directConvolver->process(m_directKernel.get(), preDelayedSource, temporaryBuffer, framesToProcess);
 
         // Now accumulate into reverb's accumulation buffer.
         m_accumulationBuffer->accumulate(temporaryBuffer, framesToProcess, &m_accumulationReadIndex, m_postDelayLength);
@@ -154,7 +166,10 @@
 
 void ReverbConvolverStage::reset()
 {
-    m_convolver->reset();
+    if (!m_directMode)
+        m_fftConvolver->reset();
+    else
+        m_directConvolver->reset();
     m_preDelayBuffer.zero();
     m_accumulationReadIndex = 0;
     m_inputReadIndex = 0;

Modified: trunk/Source/WebCore/platform/audio/ReverbConvolverStage.h (111226 => 111227)


--- trunk/Source/WebCore/platform/audio/ReverbConvolverStage.h	2012-03-19 20:13:40 UTC (rev 111226)
+++ trunk/Source/WebCore/platform/audio/ReverbConvolverStage.h	2012-03-19 20:19:46 UTC (rev 111227)
@@ -38,6 +38,7 @@
 class ReverbAccumulationBuffer;
 class ReverbConvolver;
 class FFTConvolver;
+class DirectConvolver;
     
 // A ReverbConvolverStage represents the convolution associated with a sub-section of a large impulse response.
 // It incorporates a delay line to account for the offset of the sub-section within the larger impulse response.
@@ -45,8 +46,7 @@
 public:
     // renderPhase is useful to know so that we can manipulate the pre versus post delay so that stages will perform
     // their heavy work (FFT processing) on different slices to balance the load in a real-time thread.
-    ReverbConvolverStage(const float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
-                         size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer);
+    ReverbConvolverStage(const float* impulseResponse, size_t responseLength, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength, size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer*, bool directMode = false);
 
     // WARNING: framesToProcess must be such that it evenly divides the delay buffer size (stage_offset).
     void process(const float* source, size_t framesToProcess);
@@ -59,8 +59,8 @@
     int inputReadIndex() const { return m_inputReadIndex; }
 
 private:
-    FFTFrame m_fftKernel;
-    OwnPtr<FFTConvolver> m_convolver;
+    OwnPtr<FFTFrame> m_fftKernel;
+    OwnPtr<FFTConvolver> m_fftConvolver;
 
     AudioFloatArray m_preDelayBuffer;
 
@@ -76,6 +76,10 @@
     AudioFloatArray m_temporaryBuffer;
 
     size_t m_impulseResponseLength;
+
+    bool m_directMode;
+    OwnPtr<AudioFloatArray> m_directKernel;
+    OwnPtr<DirectConvolver> m_directConvolver;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to