Add AudioFIFO class and simplify AudioPullFIFO
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Jul 2012 23:40:50 +0000 (23:40 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Jul 2012 23:40:50 +0000 (23:40 +0000)
https://bugs.webkit.org/show_bug.cgi?id=90398

Patch by Raymond Toy <rtoy@google.com> on 2012-07-03
Reviewed by Chris Rogers.

No new tests. This code will be used in audio back-end implementation.

Add AudioFIFO class to implement main parts of FIFO.  Simplify
implementation of AudioPushFIFO by using AudioFIFO.

* WebCore.gypi: Add new files.

New AudioFIFO class
* platform/audio/AudioFIFO.cpp: Copied from Source/WebCore/platform/audio/AudioPullFIFO.cpp.
(WebCore):
(WebCore::AudioFIFO::AudioFIFO):
(WebCore::AudioFIFO::consume):
(WebCore::AudioFIFO::push):
(WebCore::AudioFIFO::findWrapLengths):
* platform/audio/AudioFIFO.h: Copied from Source/WebCore/platform/audio/AudioPullFIFO.h.
(WebCore):
(AudioFIFO):
(WebCore::AudioFIFO::framesInFifo):
(WebCore::AudioFIFO::updateIndex):

Use AudioFIFO
* platform/audio/AudioPullFIFO.cpp:
(WebCore::AudioPullFIFO::AudioPullFIFO):
(WebCore::AudioPullFIFO::consume):
(WebCore::AudioPullFIFO::fillBuffer):
* platform/audio/AudioPullFIFO.h:
(AudioPullFIFO):

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

Source/WebCore/ChangeLog
Source/WebCore/WebCore.gypi
Source/WebCore/platform/audio/AudioFIFO.cpp [new file with mode: 0644]
Source/WebCore/platform/audio/AudioFIFO.h [new file with mode: 0644]
Source/WebCore/platform/audio/AudioPullFIFO.cpp
Source/WebCore/platform/audio/AudioPullFIFO.h

index d4b6b31..213399d 100644 (file)
@@ -1,3 +1,38 @@
+2012-07-03  Raymond Toy  <rtoy@google.com>
+
+        Add AudioFIFO class and simplify AudioPullFIFO
+        https://bugs.webkit.org/show_bug.cgi?id=90398
+
+        Reviewed by Chris Rogers.
+
+        No new tests. This code will be used in audio back-end implementation.
+
+        Add AudioFIFO class to implement main parts of FIFO.  Simplify
+        implementation of AudioPushFIFO by using AudioFIFO.
+        
+        * WebCore.gypi: Add new files.
+
+        New AudioFIFO class
+        * platform/audio/AudioFIFO.cpp: Copied from Source/WebCore/platform/audio/AudioPullFIFO.cpp.
+        (WebCore):
+        (WebCore::AudioFIFO::AudioFIFO):
+        (WebCore::AudioFIFO::consume):
+        (WebCore::AudioFIFO::push):
+        (WebCore::AudioFIFO::findWrapLengths):
+        * platform/audio/AudioFIFO.h: Copied from Source/WebCore/platform/audio/AudioPullFIFO.h.
+        (WebCore):
+        (AudioFIFO):
+        (WebCore::AudioFIFO::framesInFifo):
+        (WebCore::AudioFIFO::updateIndex):
+
+        Use AudioFIFO
+        * platform/audio/AudioPullFIFO.cpp:
+        (WebCore::AudioPullFIFO::AudioPullFIFO):
+        (WebCore::AudioPullFIFO::consume):
+        (WebCore::AudioPullFIFO::fillBuffer):
+        * platform/audio/AudioPullFIFO.h:
+        (AudioPullFIFO):
+
 2012-07-03  Nate Chapin  <japhet@chromium.org>
 
         Protect this DocumentThreadableLoader in cancel() to handle reentrancy properly.
index 6a077de..c7332d2 100644 (file)
             'platform/audio/AudioDSPKernelProcessor.cpp',
             'platform/audio/AudioDSPKernelProcessor.h',
             'platform/audio/AudioDestination.h',
+            'platform/audio/AudioFIFO.cpp',
+            'platform/audio/AudioFIFO.h',
             'platform/audio/AudioFileReader.h',
             'platform/audio/AudioProcessor.h',
             'platform/audio/AudioPullFIFO.cpp',
diff --git a/Source/WebCore/platform/audio/AudioFIFO.cpp b/Source/WebCore/platform/audio/AudioFIFO.cpp
new file mode 100644 (file)
index 0000000..d6ee241
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2012 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 "AudioFIFO.h"
+
+namespace WebCore {
+
+AudioFIFO::AudioFIFO(unsigned numberOfChannels, size_t fifoLength)
+    : m_fifoAudioBus(numberOfChannels, fifoLength)
+    , m_fifoLength(fifoLength)
+    , m_framesInFifo(0)
+    , m_readIndex(0)
+    , m_writeIndex(0)
+{
+}
+
+void AudioFIFO::consume(AudioBus* destination, size_t framesToConsume)
+{
+    bool isGood = destination && (framesToConsume <= m_fifoLength) && (framesToConsume <= m_framesInFifo) && (destination->length() >= framesToConsume);
+    ASSERT(isGood);
+    if (!isGood)
+        return;
+
+    // Copy the requested number of samples to the destination.
+
+    size_t part1Length;
+    size_t part2Length;
+    findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length);
+
+    size_t numberOfChannels = m_fifoAudioBus.numberOfChannels();
+
+    for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
+        float* destinationData = destination->channel(channelIndex)->mutableData();
+        const float* sourceData = m_fifoAudioBus.channel(channelIndex)->data();
+
+        bool isCopyGood = ((m_readIndex < m_fifoLength)
+                           && (m_readIndex + part1Length) <= m_fifoLength
+                           && (part1Length <= destination->length())
+                           && (part1Length + part2Length) <= destination->length());
+        ASSERT(isCopyGood);
+        if (!isCopyGood)
+            return;
+
+        memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData));
+        // Handle wrap around of the FIFO, if needed.
+        if (part2Length)
+            memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData));
+    }
+    m_readIndex = updateIndex(m_readIndex, framesToConsume);
+    ASSERT(m_framesInFifo >= framesToConsume);
+    m_framesInFifo -= framesToConsume;
+}
+
+void AudioFIFO::push(const AudioBus* sourceBus)
+{
+    // Copy the sourceBus into the FIFO buffer.
+
+    bool isGood = sourceBus && (m_framesInFifo + sourceBus->length() <= m_fifoLength);
+    if (!isGood)
+        return;
+
+    size_t sourceLength = sourceBus->length();
+    size_t part1Length;
+    size_t part2Length;
+    findWrapLengths(m_readIndex, sourceLength, part1Length, part2Length);
+
+    size_t numberOfChannels = m_fifoAudioBus.numberOfChannels();
+
+    for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
+        float* destination = m_fifoAudioBus.channel(channelIndex)->mutableData();
+        const float* source = sourceBus->channel(channelIndex)->data();
+
+        bool isCopyGood = ((m_writeIndex < m_fifoLength)
+                           && (m_writeIndex + part1Length) <= m_fifoLength
+                           && part2Length < m_fifoLength
+                           && part1Length + part2Length <= sourceLength);
+        ASSERT(isCopyGood);
+        if (!isCopyGood)
+            return;
+
+        memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination));
+
+        // Handle wrap around of the FIFO, if needed.
+        if (part2Length)
+            memcpy(destination, source + part1Length, part2Length * sizeof(*destination));
+    }
+        
+    m_framesInFifo += sourceLength;
+    ASSERT(m_framesInFifo <= m_fifoLength);
+    m_writeIndex = updateIndex(m_writeIndex, sourceLength);
+}
+
+void AudioFIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length)
+{
+    ASSERT(index < m_fifoLength && size <= m_fifoLength);
+    if (index < m_fifoLength && size <= m_fifoLength) {
+        if (index + size > m_fifoLength) {
+            // Need to wrap. Figure out the length of each piece.
+            part1Length = m_fifoLength - index;
+            part2Length = size - part1Length;
+        } else {
+            // No wrap needed.
+            part1Length = size;
+            part2Length = 0;
+        }
+    } else {
+        // Invalid values for index or size. Set the part lengths to zero so nothing is copied.
+        part1Length = 0;
+        part2Length = 0;
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/platform/audio/AudioFIFO.h b/Source/WebCore/platform/audio/AudioFIFO.h
new file mode 100644 (file)
index 0000000..f526f22
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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 AudioFIFO_h
+#define AudioFIFO_h
+
+#include "AudioBus.h"
+
+namespace WebCore {
+
+class AudioFIFO {
+public:
+    // Create a FIFO large enough to hold |fifoLength| frames of data of |numberOfChannels| channels.
+    AudioFIFO(unsigned numberOfChannels, size_t fifoLength);
+
+    // Push the data from the bus into the FIFO.
+    void push(const AudioBus*);
+
+    // Consume |framesToConsume| frames of data from the FIFO and put them in |destination|. The
+    // corresponding frames are removed from the FIFO.
+    void consume(AudioBus* destination, size_t framesToConsume);
+
+    // Number of frames of data that are currently in the FIFO.
+    size_t framesInFifo() const { return m_framesInFifo; }
+
+private:
+    // Update the FIFO index by the step, with appropriate wrapping around the endpoint.
+    int updateIndex(int index, int step) { return (index + step) % m_fifoLength; }
+
+    void findWrapLengths(size_t index, size_t providerSize, size_t& part1Length, size_t& part2Length);
+    
+    // The FIFO itself. In reality, the FIFO is a circular buffer.
+    AudioBus m_fifoAudioBus;
+
+    // The total available space in the FIFO.
+    size_t m_fifoLength;
+
+    // The number of actual elements in the FIFO
+    size_t m_framesInFifo;
+
+    // Where to start reading from the FIFO.
+    size_t m_readIndex;
+
+    // Where to start writing to the FIFO.
+    size_t m_writeIndex;
+};
+
+} // namespace WebCore
+
+#endif // AudioFIFO.h
index 03e89de..2611567 100644 (file)
@@ -36,11 +36,7 @@ namespace WebCore {
 
 AudioPullFIFO::AudioPullFIFO(AudioSourceProvider& audioProvider, unsigned numberOfChannels, size_t fifoLength, size_t providerSize)
     : m_provider(audioProvider)
-    , m_fifoAudioBus(numberOfChannels, fifoLength)
-    , m_fifoLength(fifoLength)
-    , m_framesInFifo(0)
-    , m_readIndex(0)
-    , m_writeIndex(0)
+    , m_fifo(numberOfChannels, fifoLength)
     , m_providerSize(providerSize)
     , m_tempBus(numberOfChannels, providerSize)
 {
@@ -48,64 +44,15 @@ AudioPullFIFO::AudioPullFIFO(AudioSourceProvider& audioProvider, unsigned number
 
 void AudioPullFIFO::consume(AudioBus* destination, size_t framesToConsume)
 {
-    bool isGood = destination && (framesToConsume <= m_fifoLength);
-    ASSERT(isGood);
-    if (!isGood)
+    if (!destination)
         return;
 
-    if (framesToConsume > m_framesInFifo) {
+    if (framesToConsume > m_fifo.framesInFifo()) {
         // We don't have enough data in the FIFO to fulfill the request. Ask for more data.
-        fillBuffer(framesToConsume - m_framesInFifo);
+        fillBuffer(framesToConsume - m_fifo.framesInFifo());
     }
 
-    // We have enough data now. Copy the requested number of samples to the destination.
-
-    size_t part1Length;
-    size_t part2Length;
-    findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length);
-
-    size_t numberOfChannels = m_fifoAudioBus.numberOfChannels();
-
-    for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
-        float* destinationData = destination->channel(channelIndex)->mutableData();
-        const float* sourceData = m_fifoAudioBus.channel(channelIndex)->data();
-
-        bool isCopyGood = ((m_readIndex < m_fifoLength)
-                           && (m_readIndex + part1Length) <= m_fifoLength
-                           && (part1Length <= destination->length())
-                           && (part1Length + part2Length) <= destination->length());
-        ASSERT(isCopyGood);
-        if (!isCopyGood)
-            return;
-
-        memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData));
-        // Handle wrap around of the FIFO, if needed.
-        if (part2Length > 0)
-            memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData));
-    }
-    m_readIndex = updateIndex(m_readIndex, framesToConsume);
-    m_framesInFifo -= framesToConsume;
-    ASSERT(m_framesInFifo >= 0);
-}
-
-void AudioPullFIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length)
-{
-    ASSERT(index < m_fifoLength && size <= m_fifoLength);
-    if (index < m_fifoLength && size <= m_fifoLength) {
-        if (index + size > m_fifoLength) {
-            // Need to wrap. Figure out the length of each piece.
-            part1Length = m_fifoLength - index;
-            part2Length = size - part1Length;
-        } else {
-            // No wrap needed.
-            part1Length = size;
-            part2Length = 0;
-        }
-    } else {
-        // Invalid values for index or size. Set the part lengths to zero so nothing is copied.
-        part1Length = 0;
-        part2Length = 0;
-    }
+    m_fifo.consume(destination, framesToConsume);
 }
 
 void AudioPullFIFO::fillBuffer(size_t numberOfFrames)
@@ -117,34 +64,8 @@ void AudioPullFIFO::fillBuffer(size_t numberOfFrames)
     while (framesProvided < numberOfFrames) {
         m_provider.provideInput(&m_tempBus, m_providerSize);
 
-        size_t part1Length;
-        size_t part2Length;
-        findWrapLengths(m_writeIndex, m_providerSize, part1Length, part2Length);
-
-        size_t numberOfChannels = m_fifoAudioBus.numberOfChannels();
-        
-        for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
-            float* destination = m_fifoAudioBus.channel(channelIndex)->mutableData();
-            const float* source = m_tempBus.channel(channelIndex)->data();
-
-            bool isCopyGood = (part1Length <= m_providerSize
-                               && (part1Length + part2Length) <= m_providerSize
-                               && (m_writeIndex < m_fifoLength)
-                               && (m_writeIndex + part1Length) <= m_fifoLength
-                               && part2Length < m_fifoLength);
-            ASSERT(isCopyGood);
-            if (!isCopyGood)
-                return;
-
-            memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination));
-            // Handle wrap around of the FIFO, if needed.
-            if (part2Length > 0)
-                memcpy(destination, source + part1Length, part2Length * sizeof(*destination));
-        }
+        m_fifo.push(&m_tempBus);
 
-        m_framesInFifo += m_providerSize;
-        ASSERT(m_framesInFifo <= m_fifoLength);
-        m_writeIndex = updateIndex(m_writeIndex, m_providerSize);
         framesProvided += m_providerSize;
     }
 }
index fac19b9..33269ae 100644 (file)
@@ -30,6 +30,7 @@
 #define AudioPullFIFO_h
 
 #include "AudioBus.h"
+#include "AudioFIFO.h"
 #include "AudioSourceProvider.h"
 
 namespace WebCore {
@@ -52,31 +53,14 @@ public:
     void consume(AudioBus* destination, size_t framesToConsume);
 
 private:
-    // Update the FIFO index by the step, with appropriate wrapping around the endpoint.
-    int updateIndex(int index, int step) { return (index + step) % m_fifoLength; }
-
-    void findWrapLengths(size_t index, size_t providerSize, size_t& part1Length, size_t& part2Length);
-    
     // Fill the FIFO buffer with at least |numberOfFrames| more data.
     void fillBuffer(size_t numberOfFrames);
 
     // The provider of the data in our FIFO.
     AudioSourceProvider& m_provider;
 
-    // The FIFO itself. In reality, the FIFO is a circular buffer.
-    AudioBus m_fifoAudioBus;
-
-    // The total available space in the FIFO.
-    size_t m_fifoLength;
-
-    // The number of actual elements in the FIFO
-    size_t m_framesInFifo;
-
-    // Where to start reading from the FIFO.
-    size_t m_readIndex;
-
-    // Where to start writing to the FIFO.
-    size_t m_writeIndex;
+    // The actual FIFO
+    AudioFIFO m_fifo;
 
     // Number of frames of data that the provider will produce per call.
     unsigned int m_providerSize;