[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 14:59:29 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 7c442118f47d13e6fc7887c80438432a8684e6a5
Author: crogers at google.com <crogers at google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Oct 27 01:59:08 2010 +0000

    2010-10-26  Chris Rogers  <crogers at google.com>
    
            Reviewed by Kenneth Russell.
    
            Add AudioNodeInput files
            https://bugs.webkit.org/show_bug.cgi?id=45577
    
            No new tests since audio API is not yet implemented.
    
            * webaudio/AudioNodeInput.cpp: Added.
            (WebCore::AudioNodeInput::AudioNodeInput):
            (WebCore::AudioNodeInput::connect):
            (WebCore::AudioNodeInput::disconnect):
            (WebCore::AudioNodeInput::disable):
            (WebCore::AudioNodeInput::enable):
            (WebCore::AudioNodeInput::changedOutputs):
            (WebCore::AudioNodeInput::updateRenderingState):
            (WebCore::AudioNodeInput::numberOfChannels):
            (WebCore::AudioNodeInput::numberOfRenderingChannels):
            (WebCore::AudioNodeInput::bus):
            (WebCore::AudioNodeInput::internalSummingBus):
            (WebCore::AudioNodeInput::sumAllConnections):
            (WebCore::AudioNodeInput::pull):
            * webaudio/AudioNodeInput.h: Added.
            (WebCore::AudioNodeInput::node):
            (WebCore::AudioNodeInput::context):
            (WebCore::AudioNodeInput::numberOfRenderingConnections):
            (WebCore::AudioNodeInput::renderingOutput):
            (WebCore::AudioNodeInput::isConnected):
            (WebCore::AudioNodeInput::numberOfConnections):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@70599 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 11dc741..226f092 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,34 @@
+2010-10-26  Chris Rogers  <crogers at google.com>
+
+        Reviewed by Kenneth Russell.
+
+        Add AudioNodeInput files
+        https://bugs.webkit.org/show_bug.cgi?id=45577
+
+        No new tests since audio API is not yet implemented.
+
+        * webaudio/AudioNodeInput.cpp: Added.
+        (WebCore::AudioNodeInput::AudioNodeInput):
+        (WebCore::AudioNodeInput::connect):
+        (WebCore::AudioNodeInput::disconnect):
+        (WebCore::AudioNodeInput::disable):
+        (WebCore::AudioNodeInput::enable):
+        (WebCore::AudioNodeInput::changedOutputs):
+        (WebCore::AudioNodeInput::updateRenderingState):
+        (WebCore::AudioNodeInput::numberOfChannels):
+        (WebCore::AudioNodeInput::numberOfRenderingChannels):
+        (WebCore::AudioNodeInput::bus):
+        (WebCore::AudioNodeInput::internalSummingBus):
+        (WebCore::AudioNodeInput::sumAllConnections):
+        (WebCore::AudioNodeInput::pull):
+        * webaudio/AudioNodeInput.h: Added.
+        (WebCore::AudioNodeInput::node):
+        (WebCore::AudioNodeInput::context):
+        (WebCore::AudioNodeInput::numberOfRenderingConnections):
+        (WebCore::AudioNodeInput::renderingOutput):
+        (WebCore::AudioNodeInput::isConnected):
+        (WebCore::AudioNodeInput::numberOfConnections):
+
 2010-10-26  MORITA Hajime  <morrita at google.com>
 
         Reviewed by Tony Chang.
diff --git a/WebCore/webaudio/AudioNodeInput.cpp b/WebCore/webaudio/AudioNodeInput.cpp
new file mode 100644
index 0000000..9fd1852
--- /dev/null
+++ b/WebCore/webaudio/AudioNodeInput.cpp
@@ -0,0 +1,270 @@
+/*
+ * 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.
+ *
+ * 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 "AudioNodeInput.h"
+
+#include "AudioContext.h"
+#include "AudioNode.h"
+#include "AudioNodeOutput.h"
+#include <algorithm>
+
+using namespace std;
+ 
+namespace WebCore {
+
+AudioNodeInput::AudioNodeInput(AudioNode* node)
+    : m_node(node)
+    , m_renderingStateNeedUpdating(false)
+{
+    m_monoSummingBus = adoptPtr(new AudioBus(1, AudioNode::ProcessingSizeInFrames));
+    m_stereoSummingBus = adoptPtr(new AudioBus(2, AudioNode::ProcessingSizeInFrames));
+}
+
+void AudioNodeInput::connect(AudioNodeOutput* output)
+{
+    ASSERT(context()->isGraphOwner());
+    
+    ASSERT(output && node());
+    if (!output || !node())
+        return;
+
+    // Check if we're already connected to this output.
+    if (m_outputs.contains(output))
+        return;
+        
+    output->addInput(this);
+    m_outputs.add(output);
+    changedOutputs();
+
+    // Sombody has just connected to us, so count it as a reference.
+    node()->ref(AudioNode::RefTypeConnection);
+}
+
+void AudioNodeInput::disconnect(AudioNodeOutput* output)
+{
+    ASSERT(context()->isGraphOwner());
+
+    ASSERT(output && node());
+    if (!output || !node())
+        return;
+
+    // First try to disconnect from "active" connections.
+    if (m_outputs.contains(output)) {
+        m_outputs.remove(output);
+        changedOutputs();
+        output->removeInput(this);
+        node()->deref(AudioNode::RefTypeConnection); // Note: it's important to return immediately after all deref() calls since the node may be deleted.
+        return;
+    }
+    
+    // Otherwise, try to disconnect from disabled connections.
+    if (m_disabledOutputs.contains(output)) {
+        m_disabledOutputs.remove(output);
+        output->removeInput(this);
+        node()->deref(AudioNode::RefTypeDisabled); // Note: it's important to return immediately after all deref() calls since the node may be deleted.
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+}
+
+void AudioNodeInput::disable(AudioNodeOutput* output)
+{
+    ASSERT(context()->isGraphOwner());
+
+    ASSERT(output && node());
+    if (!output || !node())
+        return;
+
+    ASSERT(m_outputs.contains(output));
+    
+    m_disabledOutputs.add(output);
+    m_outputs.remove(output);
+    changedOutputs();
+
+    node()->ref(AudioNode::RefTypeDisabled);
+    node()->deref(AudioNode::RefTypeConnection); // Note: it's important to return immediately after all deref() calls since the node may be deleted.
+}
+
+void AudioNodeInput::enable(AudioNodeOutput* output)
+{
+    ASSERT(context()->isGraphOwner());
+
+    ASSERT(output && node());
+    if (!output || !node())
+        return;
+
+    ASSERT(m_disabledOutputs.contains(output));
+
+    // Move output from disabled list to active list.
+    m_outputs.add(output);
+    m_disabledOutputs.remove(output);
+    changedOutputs();
+
+    node()->ref(AudioNode::RefTypeConnection);
+    node()->deref(AudioNode::RefTypeDisabled); // Note: it's important to return immediately after all deref() calls since the node may be deleted.
+}
+
+void AudioNodeInput::changedOutputs()
+{
+    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;
+    }
+}
+
+unsigned AudioNodeInput::numberOfChannels() const
+{
+    // Find the number of channels of the connection with the largest number of channels.
+    unsigned maxChannels = 1; // one channel is the minimum allowed
+
+    for (HashSet<AudioNodeOutput*>::iterator i = m_outputs.begin(); i != m_outputs.end(); ++i) {
+        AudioNodeOutput* output = *i;
+        maxChannels = max(maxChannels, output->bus()->numberOfChannels());
+    }
+    
+    return maxChannels;
+}
+
+unsigned AudioNodeInput::numberOfRenderingChannels()
+{
+    ASSERT(context()->isAudioThread());
+
+    // Find the number of channels of the rendering connection with the largest number of channels.
+    unsigned maxChannels = 1; // one channel is the minimum allowed
+
+    for (unsigned i = 0; i < numberOfRenderingConnections(); ++i)
+        maxChannels = max(maxChannels, renderingOutput(i)->bus()->numberOfChannels());
+    
+    return maxChannels;
+}
+
+AudioBus* AudioNodeInput::bus()
+{
+    ASSERT(context()->isAudioThread());
+
+    // Handle single connection specially to allow for in-place processing.
+    if (numberOfRenderingConnections() == 1)
+        return renderingOutput(0)->bus();
+
+    // Multiple connections case (or no connections).
+    return internalSummingBus();
+}
+
+AudioBus* AudioNodeInput::internalSummingBus()
+{
+    ASSERT(context()->isAudioThread());
+
+    // We must pick a summing bus which is the right size to handle the largest connection.
+    switch (numberOfRenderingChannels()) {
+    case 1:
+        return m_monoSummingBus.get();
+    case 2:
+        return m_stereoSummingBus.get();
+    // FIXME: could implement more than just mono and stereo mixing in the future
+    }
+    
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+void AudioNodeInput::sumAllConnections(AudioBus* summingBus, size_t framesToProcess)
+{
+    ASSERT(context()->isAudioThread());
+
+    // We shouldn't be calling this method if there's only one connection, since it's less efficient.
+    ASSERT(numberOfRenderingConnections() > 1);
+
+    ASSERT(summingBus);
+    if (!summingBus)
+        return;
+        
+    summingBus->zero();
+
+    for (unsigned i = 0; i < numberOfRenderingConnections(); ++i) {
+        AudioNodeOutput* output = renderingOutput(i);
+        ASSERT(output);
+
+        // Render audio from this output.
+        AudioBus* connectionBus = output->pull(0, framesToProcess);
+
+        // Sum, with unity-gain.
+        summingBus->sumFrom(*connectionBus);
+    }
+}
+
+AudioBus* AudioNodeInput::pull(AudioBus* inPlaceBus, size_t framesToProcess)
+{
+    ASSERT(context()->isAudioThread());
+
+    // Handle single connection case.
+    if (numberOfRenderingConnections() == 1) {
+        // The output will optimize processing using inPlaceBus if it's able.
+        AudioNodeOutput* output = this->renderingOutput(0);
+        return output->pull(inPlaceBus, framesToProcess);
+    }
+
+    AudioBus* internalSummingBus = this->internalSummingBus();
+
+    if (!numberOfRenderingConnections()) {
+        // At least, generate silence if we're not connected to anything.
+        // FIXME: if we wanted to get fancy, we could propagate a 'silent hint' here to optimize the downstream graph processing.
+        internalSummingBus->zero();
+        return internalSummingBus;
+    }
+
+    // Handle multiple connections case.
+    sumAllConnections(internalSummingBus, framesToProcess);
+    
+    return internalSummingBus;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/webaudio/AudioNodeInput.h b/WebCore/webaudio/AudioNodeInput.h
new file mode 100644
index 0000000..1d90986
--- /dev/null
+++ b/WebCore/webaudio/AudioNodeInput.h
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ *
+ * 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 AudioNodeInput_h
+#define AudioNodeInput_h
+
+#include "AudioBus.h"
+#include "AudioNode.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AudioNode;
+class AudioNodeOutput;
+
+// An AudioNodeInput represents an input to an AudioNode and can be connected from one or more AudioNodeOutputs.
+// 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 {
+public:
+    AudioNodeInput(AudioNode*);
+
+    // 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*);
+    void disconnect(AudioNodeOutput*);
+
+    // disable() will take the output out of the active connections list and set aside in a disabled list.
+    // enable() will put the output back into the active connections list.
+    // Must be called with the context's graph lock.
+    void enable(AudioNodeOutput*);
+    void disable(AudioNodeOutput*);
+
+    // pull() processes all of the AudioNodes connected to us.
+    // In the case of multiple connections it sums the result into an internal summing bus.
+    // In the single connection case, it allows in-place processing where possible using inPlaceBus.
+    // It returns the bus which it rendered into, returning inPlaceBus if in-place processing was performed.
+    // Called from context's audio thread.
+    AudioBus* pull(AudioBus* inPlaceBus, size_t framesToProcess);
+
+    // bus() contains the rendered audio after pull() has been called for each time quantum.
+    // 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();
+
+    // 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();
+
+    // m_disabledOutputs contains the AudioNodeOutputs which are disabled (will not be processed) by the audio graph rendering.
+    // But, from JavaScript's perspective, these outputs are still connected to us.
+    // Generally, these represent disabled connections from "notes" which have finished playing but are not yet garbage collected.
+    HashSet<AudioNodeOutput*> m_disabledOutputs;
+
+    // Called from context's audio thread.
+    AudioBus* internalSummingBus();
+    void sumAllConnections(AudioBus* summingBus, size_t framesToProcess);
+
+    OwnPtr<AudioBus> m_monoSummingBus;
+    OwnPtr<AudioBus> m_stereoSummingBus;
+};
+
+} // namespace WebCore
+
+#endif // AudioNodeInput_h

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list