diff options
Diffstat (limited to 'WebCore/webaudio')
-rw-r--r-- | WebCore/webaudio/AudioContext.cpp | 72 | ||||
-rw-r--r-- | WebCore/webaudio/AudioContext.h | 18 | ||||
-rw-r--r-- | WebCore/webaudio/AudioNode.cpp | 24 | ||||
-rw-r--r-- | WebCore/webaudio/AudioNode.h | 26 | ||||
-rw-r--r-- | WebCore/webaudio/AudioNode.idl | 24 | ||||
-rw-r--r-- | WebCore/webaudio/AudioNodeInput.cpp | 270 | ||||
-rw-r--r-- | WebCore/webaudio/AudioNodeInput.h | 125 | ||||
-rw-r--r-- | WebCore/webaudio/AudioNodeOutput.cpp | 216 | ||||
-rw-r--r-- | WebCore/webaudio/AudioNodeOutput.h | 134 | ||||
-rw-r--r-- | WebCore/webaudio/DelayNode.cpp | 47 | ||||
-rw-r--r-- | WebCore/webaudio/DelayNode.h | 53 | ||||
-rw-r--r-- | WebCore/webaudio/DelayNode.idl | 32 | ||||
-rw-r--r-- | WebCore/webaudio/DelayProcessor.cpp | 54 | ||||
-rw-r--r-- | WebCore/webaudio/DelayProcessor.h | 53 |
14 files changed, 1102 insertions, 46 deletions
diff --git a/WebCore/webaudio/AudioContext.cpp b/WebCore/webaudio/AudioContext.cpp index f971e6a..da7df1b 100644 --- a/WebCore/webaudio/AudioContext.cpp +++ b/WebCore/webaudio/AudioContext.cpp @@ -34,6 +34,8 @@ #include "AudioChannelSplitter.h" #include "AudioGainNode.h" #include "AudioListener.h" +#include "AudioNodeInput.h" +#include "AudioNodeOutput.h" #include "AudioPannerNode.h" #include "CachedAudio.h" #include "ConvolverNode.h" @@ -390,12 +392,12 @@ void AudioContext::unlock() m_contextGraphMutex.unlock(); } -bool AudioContext::isAudioThread() +bool AudioContext::isAudioThread() const { return currentThread() == m_audioThread; } -bool AudioContext::isGraphOwner() +bool AudioContext::isGraphOwner() const { return currentThread() == m_graphOwnerThread; } @@ -406,6 +408,23 @@ void AudioContext::addDeferredFinishDeref(AudioNode* node, AudioNode::RefType re m_deferredFinishDerefList.append(AudioContext::RefInfo(node, refType)); } +void AudioContext::handlePreRenderTasks() +{ + ASSERT(isAudioThread()); + + // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes). + // 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(); + handleDirtyAudioNodeOutputs(); + + if (mustReleaseLock) + unlock(); + } +} + void AudioContext::handlePostRenderTasks() { ASSERT(isAudioThread()); @@ -424,6 +443,10 @@ void AudioContext::handlePostRenderTasks() // Finally actually delete. deleteMarkedNodes(); + // Fixup the state of any dirty AudioNodeInputs and AudioNodeOutputs. + handleDirtyAudioNodeInputs(); + handleDirtyAudioNodeOutputs(); + if (mustReleaseLock) unlock(); } @@ -456,6 +479,18 @@ void AudioContext::deleteMarkedNodes() while (size_t n = m_nodesToDelete.size()) { AudioNode* node = m_nodesToDelete[n - 1]; m_nodesToDelete.removeLast(); + + // Before deleting the node, clear out any AudioNodeInputs from m_dirtyAudioNodeInputs. + unsigned numberOfInputs = node->numberOfInputs(); + for (unsigned i = 0; i < numberOfInputs; ++i) + m_dirtyAudioNodeInputs.remove(node->input(i)); + + // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs. + unsigned numberOfOutputs = node->numberOfOutputs(); + for (unsigned i = 0; i < numberOfOutputs; ++i) + m_dirtyAudioNodeOutputs.remove(node->output(i)); + + // Finally, delete it. delete node; // Don't delete too many nodes per render quantum since we don't want to do too much work in the realtime audio thread. @@ -464,6 +499,39 @@ void AudioContext::deleteMarkedNodes() } } +void AudioContext::markAudioNodeInputDirty(AudioNodeInput* input) +{ + ASSERT(isGraphOwner()); + m_dirtyAudioNodeInputs.add(input); +} + +void AudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output) +{ + ASSERT(isGraphOwner()); + m_dirtyAudioNodeOutputs.add(output); +} + +void AudioContext::handleDirtyAudioNodeInputs() +{ + ASSERT(isGraphOwner()); + + for (HashSet<AudioNodeInput*>::iterator i = m_dirtyAudioNodeInputs.begin(); i != m_dirtyAudioNodeInputs.end(); ++i) + (*i)->updateRenderingState(); + + m_dirtyAudioNodeInputs.clear(); +} + +void AudioContext::handleDirtyAudioNodeOutputs() +{ + ASSERT(isGraphOwner()); + + for (HashSet<AudioNodeOutput*>::iterator i = m_dirtyAudioNodeOutputs.begin(); i != m_dirtyAudioNodeOutputs.end(); ++i) + (*i)->updateRenderingState(); + + m_dirtyAudioNodeOutputs.clear(); +} + + } // namespace WebCore #endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/AudioContext.h b/WebCore/webaudio/AudioContext.h index 9fe1347..b79cd14 100644 --- a/WebCore/webaudio/AudioContext.h +++ b/WebCore/webaudio/AudioContext.h @@ -29,6 +29,7 @@ #include "AudioBus.h" #include "AudioDestinationNode.h" #include "HRTFDatabaseLoader.h" +#include <wtf/HashSet.h> #include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -107,6 +108,9 @@ public: // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it. void notifyNodeFinishedProcessing(AudioNode*); + // Called at the start of each render quantum. + void handlePreRenderTasks(); + // Called at the end of each render quantum. void handlePostRenderTasks(); @@ -132,7 +136,7 @@ public: void setAudioThread(ThreadIdentifier thread) { m_audioThread = thread; } // FIXME: check either not initialized or the same ThreadIdentifier audioThread() const { return m_audioThread; } - bool isAudioThread(); + bool isAudioThread() const; // Returns true only after the audio thread has been started and then shutdown. bool isAudioThreadFinished() { return m_isAudioThreadFinished; } @@ -147,7 +151,7 @@ public: void unlock(); // Returns true if this thread owns the context's lock. - bool isGraphOwner(); + bool isGraphOwner() const; class AutoLocker { public: @@ -173,6 +177,10 @@ public: // In the audio thread at the start of each render cycle, we'll call handleDeferredFinishDerefs(). void handleDeferredFinishDerefs(); + + // Only accessed when the graph lock is held. + void markAudioNodeInputDirty(AudioNodeInput*); + void markAudioNodeOutputDirty(AudioNodeOutput*); private: AudioContext(Document*); @@ -214,6 +222,12 @@ private: Vector<AudioNode*> m_nodesToDelete; Vector<RefPtr<CachedAudio> > m_cachedAudioReferences; + + // Only accessed when the graph lock is held. + HashSet<AudioNodeInput*> m_dirtyAudioNodeInputs; + HashSet<AudioNodeOutput*> m_dirtyAudioNodeOutputs; + void handleDirtyAudioNodeInputs(); + void handleDirtyAudioNodeOutputs(); OwnPtr<AudioBus> m_temporaryMonoBus; OwnPtr<AudioBus> m_temporaryStereoBus; diff --git a/WebCore/webaudio/AudioNode.cpp b/WebCore/webaudio/AudioNode.cpp index 9335c10..18ddd3b 100644 --- a/WebCore/webaudio/AudioNode.cpp +++ b/WebCore/webaudio/AudioNode.cpp @@ -1,29 +1,25 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * 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. + * 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * 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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * 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. + * 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" diff --git a/WebCore/webaudio/AudioNode.h b/WebCore/webaudio/AudioNode.h index 52f886d..069407d 100644 --- a/WebCore/webaudio/AudioNode.h +++ b/WebCore/webaudio/AudioNode.h @@ -1,29 +1,25 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * 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. + * 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * 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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * 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. + * 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 AudioNode_h @@ -134,6 +130,8 @@ public: static void printNodeCounts(); #endif + bool isMarkedForDeletion() const { return m_isMarkedForDeletion; } + protected: // Inputs and outputs must be created before the AudioNode is initialized. void addInput(PassOwnPtr<AudioNodeInput>); diff --git a/WebCore/webaudio/AudioNode.idl b/WebCore/webaudio/AudioNode.idl index 5ed47cb..dad5454 100644 --- a/WebCore/webaudio/AudioNode.idl +++ b/WebCore/webaudio/AudioNode.idl @@ -1,29 +1,25 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * 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. + * 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * 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 AND ITS CONTRIBUTORS "AS IS" AND ANY + * 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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * 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. + * 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. */ module audio { 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 diff --git a/WebCore/webaudio/AudioNodeOutput.cpp b/WebCore/webaudio/AudioNodeOutput.cpp new file mode 100644 index 0000000..4c777e6 --- /dev/null +++ b/WebCore/webaudio/AudioNodeOutput.cpp @@ -0,0 +1,216 @@ +/* + * 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 "AudioNodeOutput.h" + +#include "AudioBus.h" +#include "AudioContext.h" +#include "AudioNodeInput.h" +#include <wtf/Threading.h> + +namespace WebCore { + +AudioNodeOutput::AudioNodeOutput(AudioNode* node, unsigned numberOfChannels) + : m_node(node) + , m_numberOfChannels(numberOfChannels) + , m_desiredNumberOfChannels(numberOfChannels) + , m_internalOutputBus(0) + , m_actualDestinationBus(0) + , m_isEnabled(true) + , m_renderingFanOutCount(0) +{ + m_monoInternalBus = adoptPtr(new AudioBus(1, AudioNode::ProcessingSizeInFrames)); + m_stereoInternalBus = adoptPtr(new AudioBus(2, AudioNode::ProcessingSizeInFrames)); + setInternalBus(); +} + +void AudioNodeOutput::setNumberOfChannels(unsigned numberOfChannels) +{ + ASSERT(context()->isGraphOwner()); + + m_desiredNumberOfChannels = numberOfChannels; + + if (context()->isAudioThread()) { + // If we're in the audio thread then we can take care of it right away (we should be at the very start or end of a rendering quantum). + updateNumberOfChannels(); + } else { + // Let the context take care of it in the audio thread in the pre and post render tasks. + context()->markAudioNodeOutputDirty(this); + } +} + +void AudioNodeOutput::setInternalBus() +{ + switch (m_numberOfChannels) { + case 0: + case 1: + m_internalOutputBus = m_monoInternalBus.get(); + break; + case 2: + m_internalOutputBus = m_stereoInternalBus.get(); + break; + default: + // FIXME: later we can fully implement more than stereo, 5.1, etc. + ASSERT_NOT_REACHED(); + } + + // This may later be changed in pull() to point to an in-place bus with the same number of channels. + m_actualDestinationBus = m_internalOutputBus; +} + +void AudioNodeOutput::updateRenderingState() +{ + updateNumberOfChannels(); + m_renderingFanOutCount = fanOutCount(); +} + +void AudioNodeOutput::updateNumberOfChannels() +{ + ASSERT(context()->isAudioThread() && context()->isGraphOwner()); + + if (m_numberOfChannels != m_desiredNumberOfChannels) { + m_numberOfChannels = m_desiredNumberOfChannels; + setInternalBus(); + propagateChannelCount(); + } +} + +void AudioNodeOutput::propagateChannelCount() +{ + ASSERT(context()->isAudioThread() && context()->isGraphOwner()); + + if (isChannelCountKnown()) { + // Announce to any nodes we're connected to that we changed our channel count for its input. + for (InputsIterator i = m_inputs.begin(); i != m_inputs.end(); ++i) { + AudioNodeInput* input = *i; + AudioNode* connectionNode = input->node(); + connectionNode->checkNumberOfChannelsForInput(input); + } + } +} + +AudioBus* AudioNodeOutput::pull(AudioBus* inPlaceBus, size_t framesToProcess) +{ + ASSERT(context()->isAudioThread()); + ASSERT(m_renderingFanOutCount > 0); + + // Causes our AudioNode to process if it hasn't already for this render quantum. + // We try to do in-place processing (using inPlaceBus) if at all possible, + // but we can't process in-place if we're connected to more than one input (fan-out > 1). + // In this case pull() is called multiple times per rendering quantum, and the processIfNecessary() call below will + // cause our node to process() only the first time, caching the output in m_internalOutputBus for subsequent calls. + + bool isInPlace = inPlaceBus && inPlaceBus->numberOfChannels() == numberOfChannels() && m_renderingFanOutCount == 1; + + // Setup the actual destination bus for processing when our node's process() method gets called in processIfNecessary() below. + m_actualDestinationBus = isInPlace ? inPlaceBus : m_internalOutputBus; + + node()->processIfNecessary(framesToProcess); + return m_actualDestinationBus; +} + +AudioBus* AudioNodeOutput::bus() const +{ + ASSERT(const_cast<AudioNodeOutput*>(this)->context()->isAudioThread()); + ASSERT(m_actualDestinationBus); + return m_actualDestinationBus; +} + +unsigned AudioNodeOutput::renderingFanOutCount() const +{ + return m_renderingFanOutCount; +} + +unsigned AudioNodeOutput::fanOutCount() +{ + ASSERT(context()->isGraphOwner()); + return m_inputs.size(); +} + +void AudioNodeOutput::addInput(AudioNodeInput* input) +{ + ASSERT(context()->isGraphOwner()); + + ASSERT(input); + if (!input) + return; + + m_inputs.add(input); +} + +void AudioNodeOutput::removeInput(AudioNodeInput* input) +{ + ASSERT(context()->isGraphOwner()); + + ASSERT(input); + if (!input) + return; + + m_inputs.remove(input); +} + +void AudioNodeOutput::disconnectAllInputs() +{ + ASSERT(context()->isGraphOwner()); + + // AudioNodeInput::disconnect() changes m_inputs by calling removeInput(). + while (!m_inputs.isEmpty()) { + AudioNodeInput* input = *m_inputs.begin(); + input->disconnect(this); + } +} + +void AudioNodeOutput::disable() +{ + ASSERT(context()->isGraphOwner()); + + if (m_isEnabled) { + for (InputsIterator i = m_inputs.begin(); i != m_inputs.end(); ++i) { + AudioNodeInput* input = *i; + input->disable(this); + } + m_isEnabled = false; + } +} + +void AudioNodeOutput::enable() +{ + ASSERT(context()->isGraphOwner()); + + if (!m_isEnabled) { + for (InputsIterator i = m_inputs.begin(); i != m_inputs.end(); ++i) { + AudioNodeInput* input = *i; + input->enable(this); + } + m_isEnabled = true; + } +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/AudioNodeOutput.h b/WebCore/webaudio/AudioNodeOutput.h new file mode 100644 index 0000000..7114b38 --- /dev/null +++ b/WebCore/webaudio/AudioNodeOutput.h @@ -0,0 +1,134 @@ +/* + * 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 AudioNodeOutput_h +#define AudioNodeOutput_h + +#include "AudioBus.h" +#include "AudioNode.h" +#include <wtf/HashSet.h> +#include <wtf/OwnPtr.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class AudioContext; +class AudioNodeInput; + +// AudioNodeOutput represents a single output for an AudioNode. +// It may be connected to one or more AudioNodeInputs. + +class AudioNodeOutput { +public: + // It's OK to pass 0 for numberOfChannels in which case setNumberOfChannels() must be called later on. + AudioNodeOutput(AudioNode*, unsigned numberOfChannels); + + // Can be called from any thread. + AudioNode* node() const { return m_node; } + AudioContext* context() { return m_node->context(); } + + // Causes our AudioNode to process if it hasn't already for this render quantum. + // It returns the bus containing the processed audio for this output, returning inPlaceBus if in-place processing was possible. + // Called from context's audio thread. + AudioBus* pull(AudioBus* inPlaceBus, size_t framesToProcess); + + // bus() will contain the rendered audio after pull() is called for each rendering time quantum. + // Called from context's audio thread. + AudioBus* bus() const; + + // fanOutCount() is the number of AudioNodeInputs that we're connected to. + // This function should not be called in audio thread rendering code, instead renderingFanOutCount() should be used. + // It must be called with the context's graph lock. + unsigned fanOutCount(); + + // renderingFanOutCount() is the number of AudioNodeInputs that we're connected to during rendering. + // Unlike fanOutCount() it will not change during the course of a render quantum. + unsigned renderingFanOutCount() const; + + // It must be called with the context's graph lock. + void disconnectAllInputs(); + + void setNumberOfChannels(unsigned); + unsigned numberOfChannels() const { return m_numberOfChannels; } + bool isChannelCountKnown() const { return numberOfChannels() > 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. + void disable(); + void enable(); + + // updateRenderingState() is called in the audio thread at the start or end of the render quantum to handle any recent changes to the graph state. + // It must be called with the context's graph lock. + void updateRenderingState(); + +private: + AudioNode* m_node; + + friend class AudioNodeInput; + + // These are called from AudioNodeInput. + // They must be called with the context's graph lock. + void addInput(AudioNodeInput*); + void removeInput(AudioNodeInput*); + + // setInternalBus() sets m_internalOutputBus appropriately for the number of channels. + // It is called in the constructor or in the audio thread with the context's graph lock. + void setInternalBus(); + + // Announce to any nodes we're connected to that we changed our channel count for its input. + // It must be called in the audio thread with the context's graph lock. + void propagateChannelCount(); + + // updateNumberOfChannels() is called in the audio thread at the start or end of the render quantum to pick up channel changes. + // It must be called with the context's graph lock. + void updateNumberOfChannels(); + + // m_numberOfChannels will only be changed in the audio thread. + // The main thread sets m_desiredNumberOfChannels which will later get picked up in the audio thread in updateNumberOfChannels(). + unsigned m_numberOfChannels; + unsigned m_desiredNumberOfChannels; + + // m_internalOutputBus will point to either m_monoInternalBus or m_stereoInternalBus. + // It must only be changed in the audio thread (or constructor). + AudioBus* m_internalOutputBus; + OwnPtr<AudioBus> m_monoInternalBus; + OwnPtr<AudioBus> m_stereoInternalBus; + + // m_actualDestinationBus is set in pull() and will either point to one of our internal busses or to the in-place bus. + // It must only be changed in the audio thread (or constructor). + AudioBus* m_actualDestinationBus; + + HashSet<AudioNodeInput*> m_inputs; + typedef HashSet<AudioNodeInput*>::iterator InputsIterator; + bool m_isEnabled; + + // For the purposes of rendering, keeps track of the number of inputs we're connected to. + // This value should only be changed at the very start or end of the rendering quantum. + unsigned m_renderingFanOutCount; +}; + +} // namespace WebCore + +#endif // AudioNodeOutput_h diff --git a/WebCore/webaudio/DelayNode.cpp b/WebCore/webaudio/DelayNode.cpp new file mode 100644 index 0000000..29fceae --- /dev/null +++ b/WebCore/webaudio/DelayNode.cpp @@ -0,0 +1,47 @@ +/* + * 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 "DelayNode.h" + +namespace WebCore { + +DelayNode::DelayNode(AudioContext* context, double sampleRate) + : AudioBasicProcessorNode(context, sampleRate) +{ + m_processor = adoptPtr(new DelayProcessor(sampleRate, 1)); + setType(NodeTypeDelay); +} + +AudioParam* DelayNode::delayTime() +{ + return delayProcessor()->delayTime(); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/DelayNode.h b/WebCore/webaudio/DelayNode.h new file mode 100644 index 0000000..93ad227 --- /dev/null +++ b/WebCore/webaudio/DelayNode.h @@ -0,0 +1,53 @@ +/* + * 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 DelayNode_h +#define DelayNode_h + +#include "AudioBasicProcessorNode.h" +#include "DelayProcessor.h" +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class AudioParam; + +class DelayNode : public AudioBasicProcessorNode { +public: + static PassRefPtr<DelayNode> create(AudioContext* context, double sampleRate) + { + return adoptRef(new DelayNode(context, sampleRate)); + } + + AudioParam* delayTime(); + +private: + DelayNode(AudioContext*, double sampleRate); + + DelayProcessor* delayProcessor() { return static_cast<DelayProcessor*>(processor()); } +}; + +} // namespace WebCore + +#endif // DelayNode_h diff --git a/WebCore/webaudio/DelayNode.idl b/WebCore/webaudio/DelayNode.idl new file mode 100644 index 0000000..7756627 --- /dev/null +++ b/WebCore/webaudio/DelayNode.idl @@ -0,0 +1,32 @@ +/* + * 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. + */ + +module audio { + interface [ + Conditional=WEB_AUDIO, + GenerateToJS + ] DelayNode : AudioNode { + readonly attribute AudioParam delayTime; + }; +} diff --git a/WebCore/webaudio/DelayProcessor.cpp b/WebCore/webaudio/DelayProcessor.cpp new file mode 100644 index 0000000..5fdc8df --- /dev/null +++ b/WebCore/webaudio/DelayProcessor.cpp @@ -0,0 +1,54 @@ +/* + * 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 "DelayProcessor.h" + +#include "DelayDSPKernel.h" + +namespace WebCore { + +DelayProcessor::DelayProcessor(double sampleRate, unsigned numberOfChannels) + : AudioDSPKernelProcessor(sampleRate, numberOfChannels) +{ + m_delayTime = AudioParam::create("delayTime", 0.0, 0.0, 1.0); +} + +DelayProcessor::~DelayProcessor() +{ + if (isInitialized()) + uninitialize(); +} + +PassOwnPtr<AudioDSPKernel> DelayProcessor::createKernel() +{ + return adoptPtr(new DelayDSPKernel(this)); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/DelayProcessor.h b/WebCore/webaudio/DelayProcessor.h new file mode 100644 index 0000000..4844c4b --- /dev/null +++ b/WebCore/webaudio/DelayProcessor.h @@ -0,0 +1,53 @@ +/* + * 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 DelayProcessor_h +#define DelayProcessor_h + +#include "AudioDSPKernelProcessor.h" +#include "AudioParam.h" + +#include <wtf/PassOwnPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class AudioDSPKernel; + +class DelayProcessor : public AudioDSPKernelProcessor { +public: + DelayProcessor(double sampleRate, unsigned numberOfChannels); + virtual ~DelayProcessor(); + + virtual PassOwnPtr<AudioDSPKernel> createKernel(); + + AudioParam* delayTime() const { return m_delayTime.get(); } + +private: + RefPtr<AudioParam> m_delayTime; +}; + +} // namespace WebCore + +#endif // DelayProcessor_h |