Title: [98792] trunk/Source/WebCore
Revision
98792
Author
[email protected]
Date
2011-10-28 18:47:50 -0700 (Fri, 28 Oct 2011)

Log Message

SincResampler must be able to resample progressively
https://bugs.webkit.org/show_bug.cgi?id=71131

Reviewed by Kenneth Russell.

No new tests.  There is not yet an implementation using progressive resampling to test.

* platform/audio/SincResampler.cpp:
(WebCore::SincResampler::SincResampler):
(WebCore::SincResampler::consumeSource):
(WebCore::SincResampler::process):
* platform/audio/SincResampler.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (98791 => 98792)


--- trunk/Source/WebCore/ChangeLog	2011-10-29 01:31:04 UTC (rev 98791)
+++ trunk/Source/WebCore/ChangeLog	2011-10-29 01:47:50 UTC (rev 98792)
@@ -1,3 +1,18 @@
+2011-10-28  Chris Rogers  <[email protected]>
+
+        SincResampler must be able to resample progressively
+        https://bugs.webkit.org/show_bug.cgi?id=71131
+
+        Reviewed by Kenneth Russell.
+
+        No new tests.  There is not yet an implementation using progressive resampling to test.
+
+        * platform/audio/SincResampler.cpp:
+        (WebCore::SincResampler::SincResampler):
+        (WebCore::SincResampler::consumeSource):
+        (WebCore::SincResampler::process):
+        * platform/audio/SincResampler.h:
+
 2011-10-28  Adam Klein  <[email protected]>
 
         [MutationObservers] Support attributeOldValue for attribute mutations

Modified: trunk/Source/WebCore/platform/audio/SincResampler.cpp (98791 => 98792)


--- trunk/Source/WebCore/platform/audio/SincResampler.cpp	2011-10-29 01:31:04 UTC (rev 98791)
+++ trunk/Source/WebCore/platform/audio/SincResampler.cpp	2011-10-29 01:47:50 UTC (rev 98792)
@@ -32,6 +32,7 @@
 
 #include "SincResampler.h"
 
+#include "AudioBus.h"
 #include <wtf/MathExtras.h>
 
 using namespace std;
@@ -70,11 +71,13 @@
     , m_kernelSize(kernelSize)
     , m_numberOfKernelOffsets(numberOfKernelOffsets)
     , m_kernelStorage(m_kernelSize * (m_numberOfKernelOffsets + 1))
-    , m_virtualSourceIndex(0.0)
+    , m_virtualSourceIndex(0)
     , m_blockSize(512)
     , m_inputBuffer(m_blockSize + m_kernelSize) // See input buffer layout above.
     , m_source(0)
     , m_sourceFramesAvailable(0)
+    , m_sourceProvider(0)
+    , m_isBufferPrimed(false)
 {
     initializeKernel();
 }
@@ -122,28 +125,85 @@
 
 void SincResampler::consumeSource(float* buffer, unsigned numberOfSourceFrames)
 {
-    ASSERT(m_source);
-    if (!m_source)
+    ASSERT(m_sourceProvider);
+    if (!m_sourceProvider)
         return;
     
-    // Clamp to number of frames available and zero-pad.
-    unsigned framesToCopy = min(m_sourceFramesAvailable, numberOfSourceFrames);
-    memcpy(buffer, m_source, sizeof(float) * framesToCopy);
+    // Wrap the provided buffer by an AudioBus for use by the source provider.
+    AudioBus bus(1, numberOfSourceFrames, false);
+    bus.setChannelMemory(0, buffer, numberOfSourceFrames);
     
-    // Zero-pad if necessary.
-    if (framesToCopy < numberOfSourceFrames)
-        memset(buffer + framesToCopy, 0, sizeof(float) * (numberOfSourceFrames - framesToCopy));
-    
-    m_sourceFramesAvailable -= framesToCopy;
-    m_source += numberOfSourceFrames;
+    m_sourceProvider->provideInput(&bus, numberOfSourceFrames);
 }
 
+namespace {
+
+// BufferSourceProvider is an AudioSourceProvider wrapping an in-memory buffer.
+
+class BufferSourceProvider : public AudioSourceProvider {
+public:
+    BufferSourceProvider(float* source, size_t numberOfSourceFrames)
+        : m_source(source)
+        , m_sourceFramesAvailable(numberOfSourceFrames)
+    {
+    }
+    
+    // Consumes samples from the in-memory buffer.
+    virtual void provideInput(AudioBus* bus, size_t framesToProcess)
+    {
+        ASSERT(m_source && bus);
+        if (!m_source || !bus)
+            return;
+            
+        float* buffer = bus->channel(0)->data();
+
+        // Clamp to number of frames available and zero-pad.
+        size_t framesToCopy = min(m_sourceFramesAvailable, framesToProcess);
+        memcpy(buffer, m_source, sizeof(float) * framesToCopy);
+
+        // Zero-pad if necessary.
+        if (framesToCopy < framesToProcess)
+            memset(buffer + framesToCopy, 0, sizeof(float) * (framesToProcess - framesToCopy));
+
+        m_sourceFramesAvailable -= framesToCopy;
+        m_source += framesToCopy;
+    }
+    
+private:
+    float* m_source;
+    size_t m_sourceFramesAvailable;
+};
+
+} // namespace
+
 void SincResampler::process(float* source, float* destination, unsigned numberOfSourceFrames)
 {
-    ASSERT(m_blockSize > m_kernelSize);
-    ASSERT(m_inputBuffer.size() >= m_blockSize + m_kernelSize);
-    ASSERT(!(m_kernelSize % 2));
+    // Resample an in-memory buffer using an AudioSourceProvider.
+    BufferSourceProvider sourceProvider(source, numberOfSourceFrames);
+
+    unsigned numberOfDestinationFrames = static_cast<unsigned>(numberOfSourceFrames / m_scaleFactor);
+    unsigned remaining = numberOfDestinationFrames;
     
+    while (remaining) {
+        unsigned framesThisTime = min(remaining, m_blockSize);
+        process(&sourceProvider, destination, framesThisTime);
+        
+        destination += framesThisTime;
+        remaining -= framesThisTime;
+    }
+}
+
+void SincResampler::process(AudioSourceProvider* sourceProvider, float* destination, size_t framesToProcess)
+{
+    bool isGood = sourceProvider && m_blockSize > m_kernelSize && m_inputBuffer.size() >= m_blockSize + m_kernelSize && !(m_kernelSize % 2);
+    ASSERT(isGood);
+    if (!isGood)
+        return;
+    
+    m_sourceProvider = sourceProvider;
+
+    unsigned numberOfDestinationFrames = framesToProcess;
+    
     // Setup various region pointers in the buffer (see diagram above).
     float* r0 = m_inputBuffer.data() + m_kernelSize / 2;
     float* r1 = m_inputBuffer.data();
@@ -152,17 +212,14 @@
     float* r4 = r0 + m_blockSize;
     float* r5 = r0 + m_kernelSize / 2;
 
-    m_source = source;
-    m_sourceFramesAvailable = numberOfSourceFrames;
-
-    unsigned numberOfDestinationFrames = static_cast<unsigned>(numberOfSourceFrames / m_scaleFactor);
-
     // Step (1)
-    // Prime the input buffer.
-    consumeSource(r0, m_blockSize + m_kernelSize / 2);
+    // Prime the input buffer at the start of the input stream.
+    if (!m_isBufferPrimed) {
+        consumeSource(r0, m_blockSize + m_kernelSize / 2);
+        m_isBufferPrimed = true;
+    }
     
     // Step (2)
-    m_virtualSourceIndex = 0;
 
     while (numberOfDestinationFrames) {
         while (m_virtualSourceIndex < m_blockSize) {
@@ -315,12 +372,12 @@
 
             *destination++ = result;
 
+            // Advance the virtual index.
+            m_virtualSourceIndex += m_scaleFactor;
+
             --numberOfDestinationFrames;
             if (!numberOfDestinationFrames)
                 return;
-
-            // Advance the virtual index.
-            m_virtualSourceIndex += m_scaleFactor;
         }
 
         // Wrap back around to the start.

Modified: trunk/Source/WebCore/platform/audio/SincResampler.h (98791 => 98792)


--- trunk/Source/WebCore/platform/audio/SincResampler.h	2011-10-29 01:31:04 UTC (rev 98791)
+++ trunk/Source/WebCore/platform/audio/SincResampler.h	2011-10-29 01:47:50 UTC (rev 98792)
@@ -30,6 +30,7 @@
 #define SincResampler_h
 
 #include "AudioArray.h"
+#include "AudioSourceProvider.h"
 
 namespace WebCore {
 
@@ -44,10 +45,10 @@
     
     // Processes numberOfSourceFrames from source to produce numberOfSourceFrames / scaleFactor frames in destination.
     void process(float* source, float* destination, unsigned numberOfSourceFrames);
-    
-    // FIXME: we can add a process() method which takes an input source callback function for streaming applications
-    // where the entire input buffer is not all available.
-    
+
+    // Process with input source callback function for streaming applications.
+    void process(AudioSourceProvider*, float* destination, size_t framesToProcess);
+
 protected:
     void initializeKernel();
     void consumeSource(float* buffer, unsigned numberOfSourceFrames);
@@ -72,6 +73,12 @@
 
     float* m_source;
     unsigned m_sourceFramesAvailable;
+    
+    // m_sourceProvider is used to provide the audio input stream to the resampler.
+    AudioSourceProvider* m_sourceProvider;    
+
+    // The buffer is primed once at the very beginning of processing.
+    bool m_isBufferPrimed;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to