Add AudioSummingJunction class to handle fan-in (abstracted from AudioNodeInput)
authorcrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 May 2012 19:56:51 +0000 (19:56 +0000)
committercrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 May 2012 19:56:51 +0000 (19:56 +0000)
https://bugs.webkit.org/show_bug.cgi?id=86396

Reviewed by Kenneth Russell.

No new tests.  Existing layout tests already extensively test summing.

* CMakeLists.txt:
* GNUmakefile.list.am:
Add AudioSummingJunction files to makefiles.

* Modules/webaudio/AudioContext.cpp:
* Modules/webaudio/AudioContext.h:
(WebCore::AudioContext::handlePreRenderTasks):
(WebCore::AudioContext::handlePostRenderTasks):
(WebCore::AudioContext::deleteMarkedNodes):
(WebCore::AudioContext::markSummingJunctionDirty):
(WebCore::AudioContext::removeMarkedSummingJunction):
(WebCore::AudioContext::handleDirtyAudioSummingJunctions):
Simple munge from AudioNodeInput -> AudioSummingJunction

* Modules/webaudio/AudioNodeInput.cpp:
* Modules/webaudio/AudioNodeInput.h:
(WebCore::AudioNodeInput::AudioNodeInput):
(WebCore::AudioNodeInput::didUpdate):
Remove logic from AudioNodeInput which now is being moved to AudioSummingJunction.

* Modules/webaudio/AudioSummingJunction.cpp: Added.
* Modules/webaudio/AudioSummingJunction.h: Added.
(WebCore::AudioSummingJunction::AudioSummingJunction):
(WebCore::AudioSummingJunction::~AudioSummingJunction):
(WebCore::AudioSummingJunction::changedOutputs):
(WebCore::AudioSummingJunction::updateRenderingState):
(WebCore::AudioSummingJunction::context):
(WebCore::AudioSummingJunction::numberOfRenderingConnections):
(WebCore::AudioSummingJunction::renderingOutput):
(WebCore::AudioSummingJunction::isConnected):
(WebCore::AudioSummingJunction::numberOfConnections):
Add AudioSummingJunction which is an abstraction to manage/track the connections from AudioNodeOutputs
representing the fan-in points for unity gain summing junctions.

* WebCore.gypi:
* WebCore.xcodeproj/project.pbxproj:
Add AudioSummingJunction files to makefiles.

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

Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Modules/webaudio/AudioContext.cpp
Source/WebCore/Modules/webaudio/AudioContext.h
Source/WebCore/Modules/webaudio/AudioNodeInput.cpp
Source/WebCore/Modules/webaudio/AudioNodeInput.h
Source/WebCore/Modules/webaudio/AudioSummingJunction.cpp [new file with mode: 0644]
Source/WebCore/Modules/webaudio/AudioSummingJunction.h [new file with mode: 0644]
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.xcodeproj/project.pbxproj

index 48e4bac..cece18b 100644 (file)
@@ -2453,6 +2453,7 @@ IF (ENABLE_WEB_AUDIO)
         Modules/webaudio/AudioParamTimeline.cpp
         Modules/webaudio/AudioProcessingEvent.cpp
         Modules/webaudio/AudioScheduledSourceNode.cpp
+        Modules/webaudio/AudioSummingJunction.cpp
         Modules/webaudio/BiquadDSPKernel.cpp
         Modules/webaudio/BiquadFilterNode.cpp
         Modules/webaudio/BiquadProcessor.cpp
index 1eaf06d..04679a5 100644 (file)
@@ -1,3 +1,50 @@
+2012-05-15  Chris Rogers  <crogers@google.com>
+
+        Add AudioSummingJunction class to handle fan-in (abstracted from AudioNodeInput)
+        https://bugs.webkit.org/show_bug.cgi?id=86396
+
+        Reviewed by Kenneth Russell.
+
+        No new tests.  Existing layout tests already extensively test summing.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        Add AudioSummingJunction files to makefiles.
+
+        * Modules/webaudio/AudioContext.cpp:
+        * Modules/webaudio/AudioContext.h:
+        (WebCore::AudioContext::handlePreRenderTasks):
+        (WebCore::AudioContext::handlePostRenderTasks):
+        (WebCore::AudioContext::deleteMarkedNodes):
+        (WebCore::AudioContext::markSummingJunctionDirty):
+        (WebCore::AudioContext::removeMarkedSummingJunction):
+        (WebCore::AudioContext::handleDirtyAudioSummingJunctions):
+        Simple munge from AudioNodeInput -> AudioSummingJunction
+
+        * Modules/webaudio/AudioNodeInput.cpp:
+        * Modules/webaudio/AudioNodeInput.h:
+        (WebCore::AudioNodeInput::AudioNodeInput):
+        (WebCore::AudioNodeInput::didUpdate):
+        Remove logic from AudioNodeInput which now is being moved to AudioSummingJunction.
+
+        * Modules/webaudio/AudioSummingJunction.cpp: Added.
+        * Modules/webaudio/AudioSummingJunction.h: Added.
+        (WebCore::AudioSummingJunction::AudioSummingJunction):
+        (WebCore::AudioSummingJunction::~AudioSummingJunction):
+        (WebCore::AudioSummingJunction::changedOutputs):
+        (WebCore::AudioSummingJunction::updateRenderingState):
+        (WebCore::AudioSummingJunction::context):
+        (WebCore::AudioSummingJunction::numberOfRenderingConnections):
+        (WebCore::AudioSummingJunction::renderingOutput):
+        (WebCore::AudioSummingJunction::isConnected):
+        (WebCore::AudioSummingJunction::numberOfConnections):
+        Add AudioSummingJunction which is an abstraction to manage/track the connections from AudioNodeOutputs
+        representing the fan-in points for unity gain summing junctions.
+
+        * WebCore.gypi:
+        * WebCore.xcodeproj/project.pbxproj:
+        Add AudioSummingJunction files to makefiles.
+
 2012-05-15  Dan Bernstein  <mitz@apple.com>
 
         Ruby annotation is incorrectly identified as a paragraph boundary
index b923dc6..3a6b103 100644 (file)
@@ -5533,6 +5533,8 @@ webcore_sources += \
        Source/WebCore/Modules/webaudio/AudioProcessingEvent.h \
        Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.cpp \
        Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.h \
+       Source/WebCore/Modules/webaudio/AudioSummingJunction.cpp \
+       Source/WebCore/Modules/webaudio/AudioSummingJunction.h \
        Source/WebCore/Modules/webaudio/AudioSourceNode.h \
        Source/WebCore/Modules/webaudio/BiquadDSPKernel.cpp \
        Source/WebCore/Modules/webaudio/BiquadDSPKernel.h \
index f743b11..ea2d579 100644 (file)
@@ -673,8 +673,8 @@ void AudioContext::handlePreRenderTasks()
     // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes.
     bool mustReleaseLock;
     if (tryLock(mustReleaseLock)) {
-        // Fixup the state of any dirty AudioNodeInputs and AudioNodeOutputs.
-        handleDirtyAudioNodeInputs();
+        // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
+        handleDirtyAudioSummingJunctions();
         handleDirtyAudioNodeOutputs();
 
         updateAutomaticPullNodes();
@@ -703,8 +703,8 @@ void AudioContext::handlePostRenderTasks()
         // Ref-counted objects held by certain AudioNodes may not be thread-safe.
         scheduleNodeDeletion();
 
-        // Fixup the state of any dirty AudioNodeInputs and AudioNodeOutputs.
-        handleDirtyAudioNodeInputs();
+        // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
+        handleDirtyAudioSummingJunctions();
         handleDirtyAudioNodeOutputs();
 
         updateAutomaticPullNodes();
@@ -778,10 +778,10 @@ void AudioContext::deleteMarkedNodes()
         AudioNode* node = m_nodesToDelete[n - 1];
         m_nodesToDelete.removeLast();
 
-        // Before deleting the node, clear out any AudioNodeInputs from m_dirtyAudioNodeInputs.
+        // Before deleting the node, clear out any AudioNodeInputs from m_dirtySummingJunctions.
         unsigned numberOfInputs = node->numberOfInputs();
         for (unsigned i = 0; i < numberOfInputs; ++i)
-            m_dirtyAudioNodeInputs.remove(node->input(i));
+            m_dirtySummingJunctions.remove(node->input(i));
 
         // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs.
         unsigned numberOfOutputs = node->numberOfOutputs();
@@ -795,10 +795,17 @@ void AudioContext::deleteMarkedNodes()
     m_isDeletionScheduled = false;
 }
 
-void AudioContext::markAudioNodeInputDirty(AudioNodeInput* input)
+void AudioContext::markSummingJunctionDirty(AudioSummingJunction* summingJunction)
 {
     ASSERT(isGraphOwner());    
-    m_dirtyAudioNodeInputs.add(input);
+    m_dirtySummingJunctions.add(summingJunction);
+}
+
+void AudioContext::removeMarkedSummingJunction(AudioSummingJunction* summingJunction)
+{
+    ASSERT(isMainThread());
+    AutoLocker locker(this);
+    m_dirtySummingJunctions.remove(summingJunction);
 }
 
 void AudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output)
@@ -807,14 +814,14 @@ void AudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output)
     m_dirtyAudioNodeOutputs.add(output);
 }
 
-void AudioContext::handleDirtyAudioNodeInputs()
+void AudioContext::handleDirtyAudioSummingJunctions()
 {
     ASSERT(isGraphOwner());    
 
-    for (HashSet<AudioNodeInput*>::iterator i = m_dirtyAudioNodeInputs.begin(); i != m_dirtyAudioNodeInputs.end(); ++i)
+    for (HashSet<AudioSummingJunction*>::iterator i = m_dirtySummingJunctions.begin(); i != m_dirtySummingJunctions.end(); ++i)
         (*i)->updateRenderingState();
 
-    m_dirtyAudioNodeInputs.clear();
+    m_dirtySummingJunctions.clear();
 }
 
 void AudioContext::handleDirtyAudioNodeOutputs()
index edb87e7..1b742f7 100644 (file)
@@ -55,6 +55,7 @@ class AudioChannelSplitter;
 class AudioGainNode;
 class AudioPannerNode;
 class AudioListener;
+class AudioSummingJunction;
 class BiquadFilterNode;
 class DelayNode;
 class Document;
@@ -218,9 +219,12 @@ public:
     void handleDeferredFinishDerefs();
 
     // Only accessed when the graph lock is held.
-    void markAudioNodeInputDirty(AudioNodeInput*);
+    void markSummingJunctionDirty(AudioSummingJunction*);
     void markAudioNodeOutputDirty(AudioNodeOutput*);
 
+    // Must be called on main thread.
+    void removeMarkedSummingJunction(AudioSummingJunction*);
+
     // EventTarget
     virtual const AtomicString& interfaceName() const;
     virtual ScriptExecutionContext* scriptExecutionContext() const;
@@ -284,9 +288,9 @@ private:
     bool m_isDeletionScheduled;
 
     // Only accessed when the graph lock is held.
-    HashSet<AudioNodeInput*> m_dirtyAudioNodeInputs;
+    HashSet<AudioSummingJunction*> m_dirtySummingJunctions;
     HashSet<AudioNodeOutput*> m_dirtyAudioNodeOutputs;
-    void handleDirtyAudioNodeInputs();
+    void handleDirtyAudioSummingJunctions();
     void handleDirtyAudioNodeOutputs();
 
     // For the sake of thread safety, we maintain a seperate Vector of automatic pull nodes for rendering in m_renderingAutomaticPullNodes.
index 374f27a..6c2a222 100644 (file)
@@ -38,8 +38,8 @@ using namespace std;
 namespace WebCore {
 
 AudioNodeInput::AudioNodeInput(AudioNode* node)
-    : m_node(node)
-    , m_renderingStateNeedUpdating(false)
+    : AudioSummingJunction(node->context())
+    , m_node(node)
 {
     // Set to mono by default.
     m_internalSummingBus = adoptPtr(new AudioBus(1, AudioNode::ProcessingSizeInFrames));
@@ -130,33 +130,9 @@ void AudioNodeInput::enable(AudioNodeOutput* output)
     node()->deref(AudioNode::RefTypeDisabled); // Note: it's important to return immediately after all deref() calls since the node may be deleted.
 }
 
-void AudioNodeInput::changedOutputs()
+void AudioNodeInput::didUpdate()
 {
-    ASSERT(context()->isGraphOwner());
-    if (!m_renderingStateNeedUpdating && !node()->isMarkedForDeletion()) {    
-        context()->markAudioNodeInputDirty(this);
-        m_renderingStateNeedUpdating = true;
-    }
-}
-
-void AudioNodeInput::updateRenderingState()
-{
-    ASSERT(context()->isAudioThread() && context()->isGraphOwner());
-    
-    if (m_renderingStateNeedUpdating && !node()->isMarkedForDeletion()) {
-        // Copy from m_outputs to m_renderingOutputs.
-        m_renderingOutputs.resize(m_outputs.size());
-        unsigned j = 0;
-        for (HashSet<AudioNodeOutput*>::iterator i = m_outputs.begin(); i != m_outputs.end(); ++i, ++j) {
-            AudioNodeOutput* output = *i;
-            m_renderingOutputs[j] = output;
-            output->updateRenderingState();
-        }
-
-        node()->checkNumberOfChannelsForInput(this);
-        
-        m_renderingStateNeedUpdating = false;
-    }
+    node()->checkNumberOfChannelsForInput(this);
 }
 
 void AudioNodeInput::updateInternalBus()
index 98b7f46..76a4161 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "AudioBus.h"
 #include "AudioNode.h"
+#include "AudioSummingJunction.h"
 #include <wtf/HashSet.h>
 #include <wtf/Vector.h>
 
@@ -39,13 +40,16 @@ class AudioNodeOutput;
 // In the case of multiple connections, the input will act as a unity-gain summing junction, mixing all the outputs.
 // The number of channels of the input's bus is the maximum of the number of channels of all its connections.
 
-class AudioNodeInput {
+class AudioNodeInput : public AudioSummingJunction {
 public:
     AudioNodeInput(AudioNode*);
 
+    // AudioSummingJunction
+    virtual bool canUpdateState() OVERRIDE { return !node()->isMarkedForDeletion(); }
+    virtual void didUpdate() OVERRIDE;
+
     // Can be called from any thread.
     AudioNode* node() const { return m_node; }
-    AudioContext* context() { return m_node->context(); }
 
     // Must be called with the context's graph lock.
     void connect(AudioNodeOutput*);
@@ -68,46 +72,16 @@ public:
     // Called from context's audio thread.
     AudioBus* bus();
     
-    // This copies m_outputs to m_renderingOutputs.  Please see comments for these lists below.
-    // This must be called when we own the context's graph lock in the audio thread at the very start or end of the render quantum.
-    void updateRenderingState();
-
     // updateInternalBus() updates m_internalSummingBus appropriately for the number of channels.
     // This must be called when we own the context's graph lock in the audio thread at the very start or end of the render quantum.
     void updateInternalBus();
 
-    // Rendering code accesses its version of the current connections here.
-    unsigned numberOfRenderingConnections() const { return m_renderingOutputs.size(); }
-    AudioNodeOutput* renderingOutput(unsigned i) { return m_renderingOutputs[i]; }
-    const AudioNodeOutput* renderingOutput(unsigned i) const { return m_renderingOutputs[i]; }
-    bool isConnected() const { return numberOfRenderingConnections() > 0; }
-
     // The number of channels of the connection with the largest number of channels.
     unsigned numberOfChannels() const;        
     
 private:
     AudioNode* m_node;
 
-    // m_outputs contains the AudioNodeOutputs representing current connections which are not disabled.
-    // The rendering code should never use this directly, but instead uses m_renderingOutputs.
-    HashSet<AudioNodeOutput*> m_outputs;
-
-    // numberOfConnections() should never be called from the audio rendering thread.
-    // Instead numberOfRenderingConnections() and renderingOutput() should be used.
-    unsigned numberOfConnections() const { return m_outputs.size(); }
-
-    // This must be called whenever we modify m_outputs.
-    void changedOutputs();
-    
-    // m_renderingOutputs is a copy of m_outputs which will never be modified during the graph rendering on the audio thread.
-    // This is the list which is used by the rendering code.
-    // Whenever m_outputs is modified, the context is told so it can later update m_renderingOutputs from m_outputs at a safe time.
-    // Most of the time, m_renderingOutputs is identical to m_outputs.
-    Vector<AudioNodeOutput*> m_renderingOutputs;
-
-    // m_renderingStateNeedUpdating keeps track if m_outputs is modified.
-    bool m_renderingStateNeedUpdating;
-
     // The number of channels of the rendering connection with the largest number of channels.
     unsigned numberOfRenderingChannels();
 
diff --git a/Source/WebCore/Modules/webaudio/AudioSummingJunction.cpp b/Source/WebCore/Modules/webaudio/AudioSummingJunction.cpp
new file mode 100644 (file)
index 0000000..ad81cad
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 "AudioSummingJunction.h"
+
+#include "AudioContext.h"
+#include "AudioNodeOutput.h"
+#include <algorithm>
+
+using namespace std;
+
+namespace WebCore {
+
+AudioSummingJunction::AudioSummingJunction(AudioContext* context)
+    : m_context(context)
+    , m_renderingStateNeedUpdating(false)
+{
+}
+
+AudioSummingJunction::~AudioSummingJunction()
+{
+    if (m_renderingStateNeedUpdating && m_context.get())
+        m_context->removeMarkedSummingJunction(this);
+}
+
+void AudioSummingJunction::changedOutputs()
+{
+    ASSERT(context()->isGraphOwner());
+    if (!m_renderingStateNeedUpdating && canUpdateState()) {
+        context()->markSummingJunctionDirty(this);
+        m_renderingStateNeedUpdating = true;
+    }
+}
+
+void AudioSummingJunction::updateRenderingState()
+{
+    ASSERT(context()->isAudioThread() && context()->isGraphOwner());
+
+    if (m_renderingStateNeedUpdating && canUpdateState()) {
+        // Copy from m_outputs to m_renderingOutputs.
+        m_renderingOutputs.resize(m_outputs.size());
+        unsigned j = 0;
+        for (HashSet<AudioNodeOutput*>::iterator i = m_outputs.begin(); i != m_outputs.end(); ++i, ++j) {
+            AudioNodeOutput* output = *i;
+            m_renderingOutputs[j] = output;
+            output->updateRenderingState();
+        }
+
+        didUpdate();
+
+        m_renderingStateNeedUpdating = false;
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/Modules/webaudio/AudioSummingJunction.h b/Source/WebCore/Modules/webaudio/AudioSummingJunction.h
new file mode 100644 (file)
index 0000000..dd5e442
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 AudioSummingJunction_h
+#define AudioSummingJunction_h
+
+#include "AudioBus.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AudioContext;
+class AudioNodeOutput;
+
+// An AudioSummingJunction represents a point where zero, one, or more AudioNodeOutputs connect.
+
+class AudioSummingJunction {
+public:
+    AudioSummingJunction(AudioContext*);
+    virtual ~AudioSummingJunction();
+
+    // Can be called from any thread.
+    AudioContext* context() { return m_context.get(); }
+
+    // This must be called whenever we modify m_outputs.
+    void changedOutputs();
+
+    // This copies m_outputs to m_renderingOutputs. Please see comments for these lists below.
+    // This must be called when we own the context's graph lock in the audio thread at the very start or end of the render quantum.
+    void updateRenderingState();
+
+    // Rendering code accesses its version of the current connections here.
+    unsigned numberOfRenderingConnections() const { return m_renderingOutputs.size(); }
+    AudioNodeOutput* renderingOutput(unsigned i) { return m_renderingOutputs[i]; }
+    const AudioNodeOutput* renderingOutput(unsigned i) const { return m_renderingOutputs[i]; }
+    bool isConnected() const { return numberOfRenderingConnections() > 0; }
+
+    virtual bool canUpdateState() = 0;
+    virtual void didUpdate() = 0;
+
+protected:
+    RefPtr<AudioContext> m_context;
+
+    // m_outputs contains the AudioNodeOutputs representing current connections which are not disabled.
+    // The rendering code should never use this directly, but instead uses m_renderingOutputs.
+    HashSet<AudioNodeOutput*> m_outputs;
+
+    // numberOfConnections() should never be called from the audio rendering thread.
+    // Instead numberOfRenderingConnections() and renderingOutput() should be used.
+    unsigned numberOfConnections() const { return m_outputs.size(); }
+
+    // m_renderingOutputs is a copy of m_outputs which will never be modified during the graph rendering on the audio thread.
+    // This is the list which is used by the rendering code.
+    // Whenever m_outputs is modified, the context is told so it can later update m_renderingOutputs from m_outputs at a safe time.
+    // Most of the time, m_renderingOutputs is identical to m_outputs.
+    Vector<AudioNodeOutput*> m_renderingOutputs;
+
+    // m_renderingStateNeedUpdating keeps track if m_outputs is modified.
+    bool m_renderingStateNeedUpdating;
+};
+
+} // namespace WebCore
+
+#endif // AudioSummingJunction_h
index ef82413..05a950b 100644 (file)
             'Modules/webaudio/AudioScheduledSourceNode.cpp',
             'Modules/webaudio/AudioScheduledSourceNode.h',
             'Modules/webaudio/AudioSourceNode.h',
+            'Modules/webaudio/AudioSummingJunction.cpp',
+            'Modules/webaudio/AudioSummingJunction.h',
             'Modules/webaudio/AsyncAudioDecoder.cpp',
             'Modules/webaudio/AsyncAudioDecoder.h',
             'Modules/webaudio/BiquadDSPKernel.cpp',
index c006240..8ba540b 100644 (file)
                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 */; };
+               FDB052DF1561A42C00B500D6 /* AudioSummingJunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FDB052DD1561A42C00B500D6 /* AudioSummingJunction.cpp */; };
+               FDB052E01561A42C00B500D6 /* AudioSummingJunction.h in Headers */ = {isa = PBXBuildFile; fileRef = FDB052DE1561A42C00B500D6 /* AudioSummingJunction.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 */; };
                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>"; };
+               FDB052DD1561A42C00B500D6 /* AudioSummingJunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioSummingJunction.cpp; sourceTree = "<group>"; };
+               FDB052DE1561A42C00B500D6 /* AudioSummingJunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioSummingJunction.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>"; };
                                FD315FD712B0267600C1A359 /* AudioProcessingEvent.idl */,
                                FD8C46E9154608E700A5910C /* AudioScheduledSourceNode.cpp */,
                                FD8C46EA154608E700A5910C /* AudioScheduledSourceNode.h */,
+                               FDB052DD1561A42C00B500D6 /* AudioSummingJunction.cpp */,
+                               FDB052DE1561A42C00B500D6 /* AudioSummingJunction.h */,
                                FD315FD812B0267600C1A359 /* AudioSourceNode.h */,
                                FD315FD912B0267600C1A359 /* AudioSourceNode.idl */,
                                FD315FDA12B0267600C1A359 /* BiquadDSPKernel.cpp */,
                                B658FFA21522EF3A00DD5595 /* JSRadioNodeList.h in Headers */,
                                B658FFA61522EFAA00DD5595 /* RadioNodeList.h in Headers */,
                                29A309B11561CAC400BBD8E5 /* VisitedLinks.h in Headers */,
+                               FDB052E01561A42C00B500D6 /* AudioSummingJunction.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                B658FFA51522EFAA00DD5595 /* RadioNodeList.cpp in Sources */,
                                29A309AC1561C99B00BBD8E5 /* RunLoopCF.cpp in Sources */,
                                29A309B01561CAC400BBD8E5 /* VisitedLinks.cpp in Sources */,
+                               FDB052DF1561A42C00B500D6 /* AudioSummingJunction.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };