MultiChannelResampler does not need to recreate a ChannelProvider for every process call
https://bugs.webkit.org/show_bug.cgi?id=202982

Reviewed by Eric Carlson.

We no longer allocate a new ChannelProvider for every process call.
No observable change of behavior.

* platform/audio/MultiChannelResampler.cpp:
(WebCore::MultiChannelResampler::ChannelProvider::ChannelProvider):
(WebCore::MultiChannelResampler::ChannelProvider::setProvider):
(WebCore::MultiChannelResampler::MultiChannelResampler):
(WebCore::MultiChannelResampler::process):
* platform/audio/MultiChannelResampler.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251230 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 41fb475..71c789f 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,20 @@
+2019-10-17  Youenn Fablet  <youenn@apple.com>
+
+        MultiChannelResampler does not need to recreate a ChannelProvider for every process call
+        https://bugs.webkit.org/show_bug.cgi?id=202982
+
+        Reviewed by Eric Carlson.
+
+        We no longer allocate a new ChannelProvider for every process call.
+        No observable change of behavior.
+
+        * platform/audio/MultiChannelResampler.cpp:
+        (WebCore::MultiChannelResampler::ChannelProvider::ChannelProvider):
+        (WebCore::MultiChannelResampler::ChannelProvider::setProvider):
+        (WebCore::MultiChannelResampler::MultiChannelResampler):
+        (WebCore::MultiChannelResampler::process):
+        * platform/audio/MultiChannelResampler.h:
+
 2019-10-17  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: rework frontend agent construction to allow commands/events to be controlled by the related target's type
diff --git a/Source/WebCore/platform/audio/MultiChannelResampler.cpp b/Source/WebCore/platform/audio/MultiChannelResampler.cpp
index 5bf9ab9..5e6268d 100644
--- a/Source/WebCore/platform/audio/MultiChannelResampler.cpp
+++ b/Source/WebCore/platform/audio/MultiChannelResampler.cpp
@@ -36,21 +36,23 @@
 
 namespace WebCore {
 
-namespace {
-
 // ChannelProvider provides a single channel of audio data (one channel at a time) for each channel
 // of data provided to us in a multi-channel provider.
-
-class ChannelProvider : public AudioSourceProvider {
+class MultiChannelResampler::ChannelProvider : public AudioSourceProvider {
+    WTF_MAKE_FAST_ALLOCATED;
 public:
-    ChannelProvider(AudioSourceProvider* multiChannelProvider, unsigned numberOfChannels)
-        : m_multiChannelProvider(multiChannelProvider)
-        , m_numberOfChannels(numberOfChannels)
-        , m_currentChannel(0)
-        , m_framesToProcess(0)
+    explicit ChannelProvider(unsigned numberOfChannels)
+        : m_numberOfChannels(numberOfChannels)
     {
     }
 
+    void setProvider(AudioSourceProvider* multiChannelProvider)
+    {
+        m_currentChannel = 0;
+        m_framesToProcess = 0;
+        m_multiChannelProvider = multiChannelProvider;
+    }
+
     // provideInput() will be called once for each channel, starting with the first channel.
     // Each time it's called, it will provide the next channel of data.
     void provideInput(AudioBus* bus, size_t framesToProcess) override
@@ -83,23 +85,24 @@
     }
 
 private:
-    AudioSourceProvider* m_multiChannelProvider;
+    AudioSourceProvider* m_multiChannelProvider { nullptr };
     RefPtr<AudioBus> m_multiChannelBus;
-    unsigned m_numberOfChannels;
-    unsigned m_currentChannel;
-    size_t m_framesToProcess; // Used to verify that all channels ask for the same amount.
+    unsigned m_numberOfChannels { 0 };
+    unsigned m_currentChannel { 0 };
+    size_t m_framesToProcess { 0 }; // Used to verify that all channels ask for the same amount.
 };
 
-} // namespace
-
 MultiChannelResampler::MultiChannelResampler(double scaleFactor, unsigned numberOfChannels)
     : m_numberOfChannels(numberOfChannels)
+    , m_channelProvider(makeUnique<ChannelProvider>(m_numberOfChannels))
 {
     // Create each channel's resampler.
     for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex)
         m_kernels.append(makeUnique<SincResampler>(scaleFactor));
 }
 
+MultiChannelResampler::~MultiChannelResampler() = default;
+
 void MultiChannelResampler::process(AudioSourceProvider* provider, AudioBus* destination, size_t framesToProcess)
 {
     ASSERT(m_numberOfChannels == destination->numberOfChannels());
@@ -107,17 +110,19 @@
     // The provider can provide us with multi-channel audio data. But each of our single-channel resamplers (kernels)
     // below requires a provider which provides a single unique channel of data.
     // channelProvider wraps the original multi-channel provider and dishes out one channel at a time.
-    ChannelProvider channelProvider(provider, m_numberOfChannels);
+    m_channelProvider->setProvider(provider);
 
     for (unsigned channelIndex = 0; channelIndex < m_numberOfChannels; ++channelIndex) {
         // Depending on the sample-rate scale factor, and the internal buffering used in a SincResampler
         // kernel, this call to process() will only sometimes call provideInput() on the channelProvider.
         // However, if it calls provideInput() for the first channel, then it will call it for the remaining
         // channels, since they all buffer in the same way and are processing the same number of frames.
-        m_kernels[channelIndex]->process(&channelProvider,
+        m_kernels[channelIndex]->process(m_channelProvider.get(),
                                          destination->channel(channelIndex)->mutableData(),
                                          framesToProcess);
     }
+
+    m_channelProvider->setProvider(nullptr);
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/audio/MultiChannelResampler.h b/Source/WebCore/platform/audio/MultiChannelResampler.h
index 6146e92..ac81bec 100644
--- a/Source/WebCore/platform/audio/MultiChannelResampler.h
+++ b/Source/WebCore/platform/audio/MultiChannelResampler.h
@@ -36,12 +36,13 @@
 namespace WebCore {
 
 class AudioBus;
-    
+
 class MultiChannelResampler final {
     WTF_MAKE_FAST_ALLOCATED;
 public:   
     explicit MultiChannelResampler(double scaleFactor, unsigned numberOfChannels);
-    
+    ~MultiChannelResampler();
+
     // Process given AudioSourceProvider for streaming applications.
     void process(AudioSourceProvider*, AudioBus* destination, size_t framesToProcess);
 
@@ -54,6 +55,9 @@
     Vector<std::unique_ptr<SincResampler>> m_kernels;
     
     unsigned m_numberOfChannels;
+
+    class ChannelProvider;
+    std::unique_ptr<ChannelProvider> m_channelProvider;
 };
 
 } // namespace WebCore