[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc
crogers at google.com
crogers at google.com
Wed Dec 22 12:48:38 UTC 2010
The following commit has been merged in the debian/experimental branch:
commit cb2f564d4f2b65094a6ff13e5e8f2a27e6142e01
Author: crogers at google.com <crogers at google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Aug 30 22:43:07 2010 +0000
2010-08-30 Chris Rogers <crogers at google.com>
Reviewed by Kenneth Russell.
audio engine: add ReverbConvolver class
https://bugs.webkit.org/show_bug.cgi?id=34912
No new tests since audio API is not yet implemented.
* platform/audio: Added.
* platform/audio/ReverbAccumulationBuffer.cpp: Added.
(WebCore::ReverbAccumulationBuffer::ReverbAccumulationBuffer):
(WebCore::ReverbAccumulationBuffer::readAndClear):
(WebCore::ReverbAccumulationBuffer::updateReadIndex):
(WebCore::ReverbAccumulationBuffer::accumulate):
(WebCore::ReverbAccumulationBuffer::reset):
* platform/audio/ReverbAccumulationBuffer.h: Added.
(WebCore::ReverbAccumulationBuffer::readIndex):
(WebCore::ReverbAccumulationBuffer::readTimeFrame):
* platform/audio/ReverbConvolver.cpp: Added.
(WebCore::backgroundThreadEntry):
(WebCore::ReverbConvolver::ReverbConvolver):
(WebCore::ReverbConvolver::~ReverbConvolver):
(WebCore::ReverbConvolver::backgroundThreadEntry):
(WebCore::ReverbConvolver::process):
(WebCore::ReverbConvolver::reset):
* platform/audio/ReverbConvolver.h: Added.
(WebCore::ReverbConvolver::impulseResponseLength):
(WebCore::ReverbConvolver::inputBuffer):
(WebCore::ReverbConvolver::useBackgroundThreads):
* platform/audio/ReverbConvolverStage.cpp: Added.
(WebCore::ReverbConvolverStage::ReverbConvolverStage):
(WebCore::ReverbConvolverStage::processInBackground):
(WebCore::ReverbConvolverStage::process):
(WebCore::ReverbConvolverStage::reset):
* platform/audio/ReverbConvolverStage.h: Added.
(WebCore::ReverbConvolverStage::inputReadIndex):
* platform/audio/ReverbInputBuffer.cpp: Added.
(WebCore::ReverbInputBuffer::ReverbInputBuffer):
(WebCore::ReverbInputBuffer::write):
(WebCore::ReverbInputBuffer::directReadFrom):
(WebCore::ReverbInputBuffer::reset):
* platform/audio/ReverbInputBuffer.h: Added.
(WebCore::ReverbInputBuffer::writeIndex):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66419 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 4da57dc..ddcd52e 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,48 @@
+2010-08-30 Chris Rogers <crogers at google.com>
+
+ Reviewed by Kenneth Russell.
+
+ audio engine: add ReverbConvolver class
+ https://bugs.webkit.org/show_bug.cgi?id=34912
+
+ No new tests since audio API is not yet implemented.
+
+ * platform/audio: Added.
+ * platform/audio/ReverbAccumulationBuffer.cpp: Added.
+ (WebCore::ReverbAccumulationBuffer::ReverbAccumulationBuffer):
+ (WebCore::ReverbAccumulationBuffer::readAndClear):
+ (WebCore::ReverbAccumulationBuffer::updateReadIndex):
+ (WebCore::ReverbAccumulationBuffer::accumulate):
+ (WebCore::ReverbAccumulationBuffer::reset):
+ * platform/audio/ReverbAccumulationBuffer.h: Added.
+ (WebCore::ReverbAccumulationBuffer::readIndex):
+ (WebCore::ReverbAccumulationBuffer::readTimeFrame):
+ * platform/audio/ReverbConvolver.cpp: Added.
+ (WebCore::backgroundThreadEntry):
+ (WebCore::ReverbConvolver::ReverbConvolver):
+ (WebCore::ReverbConvolver::~ReverbConvolver):
+ (WebCore::ReverbConvolver::backgroundThreadEntry):
+ (WebCore::ReverbConvolver::process):
+ (WebCore::ReverbConvolver::reset):
+ * platform/audio/ReverbConvolver.h: Added.
+ (WebCore::ReverbConvolver::impulseResponseLength):
+ (WebCore::ReverbConvolver::inputBuffer):
+ (WebCore::ReverbConvolver::useBackgroundThreads):
+ * platform/audio/ReverbConvolverStage.cpp: Added.
+ (WebCore::ReverbConvolverStage::ReverbConvolverStage):
+ (WebCore::ReverbConvolverStage::processInBackground):
+ (WebCore::ReverbConvolverStage::process):
+ (WebCore::ReverbConvolverStage::reset):
+ * platform/audio/ReverbConvolverStage.h: Added.
+ (WebCore::ReverbConvolverStage::inputReadIndex):
+ * platform/audio/ReverbInputBuffer.cpp: Added.
+ (WebCore::ReverbInputBuffer::ReverbInputBuffer):
+ (WebCore::ReverbInputBuffer::write):
+ (WebCore::ReverbInputBuffer::directReadFrom):
+ (WebCore::ReverbInputBuffer::reset):
+ * platform/audio/ReverbInputBuffer.h: Added.
+ (WebCore::ReverbInputBuffer::writeIndex):
+
2010-08-30 Nikolas Zimmermann <nzimmermann at rim.com>
Reviewed by Dirk Schulze.
diff --git a/WebCore/platform/audio/ReverbAccumulationBuffer.cpp b/WebCore/platform/audio/ReverbAccumulationBuffer.cpp
new file mode 100644
index 0000000..7b1c63b
--- /dev/null
+++ b/WebCore/platform/audio/ReverbAccumulationBuffer.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010 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 "ReverbAccumulationBuffer.h"
+
+#include "Accelerate.h"
+
+namespace WebCore {
+
+ReverbAccumulationBuffer::ReverbAccumulationBuffer(size_t length)
+ : m_buffer(length)
+ , m_readIndex(0)
+ , m_readTimeFrame(0)
+{
+}
+
+void ReverbAccumulationBuffer::readAndClear(float* destination, size_t numberOfFrames)
+{
+ size_t bufferLength = m_buffer.size();
+ bool isCopySafe = m_readIndex <= bufferLength && numberOfFrames <= bufferLength;
+
+ ASSERT(isCopySafe);
+ if (!isCopySafe)
+ return;
+
+ size_t framesAvailable = bufferLength - m_readIndex;
+ size_t numberOfFrames1 = std::min(numberOfFrames, framesAvailable);
+ size_t numberOfFrames2 = numberOfFrames - numberOfFrames1;
+
+ float* source = m_buffer.data();
+ memcpy(destination, source + m_readIndex, sizeof(float) * numberOfFrames1);
+ memset(source + m_readIndex, 0, sizeof(float) * numberOfFrames1);
+
+ // Handle wrap-around if necessary
+ if (numberOfFrames2 > 0) {
+ memcpy(destination + numberOfFrames1, source, sizeof(float) * numberOfFrames2);
+ memset(source, 0, sizeof(float) * numberOfFrames2);
+ }
+
+ m_readIndex = (m_readIndex + numberOfFrames) % bufferLength;
+ m_readTimeFrame += numberOfFrames;
+}
+
+void ReverbAccumulationBuffer::updateReadIndex(int* readIndex, size_t numberOfFrames) const
+{
+ // Update caller's readIndex
+ *readIndex = (*readIndex + numberOfFrames) % m_buffer.size();
+}
+
+int ReverbAccumulationBuffer::accumulate(float* source, size_t numberOfFrames, int* readIndex, size_t delayFrames)
+{
+ size_t bufferLength = m_buffer.size();
+
+ size_t writeIndex = (*readIndex + delayFrames) % bufferLength;
+
+ // Update caller's readIndex
+ *readIndex = (*readIndex + numberOfFrames) % bufferLength;
+
+ size_t framesAvailable = bufferLength - writeIndex;
+ size_t numberOfFrames1 = std::min(numberOfFrames, framesAvailable);
+ size_t numberOfFrames2 = numberOfFrames - numberOfFrames1;
+
+ float* destination = m_buffer.data();
+
+ bool isSafe = writeIndex <= bufferLength && numberOfFrames1 + writeIndex <= bufferLength && numberOfFrames2 <= bufferLength;
+ ASSERT(isSafe);
+ if (!isSafe)
+ return 0;
+
+ vadd(source, 1, destination + writeIndex, 1, destination + writeIndex, 1, numberOfFrames1);
+
+ // Handle wrap-around if necessary
+ if (numberOfFrames2 > 0)
+ vadd(source + numberOfFrames1, 1, destination, 1, destination, 1, numberOfFrames2);
+
+ return writeIndex;
+}
+
+void ReverbAccumulationBuffer::reset()
+{
+ m_buffer.zero();
+ m_readIndex = 0;
+ m_readTimeFrame = 0;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/platform/audio/ReverbAccumulationBuffer.h b/WebCore/platform/audio/ReverbAccumulationBuffer.h
new file mode 100644
index 0000000..44a0773
--- /dev/null
+++ b/WebCore/platform/audio/ReverbAccumulationBuffer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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 ReverbAccumulationBuffer_h
+#define ReverbAccumulationBuffer_h
+
+#include "AudioFloatArray.h"
+
+namespace WebCore {
+
+// ReverbAccumulationBuffer is a circular delay buffer with one client reading from it and multiple clients
+// writing/accumulating to it at different delay offsets from the read position. The read operation will zero the memory
+// just read from the buffer, so it will be ready for accumulation the next time around.
+class ReverbAccumulationBuffer {
+public:
+ ReverbAccumulationBuffer(size_t length);
+
+ // This will read from, then clear-out numberOfFrames
+ void readAndClear(float* destination, size_t numberOfFrames);
+
+ // Each ReverbConvolverStage will accumulate its output at the appropriate delay from the read position.
+ // We need to pass in and update readIndex here, since each ReverbConvolverStage may be running in
+ // a different thread than the realtime thread calling ReadAndClear() and maintaining m_readIndex
+ // Returns the writeIndex where the accumulation took place
+ int accumulate(float* source, size_t numberOfFrames, int* readIndex, size_t delayFrames);
+
+ size_t readIndex() const { return m_readIndex; }
+ void updateReadIndex(int* readIndex, size_t numberOfFrames) const;
+
+ size_t readTimeFrame() const { return m_readTimeFrame; }
+
+ void reset();
+
+private:
+ AudioFloatArray m_buffer;
+ size_t m_readIndex;
+ size_t m_readTimeFrame; // for debugging (frame on continuous timeline)
+};
+
+} // namespace WebCore
+
+#endif // ReverbAccumulationBuffer_h
diff --git a/WebCore/platform/audio/ReverbConvolver.cpp b/WebCore/platform/audio/ReverbConvolver.cpp
new file mode 100644
index 0000000..719e586
--- /dev/null
+++ b/WebCore/platform/audio/ReverbConvolver.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2010 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 "ReverbConvolver.h"
+
+#include "Accelerate.h"
+#include "AudioBus.h"
+
+namespace WebCore {
+
+const int InputBufferSize = 8 * 16384;
+
+// We only process the leading portion of the impulse response in the real-time thread. We don't exceed this length.
+// It turns out then, that the background thread has about 278msec of scheduling slop.
+// Empirically, this has been found to be a good compromise between giving enough time for scheduling slop,
+// while still minimizing the amount of processing done in the primary (high-priority) thread.
+// This was found to be a good value on Mac OS X, and may work well on other platforms as well, assuming
+// the very rough scheduling latencies are similar on these time-scales. Of course, this code may need to be
+// 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 MaxRealtimeFFTSize = 2048;
+
+static void* backgroundThreadEntry(void* threadData)
+{
+ ReverbConvolver* reverbConvolver = static_cast<ReverbConvolver*>(threadData);
+ reverbConvolver->backgroundThreadEntry();
+ return 0;
+}
+
+ReverbConvolver::ReverbConvolver(AudioChannel* impulseResponse, size_t renderSliceSize, size_t maxFFTSize, size_t convolverRenderPhase, bool useBackgroundThreads)
+ : m_impulseResponseLength(impulseResponse->frameSize())
+ , m_accumulationBuffer(impulseResponse->frameSize() + renderSliceSize)
+ , m_inputBuffer(InputBufferSize)
+ , m_renderSliceSize(renderSliceSize)
+ , m_minFFTSize(MinFFTSize) // First stage will have this size - successive stages will double in size each time
+ , m_maxFFTSize(maxFFTSize) // until we hit m_maxFFTSize
+ , m_useBackgroundThreads(useBackgroundThreads)
+ , m_backgroundThread(0)
+ , m_wantsToExit(false)
+ , m_moreInputBuffered(false)
+{
+ // If we are using background threads then don't exceed this FFT size for the
+ // stages which run in the real-time thread. This avoids having only one or two
+ // large stages (size 16384 or so) at the end which take a lot of time every several
+ // processing slices. This way we amortize the cost over more processing slices.
+ m_maxRealtimeFFTSize = MaxRealtimeFFTSize;
+
+ // For the moment, a good way to know if we have real-time constraint is to check if we're using background threads.
+ // Otherwise, assume we're being run from a command-line tool.
+ bool hasRealtimeConstraint = useBackgroundThreads;
+
+ float* response = impulseResponse->data();
+ size_t totalResponseLength = impulseResponse->frameSize();
+
+ // 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;
+
+ size_t stageOffset = 0;
+ int i = 0;
+ size_t fftSize = m_minFFTSize;
+ while (stageOffset < totalResponseLength) {
+ size_t stageSize = fftSize / 2;
+
+ // For the last stage, it's possible that stageOffset is such that we're straddling the end
+ // of the impulse response buffer (if we use stageSize), so reduce the last stage's length...
+ if (stageSize + stageOffset > totalResponseLength)
+ stageSize = totalResponseLength - stageOffset;
+
+ // 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(new ReverbConvolverStage(response, totalResponseLength, reverbTotalLatency, stageOffset, stageSize, fftSize, renderPhase, renderSliceSize, &m_accumulationBuffer));
+
+ bool isBackgroundStage = false;
+
+ if (this->useBackgroundThreads() && stageOffset > RealtimeFrameLimit) {
+ m_backgroundStages.append(stage.release());
+ isBackgroundStage = true;
+ } else
+ m_stages.append(stage.release());
+
+ stageOffset += stageSize;
+ ++i;
+
+ // Figure out next FFT size
+ fftSize *= 2;
+ if (hasRealtimeConstraint && !isBackgroundStage && fftSize > m_maxRealtimeFFTSize)
+ fftSize = m_maxRealtimeFFTSize;
+ if (fftSize > m_maxFFTSize)
+ fftSize = m_maxFFTSize;
+ }
+
+ // Start up background thread
+ // FIXME: would be better to up the thread priority here. It doesn't need to be real-time, but higher than the default...
+ if (this->useBackgroundThreads() && m_backgroundStages.size() > 0)
+ m_backgroundThread = createThread(WebCore::backgroundThreadEntry, this, "convolution background thread");
+}
+
+ReverbConvolver::~ReverbConvolver()
+{
+ // Wait for background thread to stop
+ if (useBackgroundThreads() && m_backgroundThread) {
+ m_wantsToExit = true;
+
+ // Wake up thread so it can return
+ {
+ MutexLocker locker(m_backgroundThreadLock);
+ m_moreInputBuffered = true;
+ m_backgroundThreadCondition.signal();
+ }
+
+ waitForThreadCompletion(m_backgroundThread, 0);
+ }
+}
+
+void ReverbConvolver::backgroundThreadEntry()
+{
+ while (!m_wantsToExit) {
+ // Wait for realtime thread to give us more input
+ m_moreInputBuffered = false;
+ {
+ MutexLocker locker(m_backgroundThreadLock);
+ while (!m_moreInputBuffered && !m_wantsToExit)
+ m_backgroundThreadCondition.wait(m_backgroundThreadLock);
+ }
+
+ // Process all of the stages until their read indices reach the input buffer's write index
+ int writeIndex = m_inputBuffer.writeIndex();
+
+ // Even though it doesn't seem like every stage needs to maintain its own version of readIndex
+ // we do this in case we want to run in more than one background thread.
+ int readIndex;
+
+ while ((readIndex = m_backgroundStages[0]->inputReadIndex()) != writeIndex) { // FIXME: do better to detect buffer overrun...
+ // The ReverbConvolverStages need to process in amounts which evenly divide half the FFT size
+ const int SliceSize = MinFFTSize / 2;
+
+ // Accumulate contributions from each stage
+ for (size_t i = 0; i < m_backgroundStages.size(); ++i)
+ m_backgroundStages[i]->processInBackground(this, SliceSize);
+ }
+ }
+}
+
+void ReverbConvolver::process(AudioChannel* sourceChannel, AudioChannel* destinationChannel, size_t framesToProcess)
+{
+ bool isSafe = sourceChannel && destinationChannel && sourceChannel->frameSize() >= framesToProcess && destinationChannel->frameSize() >= framesToProcess;
+ ASSERT(isSafe);
+ if (!isSafe)
+ return;
+
+ float* source = sourceChannel->data();
+ float* destination = destinationChannel->data();
+ bool isDataSafe = source && destination;
+ ASSERT(isDataSafe);
+ if (!isDataSafe)
+ return;
+
+ // Feed input buffer (read by all threads)
+ m_inputBuffer.write(source, framesToProcess);
+
+ // Accumulate contributions from each stage
+ for (size_t i = 0; i < m_stages.size(); ++i)
+ m_stages[i]->process(source, framesToProcess);
+
+ // Finally read from accumulation buffer
+ m_accumulationBuffer.readAndClear(destination, framesToProcess);
+
+ // Now that we've buffered more input, wake up our background thread.
+
+ // Not using a MutexLocker looks strange, but we use a tryLock() instead because this is run on the real-time
+ // thread where it is a disaster for the lock to be contended (causes audio glitching). It's OK if we fail to
+ // signal from time to time, since we'll get to it the next time we're called. We're called repeatedly
+ // and frequently (around every 3ms). The background thread is processing well into the future and has a considerable amount of
+ // leeway here...
+ if (m_backgroundThreadLock.tryLock()) {
+ m_moreInputBuffered = true;
+ m_backgroundThreadCondition.signal();
+ m_backgroundThreadLock.unlock();
+ }
+}
+
+void ReverbConvolver::reset()
+{
+ for (size_t i = 0; i < m_stages.size(); ++i)
+ m_stages[i]->reset();
+
+ for (size_t i = 0; i < m_backgroundStages.size(); ++i)
+ m_backgroundStages[i]->reset();
+
+ m_accumulationBuffer.reset();
+ m_inputBuffer.reset();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/platform/audio/ReverbConvolver.h b/WebCore/platform/audio/ReverbConvolver.h
new file mode 100644
index 0000000..34f77d3
--- /dev/null
+++ b/WebCore/platform/audio/ReverbConvolver.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 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 ReverbConvolver_h
+#define ReverbConvolver_h
+
+#include "AudioFloatArray.h"
+#include "FFTConvolver.h"
+#include "ReverbAccumulationBuffer.h"
+#include "ReverbConvolverStage.h"
+#include "ReverbInputBuffer.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AudioChannel;
+
+class ReverbConvolver {
+public:
+ // maxFFTSize can be adjusted (from say 2048 to 32768) depending on how much precision is necessary.
+ // For certain tweaky de-convolving applications the phase errors add up quickly and lead to non-sensical results with
+ // larger FFT sizes and single-precision floats. In these cases 2048 is a good size.
+ // If not doing multi-threaded convolution, then should not go > 8192.
+ ReverbConvolver(AudioChannel* impulseResponse, size_t renderSliceSize, size_t maxFFTSize, size_t convolverRenderPhase, bool useBackgroundThreads);
+ ~ReverbConvolver();
+
+ void process(AudioChannel* sourceChannel, AudioChannel* destinationChannel, size_t framesToProcess);
+ void reset();
+
+ size_t impulseResponseLength() const { return m_impulseResponseLength; }
+
+ ReverbInputBuffer* inputBuffer() { return &m_inputBuffer; }
+
+ bool useBackgroundThreads() const { return m_useBackgroundThreads; }
+ void backgroundThreadEntry();
+
+private:
+ Vector<OwnPtr<ReverbConvolverStage> > m_stages;
+ Vector<OwnPtr<ReverbConvolverStage> > m_backgroundStages;
+ size_t m_impulseResponseLength;
+
+ ReverbAccumulationBuffer m_accumulationBuffer;
+
+ // One or more background threads read from this input buffer which is fed from the realtime thread.
+ ReverbInputBuffer m_inputBuffer;
+
+ // We're given a rendering hint, so the FFTs can be optimized to not all occur at the same time
+ // (very bad when rendering on a real-time thread).
+ size_t m_renderSliceSize;
+
+ // First stage will be of size m_minFFTSize. Each next stage will be twice as big until we hit m_maxFFTSize.
+ size_t m_minFFTSize;
+ size_t m_maxFFTSize;
+
+ // But don't exceed this size in the real-time thread (if we're doing background processing).
+ size_t m_maxRealtimeFFTSize;
+
+ // Background thread and synchronization
+ bool m_useBackgroundThreads;
+ ThreadIdentifier m_backgroundThread;
+ bool m_wantsToExit;
+ bool m_moreInputBuffered;
+ mutable Mutex m_backgroundThreadLock;
+ mutable ThreadCondition m_backgroundThreadCondition;
+};
+
+} // namespace WebCore
+
+#endif // ReverbConvolver_h
diff --git a/WebCore/platform/audio/ReverbConvolverStage.cpp b/WebCore/platform/audio/ReverbConvolverStage.cpp
new file mode 100644
index 0000000..8606502
--- /dev/null
+++ b/WebCore/platform/audio/ReverbConvolverStage.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2010 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 "ReverbConvolverStage.h"
+
+#include "Accelerate.h"
+#include "ReverbAccumulationBuffer.h"
+#include "ReverbConvolver.h"
+#include "ReverbInputBuffer.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+ReverbConvolverStage::ReverbConvolverStage(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)
+ , m_accumulationReadIndex(0)
+ , m_inputReadIndex(0)
+ , m_impulseResponseLength(responseLength)
+{
+ ASSERT(impulseResponse);
+ ASSERT(accumulationBuffer);
+
+ m_fftKernel.doPaddedFFT(impulseResponse + stageOffset, stageLength);
+ m_convolver = new FFTConvolver(fftSize);
+ m_temporaryBuffer.allocate(renderSliceSize);
+
+ // The convolution stage at offset stageOffset needs to have a corresponding delay to cancel out the offset.
+ size_t totalDelay = stageOffset + reverbTotalLatency;
+
+ // But, the FFT convolution itself incurs fftSize / 2 latency, so subtract this out...
+ size_t halfSize = fftSize / 2;
+ ASSERT(totalDelay >= halfSize);
+ if (totalDelay >= halfSize)
+ totalDelay -= halfSize;
+
+ // We divide up the total delay, into pre and post delay sections so that we can schedule at exactly the moment when the FFT will happen.
+ // This is coordinated with the other stages, so they don't all do their FFTs at the same time...
+ int maxPreDelayLength = std::min(halfSize, totalDelay);
+ m_preDelayLength = totalDelay > 0 ? renderPhase % maxPreDelayLength : 0;
+ if (m_preDelayLength > totalDelay)
+ m_preDelayLength = 0;
+
+ m_postDelayLength = totalDelay - m_preDelayLength;
+ m_preReadWriteIndex = 0;
+ m_framesProcessed = 0; // total frames processed so far
+
+ m_preDelayBuffer.allocate(m_preDelayLength < fftSize ? fftSize : m_preDelayLength);
+}
+
+void ReverbConvolverStage::processInBackground(ReverbConvolver* convolver, size_t framesToProcess)
+{
+ ReverbInputBuffer* inputBuffer = convolver->inputBuffer();
+ float* source = inputBuffer->directReadFrom(&m_inputReadIndex, framesToProcess);
+ process(source, framesToProcess);
+}
+
+void ReverbConvolverStage::process(float* source, size_t framesToProcess)
+{
+ ASSERT(source);
+ if (!source)
+ return;
+
+ // Deal with pre-delay stream : note special handling of zero delay.
+
+ float* preDelayedSource;
+ float* temporaryBuffer;
+ bool isTemporaryBufferSafe = false;
+ if (m_preDelayLength > 0) {
+ // Handles both the read case (call to process() ) and the write case (memcpy() )
+ bool isPreDelaySafe = m_preReadWriteIndex + framesToProcess <= m_preDelayBuffer.size();
+ ASSERT(isPreDelaySafe);
+ if (!isPreDelaySafe)
+ return;
+
+ isTemporaryBufferSafe = framesToProcess <= m_temporaryBuffer.size();
+
+ preDelayedSource = m_preDelayBuffer.data() + m_preReadWriteIndex;
+ temporaryBuffer = m_temporaryBuffer.data();
+ } else {
+ // Zero delay
+ preDelayedSource = source;
+ temporaryBuffer = m_preDelayBuffer.data();
+
+ isTemporaryBufferSafe = framesToProcess <= m_preDelayBuffer.size();
+ }
+
+ ASSERT(isTemporaryBufferSafe);
+ if (!isTemporaryBufferSafe)
+ return;
+
+ int writeIndex = 0;
+
+ if (m_framesProcessed < m_preDelayLength) {
+ // For the first m_preDelayLength frames don't process the convolver, instead simply buffer in the pre-delay.
+ // But while buffering the pre-delay, we still need to update our index.
+ m_accumulationBuffer->updateReadIndex(&m_accumulationReadIndex, framesToProcess);
+ } else {
+ // 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);
+
+ // Now accumulate into reverb's accumulation buffer.
+ writeIndex = m_accumulationBuffer->accumulate(temporaryBuffer, framesToProcess, &m_accumulationReadIndex, m_postDelayLength);
+ }
+
+ // Finally copy input to pre-delay.
+ if (m_preDelayLength > 0) {
+ memcpy(preDelayedSource, source, sizeof(float) * framesToProcess);
+ m_preReadWriteIndex += framesToProcess;
+
+ ASSERT(m_preReadWriteIndex <= m_preDelayLength);
+ if (m_preReadWriteIndex >= m_preDelayLength)
+ m_preReadWriteIndex = 0;
+ }
+
+ m_framesProcessed += framesToProcess;
+}
+
+void ReverbConvolverStage::reset()
+{
+ m_convolver->reset();
+ m_preDelayBuffer.zero();
+ m_accumulationReadIndex = 0;
+ m_inputReadIndex = 0;
+ m_framesProcessed = 0;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/platform/audio/ReverbConvolverStage.h b/WebCore/platform/audio/ReverbConvolverStage.h
new file mode 100644
index 0000000..88351af
--- /dev/null
+++ b/WebCore/platform/audio/ReverbConvolverStage.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 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 ReverbConvolverStage_h
+#define ReverbConvolverStage_h
+
+#include "AudioFloatArray.h"
+#include "FFTFrame.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class ReverbAccumulationBuffer;
+class ReverbConvolver;
+class FFTConvolver;
+
+// 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.
+class ReverbConvolverStage {
+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(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);
+
+ // WARNING: framesToProcess must be such that it evenly divides the delay buffer size (stage_offset).
+ void process(float* source, size_t framesToProcess);
+
+ void processInBackground(ReverbConvolver* convolver, size_t framesToProcess);
+
+ void reset();
+
+ // Useful for background processing
+ int inputReadIndex() const { return m_inputReadIndex; }
+
+private:
+ FFTFrame m_fftKernel;
+ OwnPtr<FFTConvolver> m_convolver;
+
+ AudioFloatArray m_preDelayBuffer;
+
+ ReverbAccumulationBuffer* m_accumulationBuffer;
+ int m_accumulationReadIndex;
+ int m_inputReadIndex;
+
+ size_t m_preDelayLength;
+ size_t m_postDelayLength;
+ size_t m_preReadWriteIndex;
+ size_t m_framesProcessed;
+
+ AudioFloatArray m_temporaryBuffer;
+
+ size_t m_impulseResponseLength;
+};
+
+} // namespace WebCore
+
+#endif // ReverbConvolverStage_h
diff --git a/WebCore/platform/audio/ReverbInputBuffer.cpp b/WebCore/platform/audio/ReverbInputBuffer.cpp
new file mode 100644
index 0000000..f270f6f
--- /dev/null
+++ b/WebCore/platform/audio/ReverbInputBuffer.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 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 "ReverbInputBuffer.h"
+
+namespace WebCore {
+
+ReverbInputBuffer::ReverbInputBuffer(size_t length)
+ : m_buffer(length)
+ , m_writeIndex(0)
+{
+}
+
+void ReverbInputBuffer::write(float* sourceP, size_t numberOfFrames)
+{
+ size_t bufferLength = m_buffer.size();
+ bool isCopySafe = m_writeIndex + numberOfFrames <= bufferLength;
+ ASSERT(isCopySafe);
+ if (!isCopySafe)
+ return;
+
+ memcpy(m_buffer.data() + m_writeIndex, sourceP, sizeof(float) * numberOfFrames);
+
+ m_writeIndex += numberOfFrames;
+ ASSERT(m_writeIndex <= bufferLength);
+
+ if (m_writeIndex >= bufferLength)
+ m_writeIndex = 0;
+}
+
+float* ReverbInputBuffer::directReadFrom(int* readIndex, size_t numberOfFrames)
+{
+ size_t bufferLength = m_buffer.size();
+ bool isPointerGood = readIndex && *readIndex >= 0 && *readIndex + numberOfFrames <= bufferLength;
+ ASSERT(isPointerGood);
+ if (!isPointerGood) {
+ // Should never happen in practice but return pointer to start of buffer (avoid crash)
+ if (readIndex)
+ *readIndex = 0;
+ return m_buffer.data();
+ }
+
+ float* sourceP = m_buffer.data();
+ float* p = sourceP + *readIndex;
+
+ // Update readIndex
+ *readIndex = (*readIndex + numberOfFrames) % bufferLength;
+
+ return p;
+}
+
+void ReverbInputBuffer::reset()
+{
+ m_buffer.zero();
+ m_writeIndex = 0;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/platform/audio/ReverbInputBuffer.h b/WebCore/platform/audio/ReverbInputBuffer.h
new file mode 100644
index 0000000..aa9cf41
--- /dev/null
+++ b/WebCore/platform/audio/ReverbInputBuffer.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 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 ReverbInputBuffer_h
+#define ReverbInputBuffer_h
+
+#include "AudioFloatArray.h"
+
+namespace WebCore {
+
+// ReverbInputBuffer is used to buffer input samples for deferred processing by the background threads.
+class ReverbInputBuffer {
+public:
+ ReverbInputBuffer(size_t length);
+
+ // The realtime audio thread keeps writing samples here.
+ // The assumption is that the buffer's length is evenly divisible by numberOfFrames (for nearly all cases this will be fine).
+ // FIXME: remove numberOfFrames restriction...
+ void write(float* sourceP, size_t numberOfFrames);
+
+ // Background threads can call this to check if there's anything to read...
+ size_t writeIndex() const { return m_writeIndex; }
+
+ // The individual background threads read here (and hope that they can keep up with the buffer writing).
+ // readIndex is updated with the next readIndex to read from...
+ // The assumption is that the buffer's length is evenly divisible by numberOfFrames.
+ // FIXME: remove numberOfFrames restriction...
+ float* directReadFrom(int* readIndex, size_t numberOfFrames);
+
+ void reset();
+
+private:
+ AudioFloatArray m_buffer;
+ size_t m_writeIndex;
+};
+
+} // namespace WebCore
+
+#endif // ReverbInputBuffer_h
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list