Diff
Modified: trunk/LayoutTests/ChangeLog (115786 => 115787)
--- trunk/LayoutTests/ChangeLog 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/LayoutTests/ChangeLog 2012-05-02 03:38:23 UTC (rev 115787)
@@ -1,3 +1,13 @@
+2012-05-01 Raymond Liu <[email protected]>
+
+ Modify RealtimeAnalyserNode pull mechanism
+ https://bugs.webkit.org/show_bug.cgi?id=77515
+
+ Reviewed by Chris Rogers.
+
+ * webaudio/automatic-pull-node-expected.txt: Added.
+ * webaudio/automatic-pull-node.html: Added.
+
2012-05-01 Keishi Hattori <[email protected]>
datalist: Form control in a <datalist> should be barred from constraint validation
Added: trunk/LayoutTests/webaudio/automatic-pull-node-expected.txt (0 => 115787)
--- trunk/LayoutTests/webaudio/automatic-pull-node-expected.txt (rev 0)
+++ trunk/LayoutTests/webaudio/automatic-pull-node-expected.txt 2012-05-02 03:38:23 UTC (rev 115787)
@@ -0,0 +1,11 @@
+This test verifies that the AudioBasicInspectorNode based nodes work correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS RealtimeAnalyserNode got pulled when connected from upstream node but not to downstream node.
+PASS RealtimeAnalyserNode got pulled when connected from upstream node and to destination node.
+PASS RealtimeAnalyserNode didn't get pulled when it should not.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/webaudio/automatic-pull-node.html (0 => 115787)
--- trunk/LayoutTests/webaudio/automatic-pull-node.html (rev 0)
+++ trunk/LayoutTests/webaudio/automatic-pull-node.html 2012-05-02 03:38:23 UTC (rev 115787)
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<script src=""
+<script type="text/_javascript_" src=""
+</head>
+
+<body>
+
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+description("This test verifies that the AudioBasicInspectorNode based nodes work correctly.");
+
+var sampleRate = 44100.0;
+// We carefully arrange the renderLengthInFrames to be a multiple of the AudioNode rendering quantum (AudioNode::ProcessingSizeInFrames)
+// so that AudioSourceNode will not feed tailing zeroes into the context and fail this test.
+var renderLengthInFrames = 256;
+var fftSize = 64;
+
+var audioDataOne = 255; // Audio data 1.0 in Uint8 format will be 255.
+var audioDataZero = 128; // Audio data 0 in Uint8 format will be 128.
+
+var context;
+var constantBuffer;
+var bufferSource;
+var analyser;
+
+function constructCommonGraph() {
+ // Create offline audio context.
+ context = new webkitAudioContext(1, renderLengthInFrames, sampleRate);
+ constantBuffer = createConstantBuffer(context, renderLengthInFrames, 1);
+
+ bufferSource = context.createBufferSource();
+ bufferSource.buffer = constantBuffer;
+
+ analyser = context.createAnalyser();
+ analyser.fftSize = fftSize;
+
+ bufferSource.connect(analyser);
+}
+
+function test1Finished() {
+ var timeDomainData = new Uint8Array(fftSize);
+ analyser.getByteTimeDomainData(timeDomainData);
+
+ if (timeDomainData[0] >= audioDataOne)
+ testPassed("RealtimeAnalyserNode got pulled when connected from upstream node but not to downstream node.");
+ else
+ testFailed("RealtimeAnalyserNode failed to get pulled when connected from upstream node but not to downstream node.");
+
+ test2();
+}
+
+// To verify the realtimeAnalyser can pull data when there is an upstream node connected to it
+// but it's not connected to a downstream node.
+function test1() {
+ constructCommonGraph();
+
+ bufferSource.noteOn(0);
+
+ context._oncomplete_ = test1Finished;
+ context.startRendering();
+}
+
+function test2Finished() {
+ var timeDomainData = new Uint8Array(fftSize);
+ analyser.getByteTimeDomainData(timeDomainData);
+
+ if (timeDomainData[0] >= audioDataOne)
+ testPassed("RealtimeAnalyserNode got pulled when connected from upstream node and to destination node.");
+ else
+ testFailed("RealtimeAnalyserNode failed to be pulled when connected by upstream node and to destination node.");
+
+ test3();
+}
+
+// To verify the realtimeAnalyser can process normally when there is an upstream node connected to it
+// and it's also connected to a downstream node which ultimately connect to audio destination.
+function test2() {
+ constructCommonGraph();
+
+ analyser.connect(context.destination);
+
+ bufferSource.noteOn(0);
+
+ context._oncomplete_ = test2Finished;
+ context.startRendering();
+}
+
+function test3Finished() {
+ var timeDomainData = new Uint8Array(fftSize);
+ analyser.getByteTimeDomainData(timeDomainData);
+
+ // If realtimeAnalyser hasn't pulled any data, the data in buffer will be 0.
+ if (timeDomainData[0] == audioDataZero)
+ testPassed("RealtimeAnalyserNode didn't get pulled when it should not.");
+ else
+ testFailed("RealtimeAnalyserNode been pulled when it should not.");
+
+ finishJSTest();
+}
+
+// To verify the realtimeAnalyser will stop pulling if it is connected to a downstream node
+// which is not ultimatly connected to any audio destination.
+function test3() {
+ constructCommonGraph();
+
+ var gain = context.createGainNode();
+ analyser.connect(gain);
+
+ bufferSource.noteOn(0);
+
+ context._oncomplete_ = test3Finished;
+ context.startRendering();
+}
+
+function runTest() {
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ layoutTestController.waitUntilDone();
+ }
+
+ window.jsTestIsAsync = true;
+
+ test1();
+}
+
+runTest();
+
+</script>
+
+<script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (115786 => 115787)
--- trunk/Source/WebCore/ChangeLog 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/ChangeLog 2012-05-02 03:38:23 UTC (rev 115787)
@@ -1,3 +1,51 @@
+2012-05-01 Raymond Liu <[email protected]>
+
+ Modify RealtimeAnalyserNode pull mechanism
+ https://bugs.webkit.org/show_bug.cgi?id=77515
+
+ Reviewed by Chris Rogers.
+
+ Test: webaudio/automatic-pull-node.html
+
+ * GNUmakefile.list.am:
+ * Modules/webaudio/AudioBasicInspectorNode.cpp: Added.
+ (WebCore):
+ (WebCore::AudioBasicInspectorNode::AudioBasicInspectorNode):
+ (WebCore::AudioBasicInspectorNode::pullInputs):
+ (WebCore::AudioBasicInspectorNode::connect):
+ (WebCore::AudioBasicInspectorNode::disconnect):
+ (WebCore::AudioBasicInspectorNode::checkNumberOfChannelsForInput):
+ (WebCore::AudioBasicInspectorNode::updatePullStatus):
+ * Modules/webaudio/AudioBasicInspectorNode.h: Added.
+ (WebCore):
+ (AudioBasicInspectorNode):
+ * Modules/webaudio/AudioContext.cpp:
+ (WebCore::AudioContext::AudioContext):
+ (WebCore::AudioContext::~AudioContext):
+ (WebCore::AudioContext::handlePreRenderTasks):
+ (WebCore::AudioContext::handlePostRenderTasks):
+ (WebCore::AudioContext::markForDeletion):
+ (WebCore):
+ (WebCore::AudioContext::addAutomaticPullNode):
+ (WebCore::AudioContext::removeAutomaticPullNode):
+ (WebCore::AudioContext::updateAutomaticPullNodes):
+ (WebCore::AudioContext::processAutomaticPullNodes):
+ * Modules/webaudio/AudioContext.h:
+ (AudioContext):
+ * Modules/webaudio/AudioDestinationNode.cpp:
+ (WebCore::AudioDestinationNode::provideInput):
+ * Modules/webaudio/AudioNode.h:
+ (AudioNode):
+ * Modules/webaudio/AudioNodeOutput.h:
+ (WebCore::AudioNodeOutput::isConnected):
+ (AudioNodeOutput):
+ * Modules/webaudio/RealtimeAnalyserNode.cpp:
+ (WebCore::RealtimeAnalyserNode::RealtimeAnalyserNode):
+ * Modules/webaudio/RealtimeAnalyserNode.h:
+ (RealtimeAnalyserNode):
+ * WebCore.gypi:
+ * WebCore.xcodeproj/project.pbxproj:
+
2012-05-01 Keishi Hattori <[email protected]>
datalist: Form control in a <datalist> should be barred from constraint validation
Modified: trunk/Source/WebCore/GNUmakefile.list.am (115786 => 115787)
--- trunk/Source/WebCore/GNUmakefile.list.am 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/GNUmakefile.list.am 2012-05-02 03:38:23 UTC (rev 115787)
@@ -5473,6 +5473,8 @@
webcore_sources += \
Source/WebCore/Modules/webaudio/AsyncAudioDecoder.cpp \
Source/WebCore/Modules/webaudio/AsyncAudioDecoder.h \
+ Source/WebCore/Modules/webaudio/AudioBasicInspectorNode.cpp \
+ Source/WebCore/Modules/webaudio/AudioBasicInspectorNode.h \
Source/WebCore/Modules/webaudio/AudioBasicProcessorNode.cpp \
Source/WebCore/Modules/webaudio/AudioBasicProcessorNode.h \
Source/WebCore/Modules/webaudio/AudioBuffer.cpp \
Added: trunk/Source/WebCore/Modules/webaudio/AudioBasicInspectorNode.cpp (0 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/AudioBasicInspectorNode.cpp (rev 0)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBasicInspectorNode.cpp 2012-05-02 03:38:23 UTC (rev 115787)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012, Intel Corporation. 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 "AudioBasicInspectorNode.h"
+
+#include "AudioContext.h"
+#include "AudioNodeInput.h"
+#include "AudioNodeOutput.h"
+
+namespace WebCore {
+
+AudioBasicInspectorNode::AudioBasicInspectorNode(AudioContext* context, float sampleRate)
+ : AudioNode(context, sampleRate)
+ , m_needAutomaticPull(false)
+{
+ addInput(adoptPtr(new AudioNodeInput(this)));
+ addOutput(adoptPtr(new AudioNodeOutput(this, 2)));
+}
+
+// We override pullInputs() as an optimization allowing this node to take advantage of in-place processing,
+// where the input is simply passed through unprocessed to the output.
+// Note: this only applies if the input and output channel counts match.
+void AudioBasicInspectorNode::pullInputs(size_t framesToProcess)
+{
+ // Render input stream - try to render directly into output bus for pass-through processing where process() doesn't need to do anything...
+ input(0)->pull(output(0)->bus(), framesToProcess);
+}
+
+void AudioBasicInspectorNode::connect(AudioNode* destination, unsigned outputIndex, unsigned inputIndex, ExceptionCode& ec)
+{
+ ASSERT(isMainThread());
+
+ AudioContext::AutoLocker locker(context());
+
+ AudioNode::connect(destination, outputIndex, inputIndex, ec);
+ updatePullStatus();
+}
+
+void AudioBasicInspectorNode::disconnect(unsigned outputIndex, ExceptionCode& ec)
+{
+ ASSERT(isMainThread());
+
+ AudioContext::AutoLocker locker(context());
+
+ AudioNode::disconnect(outputIndex, ec);
+ updatePullStatus();
+}
+
+void AudioBasicInspectorNode::checkNumberOfChannelsForInput(AudioNodeInput* input)
+{
+ ASSERT(context()->isAudioThread() && context()->isGraphOwner());
+
+ ASSERT(input == this->input(0));
+ if (input != this->input(0))
+ return;
+
+ unsigned numberOfChannels = input->numberOfChannels();
+
+ if (numberOfChannels != output(0)->numberOfChannels()) {
+ // This will propagate the channel count to any nodes connected further downstream in the graph.
+ output(0)->setNumberOfChannels(numberOfChannels);
+ }
+
+ AudioNode::checkNumberOfChannelsForInput(input);
+
+ updatePullStatus();
+}
+
+void AudioBasicInspectorNode::updatePullStatus()
+{
+ ASSERT(context()->isGraphOwner());
+
+ if (output(0)->isConnected()) {
+ // When an AudioBasicInspectorNode is connected to a downstream node, it will get pulled by the
+ // downstream node, thus remove it from the context's automatic pull list.
+ if (m_needAutomaticPull) {
+ context()->removeAutomaticPullNode(this);
+ m_needAutomaticPull = false;
+ }
+ } else {
+ unsigned numberOfInputConnections = input(0)->numberOfRenderingConnections();
+ if (numberOfInputConnections && !m_needAutomaticPull) {
+ // When an AudioBasicInspectorNode is not connected to any downstream node while still connected from
+ // upstream node(s), add it to the context's automatic pull list.
+ context()->addAutomaticPullNode(this);
+ m_needAutomaticPull = true;
+ } else if (!numberOfInputConnections && m_needAutomaticPull) {
+ // The AudioBasicInspectorNode is connected to nothing, remove it from the context's automatic pull list.
+ context()->removeAutomaticPullNode(this);
+ m_needAutomaticPull = false;
+ }
+ }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
Added: trunk/Source/WebCore/Modules/webaudio/AudioBasicInspectorNode.h (0 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/AudioBasicInspectorNode.h (rev 0)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBasicInspectorNode.h 2012-05-02 03:38:23 UTC (rev 115787)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012, Intel Corporation. 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 AudioBasicInspectorNode_h
+#define AudioBasicInspectorNode_h
+
+#include "AudioNode.h"
+
+namespace WebCore {
+
+// AudioBasicInspectorNode is an AudioNode with one input and one output where the output might not necessarily connect to another node's input.
+// If the output is not connected to any other node, then the AudioBasicInspectorNode's processIfNecessary() function will be called automatically by
+// AudioContext before the end of each render quantum so that it can inspect the audio stream.
+class AudioBasicInspectorNode : public AudioNode {
+public:
+ AudioBasicInspectorNode(AudioContext*, float sampleRate);
+
+ // AudioNode
+ virtual void pullInputs(size_t framesToProcess);
+ virtual void connect(AudioNode*, unsigned outputIndex, unsigned inputIndex, ExceptionCode&);
+ virtual void disconnect(unsigned outputIndex, ExceptionCode&);
+ virtual void checkNumberOfChannelsForInput(AudioNodeInput*);
+
+private:
+ void updatePullStatus();
+ bool m_needAutomaticPull; // When setting to true, AudioBasicInspectorNode will be pulled automaticlly by AudioContext before the end of each render quantum.
+};
+
+} // namespace WebCore
+
+#endif // AudioBasicInspectorNode_h
Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp (115786 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.cpp 2012-05-02 03:38:23 UTC (rev 115787)
@@ -140,6 +140,7 @@
, m_document(document)
, m_destinationNode(0)
, m_isDeletionScheduled(false)
+ , m_automaticPullNodesNeedUpdating(false)
, m_connectionCount(0)
, m_audioThread(0)
, m_graphOwnerThread(UndefinedThreadIdentifier)
@@ -164,6 +165,7 @@
, m_isAudioThreadFinished(false)
, m_document(document)
, m_destinationNode(0)
+ , m_automaticPullNodesNeedUpdating(false)
, m_connectionCount(0)
, m_audioThread(0)
, m_graphOwnerThread(UndefinedThreadIdentifier)
@@ -200,6 +202,8 @@
ASSERT(!m_nodesToDelete.size());
ASSERT(!m_referencedNodes.size());
ASSERT(!m_finishedNodes.size());
+ ASSERT(!m_automaticPullNodes.size());
+ ASSERT(!m_renderingAutomaticPullNodes.size());
}
void AudioContext::lazyInitialize()
@@ -662,7 +666,9 @@
// Fixup the state of any dirty AudioNodeInputs and AudioNodeOutputs.
handleDirtyAudioNodeInputs();
handleDirtyAudioNodeOutputs();
-
+
+ updateAutomaticPullNodes();
+
if (mustReleaseLock)
unlock();
}
@@ -690,7 +696,9 @@
// Fixup the state of any dirty AudioNodeInputs and AudioNodeOutputs.
handleDirtyAudioNodeInputs();
handleDirtyAudioNodeOutputs();
-
+
+ updateAutomaticPullNodes();
+
if (mustReleaseLock)
unlock();
}
@@ -712,6 +720,12 @@
{
ASSERT(isGraphOwner());
m_nodesToDelete.append(node);
+
+ // This is probably the best time for us to remove the node from automatic pull list,
+ // since all connections are gone and we hold the graph lock. Then when handlePostRenderTasks()
+ // gets a chance to schedule the deletion work, updateAutomaticPullNodes() also gets a chance to
+ // modify m_renderingAutomaticPullNodes.
+ removeAutomaticPullNode(node);
}
void AudioContext::scheduleNodeDeletion()
@@ -803,6 +817,52 @@
m_dirtyAudioNodeOutputs.clear();
}
+void AudioContext::addAutomaticPullNode(AudioNode* node)
+{
+ ASSERT(isGraphOwner());
+
+ if (!m_automaticPullNodes.contains(node)) {
+ m_automaticPullNodes.add(node);
+ m_automaticPullNodesNeedUpdating = true;
+ }
+}
+
+void AudioContext::removeAutomaticPullNode(AudioNode* node)
+{
+ ASSERT(isGraphOwner());
+
+ if (m_automaticPullNodes.contains(node)) {
+ m_automaticPullNodes.remove(node);
+ m_automaticPullNodesNeedUpdating = true;
+ }
+}
+
+void AudioContext::updateAutomaticPullNodes()
+{
+ ASSERT(isGraphOwner());
+
+ if (m_automaticPullNodesNeedUpdating) {
+ // Copy from m_automaticPullNodes to m_renderingAutomaticPullNodes.
+ m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
+
+ unsigned j = 0;
+ for (HashSet<AudioNode*>::iterator i = m_automaticPullNodes.begin(); i != m_automaticPullNodes.end(); ++i, ++j) {
+ AudioNode* output = *i;
+ m_renderingAutomaticPullNodes[j] = output;
+ }
+
+ m_automaticPullNodesNeedUpdating = false;
+ }
+}
+
+void AudioContext::processAutomaticPullNodes(size_t framesToProcess)
+{
+ ASSERT(isAudioThread());
+
+ for (unsigned i = 0; i < m_renderingAutomaticPullNodes.size(); ++i)
+ m_renderingAutomaticPullNodes[i]->processIfNecessary(framesToProcess);
+}
+
const AtomicString& AudioContext::interfaceName() const
{
return eventNames().interfaceForAudioContext;
Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.h (115786 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/AudioContext.h 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.h 2012-05-02 03:38:23 UTC (rev 115787)
@@ -148,7 +148,15 @@
// We schedule deletion of all marked nodes at the end of each realtime render quantum.
void markForDeletion(AudioNode*);
void deleteMarkedNodes();
-
+
+ // AudioContext can pull node(s) at the end of each render quantum even when they are not connected to any downstream nodes.
+ // These two methods are called by the nodes who want to add/remove themselves into/from the automatic pull lists.
+ void addAutomaticPullNode(AudioNode*);
+ void removeAutomaticPullNode(AudioNode*);
+
+ // Called right before handlePostRenderTasks() to handle nodes which need to be pulled even when they are not connected to anything.
+ void processAutomaticPullNodes(size_t framesToProcess);
+
// Keeps track of the number of connections made.
void incrementConnectionCount()
{
@@ -281,6 +289,14 @@
void handleDirtyAudioNodeInputs();
void handleDirtyAudioNodeOutputs();
+ // For the sake of thread safety, we maintain a seperate Vector of automatic pull nodes for rendering in m_renderingAutomaticPullNodes.
+ // It will be copied from m_automaticPullNodes by updateAutomaticPullNodes() at the very start or end of the rendering quantum.
+ HashSet<AudioNode*> m_automaticPullNodes;
+ Vector<AudioNode*> m_renderingAutomaticPullNodes;
+ // m_automaticPullNodesNeedUpdating keeps track if m_automaticPullNodes is modified.
+ bool m_automaticPullNodesNeedUpdating;
+ void updateAutomaticPullNodes();
+
unsigned m_connectionCount;
// Graph locking.
Modified: trunk/Source/WebCore/Modules/webaudio/AudioDestinationNode.cpp (115786 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/AudioDestinationNode.cpp 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/Modules/webaudio/AudioDestinationNode.cpp 2012-05-02 03:38:23 UTC (rev 115787)
@@ -80,6 +80,9 @@
destinationBus->copyFrom(*renderedBus);
}
+ // Process nodes which need a little extra help because they are not connected to anything, but still need to process.
+ context()->processAutomaticPullNodes(numberOfFrames);
+
// Let the context take care of any business at the end of each render quantum.
context()->handlePostRenderTasks();
Modified: trunk/Source/WebCore/Modules/webaudio/AudioNode.h (115786 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/AudioNode.h 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNode.h 2012-05-02 03:38:23 UTC (rev 115787)
@@ -116,9 +116,9 @@
AudioNodeOutput* output(unsigned);
// Called from main thread by corresponding _javascript_ methods.
- void connect(AudioNode*, unsigned outputIndex, unsigned inputIndex, ExceptionCode&);
+ virtual void connect(AudioNode*, unsigned outputIndex, unsigned inputIndex, ExceptionCode&);
void connect(AudioParam*, unsigned outputIndex, ExceptionCode&);
- void disconnect(unsigned outputIndex, ExceptionCode&);
+ virtual void disconnect(unsigned outputIndex, ExceptionCode&);
virtual float sampleRate() const { return m_sampleRate; }
Modified: trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.h (115786 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.h 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.h 2012-05-02 03:38:23 UTC (rev 115787)
@@ -72,6 +72,8 @@
unsigned numberOfChannels() const { return m_numberOfChannels; }
bool isChannelCountKnown() const { return numberOfChannels() > 0; }
+ bool isConnected() { return fanOutCount() > 0 || paramFanOutCount() > 0; }
+
// Disable/Enable happens when there are still _javascript_ references to a node, but it has otherwise "finished" its work.
// For example, when a note has finished playing. It is kept around, because it may be played again at a later time.
// They must be called with the context's graph lock.
Modified: trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyserNode.cpp (115786 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyserNode.cpp 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyserNode.cpp 2012-05-02 03:38:23 UTC (rev 115787)
@@ -35,7 +35,7 @@
namespace WebCore {
RealtimeAnalyserNode::RealtimeAnalyserNode(AudioContext* context, float sampleRate)
- : AudioNode(context, sampleRate)
+ : AudioBasicInspectorNode(context, sampleRate)
{
addInput(adoptPtr(new AudioNodeInput(this)));
addOutput(adoptPtr(new AudioNodeOutput(this, 2)));
@@ -70,15 +70,6 @@
outputBus->copyFrom(*inputBus);
}
-// We override pullInputs() as an optimization allowing this node to take advantage of in-place processing,
-// where the input is simply passed through unprocessed to the output.
-// Note: this only applies if the input and output channel counts match.
-void RealtimeAnalyserNode::pullInputs(size_t framesToProcess)
-{
- // Render input stream - try to render directly into output bus for pass-through processing where process() doesn't need to do anything...
- input(0)->pull(output(0)->bus(), framesToProcess);
-}
-
void RealtimeAnalyserNode::reset()
{
m_analyser.reset();
Modified: trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyserNode.h (115786 => 115787)
--- trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyserNode.h 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyserNode.h 2012-05-02 03:38:23 UTC (rev 115787)
@@ -25,13 +25,13 @@
#ifndef RealtimeAnalyserNode_h
#define RealtimeAnalyserNode_h
-#include "AudioNode.h"
+#include "AudioBasicInspectorNode.h"
#include "RealtimeAnalyser.h"
#include <wtf/Forward.h>
namespace WebCore {
-class RealtimeAnalyserNode : public AudioNode {
+class RealtimeAnalyserNode : public AudioBasicInspectorNode {
public:
static PassRefPtr<RealtimeAnalyserNode> create(AudioContext* context, float sampleRate)
{
@@ -42,7 +42,6 @@
// AudioNode
virtual void process(size_t framesToProcess);
- virtual void pullInputs(size_t framesToProcess);
virtual void reset();
// _javascript_ bindings
Modified: trunk/Source/WebCore/WebCore.gypi (115786 => 115787)
--- trunk/Source/WebCore/WebCore.gypi 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/WebCore.gypi 2012-05-02 03:38:23 UTC (rev 115787)
@@ -1557,6 +1557,8 @@
'Modules/speech/SpeechRecognitionResult.h',
'Modules/speech/SpeechRecognitionResultList.cpp',
'Modules/speech/SpeechRecognitionResultList.h',
+ 'Modules/webaudio/AudioBasicInspectorNode.cpp',
+ 'Modules/webaudio/AudioBasicInspectorNode.h',
'Modules/webaudio/AudioBasicProcessorNode.cpp',
'Modules/webaudio/AudioBasicProcessorNode.h',
'Modules/webaudio/AudioBuffer.cpp',
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (115786 => 115787)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2012-05-02 03:35:48 UTC (rev 115786)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2012-05-02 03:38:23 UTC (rev 115787)
@@ -6292,6 +6292,8 @@
FD581FAF1520F91F003A7A75 /* Oscillator.h in Headers */ = {isa = PBXBuildFile; fileRef = FD581FAC1520F91F003A7A75 /* Oscillator.h */; };
FD581FB41520F93B003A7A75 /* WaveTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD581FB11520F93B003A7A75 /* WaveTable.cpp */; };
FD581FB51520F93B003A7A75 /* WaveTable.h in Headers */ = {isa = PBXBuildFile; fileRef = FD581FB21520F93B003A7A75 /* WaveTable.h */; };
+ FD629EA3154B47160006D026 /* AudioBasicInspectorNode.h in Headers */ = {isa = PBXBuildFile; fileRef = FD629EA1154B47160006D026 /* AudioBasicInspectorNode.h */; };
+ FD629EA4154B47160006D026 /* AudioBasicInspectorNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD629EA2154B47160006D026 /* AudioBasicInspectorNode.cpp */; };
FD62F52E145898D80094B0ED /* AudioSourceProviderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = FD62F52D145898D80094B0ED /* AudioSourceProviderClient.h */; };
FD6ED2C3136B8E42003CF072 /* DynamicsCompressorNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD6ED2C1136B8E42003CF072 /* DynamicsCompressorNode.cpp */; };
FD6ED2C4136B8E42003CF072 /* DynamicsCompressorNode.h in Headers */ = {isa = PBXBuildFile; fileRef = FD6ED2C2136B8E42003CF072 /* DynamicsCompressorNode.h */; };
@@ -13520,6 +13522,8 @@
FD581FB11520F93B003A7A75 /* WaveTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WaveTable.cpp; sourceTree = "<group>"; };
FD581FB21520F93B003A7A75 /* WaveTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WaveTable.h; sourceTree = "<group>"; };
FD581FB31520F93B003A7A75 /* WaveTable.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WaveTable.idl; sourceTree = "<group>"; };
+ FD629EA1154B47160006D026 /* AudioBasicInspectorNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioBasicInspectorNode.h; sourceTree = "<group>"; };
+ FD629EA2154B47160006D026 /* AudioBasicInspectorNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioBasicInspectorNode.cpp; sourceTree = "<group>"; };
FD62F52D145898D80094B0ED /* AudioSourceProviderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioSourceProviderClient.h; sourceTree = "<group>"; };
FD6ED2C1136B8E42003CF072 /* DynamicsCompressorNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicsCompressorNode.cpp; sourceTree = "<group>"; };
FD6ED2C2136B8E42003CF072 /* DynamicsCompressorNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicsCompressorNode.h; sourceTree = "<group>"; };
@@ -21365,6 +21369,8 @@
children = (
FD5686C713AC180200B69C68 /* AsyncAudioDecoder.cpp */,
FD5686C813AC180200B69C68 /* AsyncAudioDecoder.h */,
+ FD629EA1154B47160006D026 /* AudioBasicInspectorNode.h */,
+ FD629EA2154B47160006D026 /* AudioBasicInspectorNode.cpp */,
FD315FAC12B0267500C1A359 /* AudioBasicProcessorNode.cpp */,
FD315FAD12B0267500C1A359 /* AudioBasicProcessorNode.h */,
FD315FAE12B0267500C1A359 /* AudioBuffer.cpp */,
@@ -24837,6 +24843,7 @@
FD8C46EC154608E700A5910C /* AudioScheduledSourceNode.h in Headers */,
71A57DF2154BE25C0009D120 /* SVGPathUtilities.h in Headers */,
78D02BC6154A18DF00B62D05 /* CSSPropertyAnimation.h in Headers */,
+ FD629EA3154B47160006D026 /* AudioBasicInspectorNode.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -27853,6 +27860,7 @@
FD8C46EB154608E700A5910C /* AudioScheduledSourceNode.cpp in Sources */,
71A57DF1154BE25C0009D120 /* SVGPathUtilities.cpp in Sources */,
78D02BC5154A18DF00B62D05 /* CSSPropertyAnimation.cpp in Sources */,
+ FD629EA4154B47160006D026 /* AudioBasicInspectorNode.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};