diff options
Diffstat (limited to 'WebCore/webaudio')
31 files changed, 2209 insertions, 54 deletions
diff --git a/WebCore/webaudio/AudioBasicProcessorNode.cpp b/WebCore/webaudio/AudioBasicProcessorNode.cpp new file mode 100644 index 0000000..cadaa73 --- /dev/null +++ b/WebCore/webaudio/AudioBasicProcessorNode.cpp @@ -0,0 +1,146 @@ +/* + * 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 "AudioBasicProcessorNode.h" + +#include "AudioBus.h" +#include "AudioNodeInput.h" +#include "AudioNodeOutput.h" +#include "AudioProcessor.h" + +namespace WebCore { + +AudioBasicProcessorNode::AudioBasicProcessorNode(AudioContext* context, double sampleRate) + : AudioNode(context, sampleRate) +{ + addInput(adoptPtr(new AudioNodeInput(this))); + addOutput(adoptPtr(new AudioNodeOutput(this, 0))); + + // The subclass must create m_processor. +} + +void AudioBasicProcessorNode::initialize() +{ + if (isInitialized()) + return; + + ASSERT(processor()); + processor()->initialize(); + + AudioNode::initialize(); +} + +void AudioBasicProcessorNode::uninitialize() +{ + if (!isInitialized()) + return; + + ASSERT(processor()); + processor()->uninitialize(); + + AudioNode::uninitialize(); +} + +void AudioBasicProcessorNode::process(size_t framesToProcess) +{ + AudioBus* destinationBus = output(0)->bus(); + + // The realtime thread can't block on this lock, so we call tryLock() instead. + if (m_processLock.tryLock()) { + if (!isInitialized() || !processor()) + destinationBus->zero(); + else { + AudioBus* sourceBus = input(0)->bus(); + + // FIXME: if we take "tail time" into account, then we can avoid calling processor()->process() once the tail dies down. + if (!input(0)->isConnected()) + sourceBus->zero(); + + processor()->process(sourceBus, destinationBus, framesToProcess); + } + + m_processLock.unlock(); + } else { + // Too bad - the tryLock() failed. We must be in the middle of re-connecting and were already outputting silence anyway... + destinationBus->zero(); + } +} + +// Nice optimization in the very common case allowing for "in-place" processing +void AudioBasicProcessorNode::pullInputs(size_t framesToProcess) +{ + // Render input stream - suggest to the input to render directly into output bus for in-place processing in process() if possible. + input(0)->pull(output(0)->bus(), framesToProcess); +} + +void AudioBasicProcessorNode::reset() +{ + if (processor()) + processor()->reset(); +} + +// As soon as we know the channel count of our input, we can lazily initialize. +// Sometimes this may be called more than once with different channel counts, in which case we must safely +// uninitialize and then re-initialize with the new channel count. +void AudioBasicProcessorNode::checkNumberOfChannelsForInput(AudioNodeInput* input) +{ + ASSERT(isMainThread()); + + ASSERT(input == this->input(0)); + if (input != this->input(0)) + return; + + ASSERT(processor()); + if (!processor()) + return; + + unsigned numberOfChannels = input->numberOfChannels(); + + if (isInitialized() && numberOfChannels != output(0)->numberOfChannels()) { + // We're already initialized but the channel count has changed. + // We need to be careful since we may be actively processing right now, so synchronize with process(). + MutexLocker locker(m_processLock); + uninitialize(); + } + + // This will propagate the channel count to any nodes connected further down the chain... + output(0)->setNumberOfChannels(numberOfChannels); + + // Re-initialize the processor with the new channel count. + processor()->setNumberOfChannels(numberOfChannels); + initialize(); +} + +unsigned AudioBasicProcessorNode::numberOfChannels() +{ + return output(0)->numberOfChannels(); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/AudioBasicProcessorNode.h b/WebCore/webaudio/AudioBasicProcessorNode.h new file mode 100644 index 0000000..38bfd3b --- /dev/null +++ b/WebCore/webaudio/AudioBasicProcessorNode.h @@ -0,0 +1,68 @@ +/* + * 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 AudioBasicProcessorNode_h +#define AudioBasicProcessorNode_h + +#include "AudioNode.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/Threading.h> + +namespace WebCore { + +class AudioBus; +class AudioNodeInput; +class AudioProcessor; + +// AudioBasicProcessorNode is an AudioNode with one input and one output where the input and output have the same number of channels. +class AudioBasicProcessorNode : public AudioNode { +public: + AudioBasicProcessorNode(AudioContext*, double sampleRate); + + // AudioNode + virtual void process(size_t framesToProcess); + virtual void pullInputs(size_t framesToProcess); + virtual void reset(); + virtual void initialize(); + virtual void uninitialize(); + + // Called in the main thread when the number of channels for the input may have changed. + virtual void checkNumberOfChannelsForInput(AudioNodeInput*); + + // Returns the number of channels for both the input and the output. + unsigned numberOfChannels(); + +protected: + AudioProcessor* processor() { return m_processor.get(); } + OwnPtr<AudioProcessor> m_processor; + +private: + // This synchronizes live channel count changes which require an uninitialization / re-initialization. + mutable Mutex m_processLock; +}; + +} // namespace WebCore + +#endif // AudioBasicProcessorNode_h diff --git a/WebCore/webaudio/AudioChannelMerger.cpp b/WebCore/webaudio/AudioChannelMerger.cpp new file mode 100644 index 0000000..c418a61 --- /dev/null +++ b/WebCore/webaudio/AudioChannelMerger.cpp @@ -0,0 +1,102 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 "AudioChannelMerger.h" + +#include "AudioNodeInput.h" +#include "AudioNodeOutput.h" + +namespace WebCore { + +// This is considering that 5.1 (6 channels) is the largest we'll ever deal with. +// It can easily be increased to support more if the web audio specification is updated. +const unsigned NumberOfInputs = 6; + +AudioChannelMerger::AudioChannelMerger(AudioContext* context, double sampleRate) + : AudioNode(context, sampleRate) +{ + // Create a fixed number of inputs (able to handle the maximum number of channels we deal with). + for (unsigned i = 0; i < NumberOfInputs; ++i) + addInput(adoptPtr(new AudioNodeInput(this))); + + addOutput(adoptPtr(new AudioNodeOutput(this, 1))); + + setType(NodeTypeChannelMerger); + + initialize(); +} + +void AudioChannelMerger::process(size_t framesToProcess) +{ + AudioNodeOutput* output = this->output(0); + ASSERT(output); + ASSERT_UNUSED(framesToProcess, framesToProcess == output->bus()->length()); + + // Count how many channels we have all together from all of the inputs. + unsigned numberOfOutputChannels = 0; + for (unsigned i = 0; i < numberOfInputs(); ++i) { + AudioNodeInput* input = this->input(i); + if (input->isConnected()) + numberOfOutputChannels += input->bus()->numberOfChannels(); + } + + // Set the correct number of channels on the output + output->setNumberOfChannels(numberOfOutputChannels); + + // Now merge the channels back into one output. + unsigned outputChannelIndex = 0; + for (unsigned i = 0; i < numberOfInputs(); ++i) { + AudioNodeInput* input = this->input(i); + if (input->isConnected()) { + unsigned numberOfInputChannels = input->bus()->numberOfChannels(); + + // Merge channels from this particular input. + for (unsigned j = 0; j < numberOfInputChannels; ++j) { + AudioChannel* inputChannel = input->bus()->channel(j); + AudioChannel* outputChannel = output->bus()->channel(outputChannelIndex); + outputChannel->copyFrom(inputChannel); + + ++outputChannelIndex; + } + } + } + + ASSERT(outputChannelIndex == numberOfOutputChannels); +} + +void AudioChannelMerger::reset() +{ +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/AudioChannelMerger.h b/WebCore/webaudio/AudioChannelMerger.h new file mode 100644 index 0000000..20a9628 --- /dev/null +++ b/WebCore/webaudio/AudioChannelMerger.h @@ -0,0 +1,56 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 AudioChannelMerger_h +#define AudioChannelMerger_h + +#include "AudioNode.h" +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class AudioContext; + +class AudioChannelMerger : public AudioNode { +public: + static PassRefPtr<AudioChannelMerger> create(AudioContext* context, double sampleRate) + { + return adoptRef(new AudioChannelMerger(context, sampleRate)); + } + + // AudioNode + virtual void process(size_t framesToProcess); + virtual void reset(); + +private: + AudioChannelMerger(AudioContext*, double sampleRate); +}; + +} // namespace WebCore + +#endif // AudioChannelMerger_h diff --git a/WebCore/webaudio/AudioChannelMerger.idl b/WebCore/webaudio/AudioChannelMerger.idl new file mode 100644 index 0000000..3862af9 --- /dev/null +++ b/WebCore/webaudio/AudioChannelMerger.idl @@ -0,0 +1,34 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 + ] AudioChannelMerger : AudioNode { + }; +} diff --git a/WebCore/webaudio/AudioChannelSplitter.cpp b/WebCore/webaudio/AudioChannelSplitter.cpp new file mode 100644 index 0000000..2689cd7 --- /dev/null +++ b/WebCore/webaudio/AudioChannelSplitter.cpp @@ -0,0 +1,88 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 "AudioChannelSplitter.h" + +#include "AudioNodeInput.h" +#include "AudioNodeOutput.h" + +namespace WebCore { + +// This is considering that 5.1 (6 channels) is the largest we'll ever deal with. +// It can easily be increased to support more if the web audio specification is updated. +const unsigned NumberOfOutputs = 6; + +AudioChannelSplitter::AudioChannelSplitter(AudioContext* context, double sampleRate) + : AudioNode(context, sampleRate) +{ + addInput(adoptPtr(new AudioNodeInput(this))); + + // Create a fixed number of outputs (able to handle the maximum number of channels fed to an input). + for (unsigned i = 0; i < NumberOfOutputs; ++i) + addOutput(adoptPtr(new AudioNodeOutput(this, 1))); + + setType(NodeTypeChannelSplitter); + + initialize(); +} + +void AudioChannelSplitter::process(size_t framesToProcess) +{ + AudioBus* source = input(0)->bus(); + ASSERT(source); + ASSERT_UNUSED(framesToProcess, framesToProcess == source->length()); + + unsigned numberOfSourceChannels = source->numberOfChannels(); + + ASSERT(numberOfOutputs() == NumberOfOutputs); + for (unsigned i = 0; i < NumberOfOutputs; ++i) { + AudioBus* destination = output(i)->bus(); + ASSERT(destination); + + if (i < numberOfSourceChannels) { + // Split the channel out if it exists in the source. + // It would be nice to avoid the copy and simply pass along pointers, but this becomes extremely difficult with fanout and fanin. + destination->channel(0)->copyFrom(source->channel(i)); + } else if (output(i)->fanOutCount() > 0) { + // Only bother zeroing out the destination if it's connected to anything + destination->zero(); + } + } +} + +void AudioChannelSplitter::reset() +{ +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/AudioChannelSplitter.h b/WebCore/webaudio/AudioChannelSplitter.h new file mode 100644 index 0000000..29092d6 --- /dev/null +++ b/WebCore/webaudio/AudioChannelSplitter.h @@ -0,0 +1,56 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 AudioChannelSplitter_h +#define AudioChannelSplitter_h + +#include "AudioNode.h" +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class AudioContext; + +class AudioChannelSplitter : public AudioNode { +public: + static PassRefPtr<AudioChannelSplitter> create(AudioContext* context, double sampleRate) + { + return adoptRef(new AudioChannelSplitter(context, sampleRate)); + } + + // AudioNode + virtual void process(size_t framesToProcess); + virtual void reset(); + +private: + AudioChannelSplitter(AudioContext*, double sampleRate); +}; + +} // namespace WebCore + +#endif // AudioChannelSplitter_h diff --git a/WebCore/webaudio/AudioChannelSplitter.idl b/WebCore/webaudio/AudioChannelSplitter.idl new file mode 100644 index 0000000..a7450e6 --- /dev/null +++ b/WebCore/webaudio/AudioChannelSplitter.idl @@ -0,0 +1,34 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 + ] AudioChannelSplitter : AudioNode { + }; +} diff --git a/WebCore/webaudio/AudioContext.cpp b/WebCore/webaudio/AudioContext.cpp index 6ca8ee1..f971e6a 100644 --- a/WebCore/webaudio/AudioContext.cpp +++ b/WebCore/webaudio/AudioContext.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" @@ -58,7 +54,9 @@ // FIXME: check the proper way to reference an undefined thread ID const int UndefinedThreadIdentifier = 0xffffffff; - + +const unsigned MaxNodesToDeletePerQuantum = 10; + namespace WebCore { PassRefPtr<CachedAudio> AudioContext::createAudioRequest(const String &url, bool mixToMono) @@ -102,10 +100,10 @@ AudioContext::AudioContext(Document* document) m_temporaryStereoBus = adoptPtr(new AudioBus(2, AudioNode::ProcessingSizeInFrames)); // This sets in motion an asynchronous loading mechanism on another thread. - // We can check hrtfDatabaseLoader()->isLoaded() to find out whether or not it has been fully loaded. + // We can check m_hrtfDatabaseLoader->isLoaded() to find out whether or not it has been fully loaded. // It's not that useful to have a callback function for this since the audio thread automatically starts rendering on the graph // when this has finished (see AudioDestinationNode). - hrtfDatabaseLoader()->loadAsynchronously(sampleRate()); + m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate()); } AudioContext::~AudioContext() @@ -172,7 +170,7 @@ bool AudioContext::isRunnable() const return false; // Check with the HRTF spatialization system to see if it's finished loading. - return hrtfDatabaseLoader()->isLoaded(); + return m_hrtfDatabaseLoader->isLoaded(); } void AudioContext::stop() @@ -346,10 +344,9 @@ void AudioContext::lock(bool& mustReleaseLock) } else { // Acquire the lock. m_contextGraphMutex.lock(); + m_graphOwnerThread = thisThread; mustReleaseLock = true; } - - m_graphOwnerThread = thisThread; } bool AudioContext::tryLock(bool& mustReleaseLock) @@ -412,7 +409,7 @@ void AudioContext::addDeferredFinishDeref(AudioNode* node, AudioNode::RefType re void AudioContext::handlePostRenderTasks() { ASSERT(isAudioThread()); - + // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently. // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed // from the render graph (in which case they'll render silence). @@ -434,7 +431,7 @@ void AudioContext::handlePostRenderTasks() void AudioContext::handleDeferredFinishDerefs() { - ASSERT(isAudioThread()); + ASSERT(isAudioThread() && isGraphOwner()); for (unsigned i = 0; i < m_deferredFinishDerefList.size(); ++i) { AudioNode* node = m_deferredFinishDerefList[i].m_node; AudioNode::RefType refType = m_deferredFinishDerefList[i].m_refType; @@ -455,10 +452,15 @@ void AudioContext::deleteMarkedNodes() ASSERT(isGraphOwner() || isAudioThreadFinished()); // Note: deleting an AudioNode can cause m_nodesToDelete to grow. + size_t nodesDeleted = 0; while (size_t n = m_nodesToDelete.size()) { AudioNode* node = m_nodesToDelete[n - 1]; m_nodesToDelete.removeLast(); 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. + if (++nodesDeleted > MaxNodesToDeletePerQuantum) + break; } } diff --git a/WebCore/webaudio/AudioContext.h b/WebCore/webaudio/AudioContext.h index f175bfe..9fe1347 100644 --- a/WebCore/webaudio/AudioContext.h +++ b/WebCore/webaudio/AudioContext.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 AudioContext_h @@ -32,6 +28,7 @@ #include "ActiveDOMObject.h" #include "AudioBus.h" #include "AudioDestinationNode.h" +#include "HRTFDatabaseLoader.h" #include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -241,6 +238,9 @@ private: // Only accessed in the audio thread. Vector<RefInfo> m_deferredFinishDerefList; + + // HRTF Database loader + RefPtr<HRTFDatabaseLoader> m_hrtfDatabaseLoader; }; } // WebCore diff --git a/WebCore/webaudio/AudioContext.idl b/WebCore/webaudio/AudioContext.idl index 8951121..35aea35 100644 --- a/WebCore/webaudio/AudioContext.idl +++ b/WebCore/webaudio/AudioContext.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 webaudio { diff --git a/WebCore/webaudio/AudioGainNode.cpp b/WebCore/webaudio/AudioGainNode.cpp new file mode 100644 index 0000000..332929d --- /dev/null +++ b/WebCore/webaudio/AudioGainNode.cpp @@ -0,0 +1,116 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 "AudioGainNode.h" + +#include "AudioBus.h" +#include "AudioNodeInput.h" +#include "AudioNodeOutput.h" + +namespace WebCore { + +AudioGainNode::AudioGainNode(AudioContext* context, double sampleRate) + : AudioNode(context, sampleRate) + , m_lastGain(1.0) +{ + m_gain = AudioGain::create("gain", 1.0, 0.0, 1.0); + + addInput(adoptPtr(new AudioNodeInput(this))); + addOutput(adoptPtr(new AudioNodeOutput(this, 1))); + + setType(NodeTypeGain); + + initialize(); +} + +void AudioGainNode::process(size_t /*framesToProcess*/) +{ + // FIXME: there is a nice optimization to avoid processing here, and let the gain change + // happen in the summing junction input of the AudioNode we're connected to. + // Then we can avoid all of the following: + + AudioBus* outputBus = output(0)->bus(); + ASSERT(outputBus); + + // The realtime thread can't block on this lock, so we call tryLock() instead. + if (m_processLock.tryLock()) { + if (!isInitialized() || !input(0)->isConnected()) + outputBus->zero(); + else { + AudioBus* inputBus = input(0)->bus(); + + // Apply the gain with de-zippering into the output bus. + outputBus->copyWithGainFrom(*inputBus, &m_lastGain, gain()->value()); + } + + m_processLock.unlock(); + } else { + // Too bad - the tryLock() failed. We must be in the middle of re-connecting and were already outputting silence anyway... + outputBus->zero(); + } +} + +void AudioGainNode::reset() +{ + // Snap directly to desired gain. + m_lastGain = gain()->value(); +} + +// FIXME: this can go away when we do mixing with gain directly in summing junction of AudioNodeInput +// +// As soon as we know the channel count of our input, we can lazily initialize. +// Sometimes this may be called more than once with different channel counts, in which case we must safely +// uninitialize and then re-initialize with the new channel count. +void AudioGainNode::checkNumberOfChannelsForInput(AudioNodeInput* input) +{ + ASSERT(input && input == this->input(0)); + if (input != this->input(0)) + return; + + unsigned numberOfChannels = input->numberOfChannels(); + + if (isInitialized() && numberOfChannels != output(0)->numberOfChannels()) { + // We're already initialized but the channel count has changed. + // We need to be careful since we may be actively processing right now, so synchronize with process(). + MutexLocker locker(m_processLock); + uninitialize(); + } + + // This will propagate the channel count to any nodes connected further downstream in the graph. + output(0)->setNumberOfChannels(numberOfChannels); + + initialize(); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/AudioGainNode.h b/WebCore/webaudio/AudioGainNode.h new file mode 100644 index 0000000..91f9d16 --- /dev/null +++ b/WebCore/webaudio/AudioGainNode.h @@ -0,0 +1,74 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 AudioGainNode_h +#define AudioGainNode_h + +#include "AudioGain.h" +#include "AudioNode.h" +#include <wtf/PassRefPtr.h> +#include <wtf/Threading.h> + +namespace WebCore { + +class AudioContext; + +// AudioGainNode is an AudioNode with one input and one output which applies a gain (volume) change to the audio signal. +// De-zippering (smoothing) is applied when the gain value is changed dynamically. + +class AudioGainNode : public AudioNode { +public: + static PassRefPtr<AudioGainNode> create(AudioContext* context, double sampleRate) + { + return adoptRef(new AudioGainNode(context, sampleRate)); + } + + // AudioNode + virtual void process(size_t framesToProcess); + virtual void reset(); + + // Called in the main thread when the number of channels for the input may have changed. + virtual void checkNumberOfChannelsForInput(AudioNodeInput*); + + // JavaScript interface + AudioGain* gain() { return m_gain.get(); } + +private: + AudioGainNode(AudioContext*, double sampleRate); + + double m_lastGain; // for de-zippering + RefPtr<AudioGain> m_gain; + + // This synchronizes live channel count changes which require an uninitialization / re-initialization. + // FIXME: this can go away when we implement optimization for mixing with gain directly in summing junction of AudioNodeInput. + mutable Mutex m_processLock; +}; + +} // namespace WebCore + +#endif // AudioGainNode_h diff --git a/WebCore/webaudio/AudioGainNode.idl b/WebCore/webaudio/AudioGainNode.idl new file mode 100644 index 0000000..8bf117a --- /dev/null +++ b/WebCore/webaudio/AudioGainNode.idl @@ -0,0 +1,37 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 + ] AudioGainNode : AudioNode { + // FIXME: eventually it will be interesting to remove the readonly restriction, but need to properly deal with thread safety here. + readonly attribute AudioGain gain; + }; +} diff --git a/WebCore/webaudio/AudioNode.cpp b/WebCore/webaudio/AudioNode.cpp index 497ac95..9335c10 100644 --- a/WebCore/webaudio/AudioNode.cpp +++ b/WebCore/webaudio/AudioNode.cpp @@ -67,6 +67,16 @@ AudioNode::~AudioNode() #endif } +void AudioNode::initialize() +{ + m_isInitialized = true; +} + +void AudioNode::uninitialize() +{ + m_isInitialized = false; +} + void AudioNode::setType(NodeType type) { m_type = type; diff --git a/WebCore/webaudio/AudioNode.h b/WebCore/webaudio/AudioNode.h index b697457..52f886d 100644 --- a/WebCore/webaudio/AudioNode.h +++ b/WebCore/webaudio/AudioNode.h @@ -100,8 +100,8 @@ public: // No significant resources should be allocated until initialize() is called. // Processing may not occur until a node is initialized. - virtual void initialize() = 0; - virtual void uninitialize() = 0; + virtual void initialize(); + virtual void uninitialize(); bool isInitialized() const { return m_isInitialized; } void lazyInitialize(); @@ -144,9 +144,8 @@ protected: // Called from context's audio thread. virtual void pullInputs(size_t framesToProcess); - bool m_isInitialized; - private: + volatile bool m_isInitialized; NodeType m_type; RefPtr<AudioContext> m_context; double m_sampleRate; diff --git a/WebCore/webaudio/AudioPannerNode.cpp b/WebCore/webaudio/AudioPannerNode.cpp new file mode 100644 index 0000000..b7282e3 --- /dev/null +++ b/WebCore/webaudio/AudioPannerNode.cpp @@ -0,0 +1,321 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 "AudioPannerNode.h" + +#include "AudioBufferSourceNode.h" +#include "AudioBus.h" +#include "AudioContext.h" +#include "AudioNodeInput.h" +#include "AudioNodeOutput.h" +#include "HRTFPanner.h" +#include <wtf/MathExtras.h> + +using namespace std; + +namespace WebCore { + +static void fixNANs(double &x) +{ + if (isnan(x) || isinf(x)) + x = 0.0; +} + +AudioPannerNode::AudioPannerNode(AudioContext* context, double sampleRate) + : AudioNode(context, sampleRate) + , m_panningModel(Panner::PanningModelHRTF) + , m_lastGain(-1.0) + , m_connectionCount(0) +{ + addInput(adoptPtr(new AudioNodeInput(this))); + addOutput(adoptPtr(new AudioNodeOutput(this, 2))); + + m_distanceGain = AudioGain::create("distanceGain", 1.0, 0.0, 1.0); + m_coneGain = AudioGain::create("coneGain", 1.0, 0.0, 1.0); + + m_position = Vector3(0, 0, 0); + m_orientation = Vector3(1, 0, 0); + m_velocity = Vector3(0, 0, 0); + + setType(NodeTypePanner); + + initialize(); +} + +AudioPannerNode::~AudioPannerNode() +{ + uninitialize(); +} + +void AudioPannerNode::pullInputs(size_t framesToProcess) +{ + // We override pullInputs(), so we can detect new AudioSourceNodes which have connected to us when new connections are made. + // These AudioSourceNodes need to be made aware of our existence in order to handle doppler shift pitch changes. + if (m_connectionCount != context()->connectionCount()) { + m_connectionCount = context()->connectionCount(); + + // Recursively go through all nodes connected to us. + notifyAudioSourcesConnectedToNode(this); + } + + AudioNode::pullInputs(framesToProcess); +} + +void AudioPannerNode::process(size_t framesToProcess) +{ + AudioBus* destination = output(0)->bus(); + + if (!isInitialized() || !input(0)->isConnected() || !m_panner.get()) { + destination->zero(); + return; + } + + AudioBus* source = input(0)->bus(); + + if (!source) { + destination->zero(); + return; + } + + // Apply the panning effect. + double azimuth; + double elevation; + getAzimuthElevation(&azimuth, &elevation); + m_panner->pan(azimuth, elevation, source, destination, framesToProcess); + + // Get the distance and cone gain. + double totalGain = distanceConeGain(); + + // Snap to desired gain at the beginning. + if (m_lastGain == -1.0) + m_lastGain = totalGain; + + // Apply gain in-place with de-zippering. + destination->copyWithGainFrom(*destination, &m_lastGain, totalGain); +} + +void AudioPannerNode::reset() +{ + m_lastGain = -1.0; // force to snap to initial gain + if (m_panner.get()) + m_panner->reset(); +} + +void AudioPannerNode::initialize() +{ + if (isInitialized()) + return; + + m_panner = Panner::create(m_panningModel, sampleRate()); + + AudioNode::initialize(); +} + +void AudioPannerNode::uninitialize() +{ + if (!isInitialized()) + return; + + m_panner.clear(); + AudioNode::uninitialize(); +} + +AudioListener* AudioPannerNode::listener() +{ + return context()->listener(); +} + +void AudioPannerNode::setPanningModel(unsigned short model) +{ + if (!m_panner.get() || model != m_panningModel) { + OwnPtr<Panner> newPanner = Panner::create(model, sampleRate()); + m_panner = newPanner.release(); + } +} + +void AudioPannerNode::getAzimuthElevation(double* outAzimuth, double* outElevation) +{ + // FIXME: we should cache azimuth and elevation (if possible), so we only re-calculate if a change has been made. + + double azimuth = 0.0; + + // Calculate the source-listener vector + Vector3 listenerPosition = listener()->position(); + Vector3 sourceListener = m_position - listenerPosition; + + if (sourceListener.isZero()) { + // degenerate case if source and listener are at the same point + *outAzimuth = 0.0; + *outElevation = 0.0; + return; + } + + sourceListener.normalize(); + + // Align axes + Vector3 listenerFront = listener()->orientation(); + Vector3 listenerUp = listener()->upVector(); + Vector3 listenerRight = cross(listenerFront, listenerUp); + listenerRight.normalize(); + + Vector3 listenerFrontNorm = listenerFront; + listenerFrontNorm.normalize(); + + Vector3 up = cross(listenerRight, listenerFrontNorm); + + double upProjection = dot(sourceListener, up); + + Vector3 projectedSource = sourceListener - upProjection * up; + projectedSource.normalize(); + + azimuth = 180.0 * acos(dot(projectedSource, listenerRight)) / M_PI; + fixNANs(azimuth); // avoid illegal values + + // Source in front or behind the listener + double frontBack = dot(projectedSource, listenerFrontNorm); + if (frontBack < 0.0) + azimuth = 360.0 - azimuth; + + // Make azimuth relative to "front" and not "right" listener vector + if ((azimuth >= 0.0) && (azimuth <= 270.0)) + azimuth = 90.0 - azimuth; + else + azimuth = 450.0 - azimuth; + + // Elevation + double elevation = 90.0 - 180.0 * acos(dot(sourceListener, up)) / M_PI; + fixNANs(azimuth); // avoid illegal values + + if (elevation > 90.0) + elevation = 180.0 - elevation; + else if (elevation < -90.0) + elevation = -180.0 - elevation; + + if (outAzimuth) + *outAzimuth = azimuth; + if (outElevation) + *outElevation = elevation; +} + +float AudioPannerNode::dopplerRate() +{ + double dopplerShift = 1.0; + + // FIXME: optimize for case when neither source nor listener has changed... + double dopplerFactor = listener()->dopplerFactor(); + + if (dopplerFactor > 0.0) { + double speedOfSound = listener()->speedOfSound(); + + const Vector3 &sourceVelocity = m_velocity; + const Vector3 &listenerVelocity = listener()->velocity(); + + // Don't bother if both source and listener have no velocity + bool sourceHasVelocity = !sourceVelocity.isZero(); + bool listenerHasVelocity = !listenerVelocity.isZero(); + + if (sourceHasVelocity || listenerHasVelocity) { + // Calculate the source to listener vector + Vector3 listenerPosition = listener()->position(); + Vector3 sourceToListener = m_position - listenerPosition; + + double sourceListenerMagnitude = sourceToListener.abs(); + + double listenerProjection = dot(sourceToListener, listenerVelocity) / sourceListenerMagnitude; + double sourceProjection = dot(sourceToListener, sourceVelocity) / sourceListenerMagnitude; + + listenerProjection = -listenerProjection; + sourceProjection = -sourceProjection; + + double scaledSpeedOfSound = speedOfSound / dopplerFactor; + listenerProjection = min(listenerProjection, scaledSpeedOfSound); + sourceProjection = min(sourceProjection, scaledSpeedOfSound); + + dopplerShift = ((speedOfSound - dopplerFactor * listenerProjection) / (speedOfSound - dopplerFactor * sourceProjection)); + fixNANs(dopplerShift); // avoid illegal values + + // Limit the pitch shifting to 4 octaves up and 3 octaves down. + if (dopplerShift > 16.0) + dopplerShift = 16.0; + else if (dopplerShift < 0.125) + dopplerShift = 0.125; + } + } + + return static_cast<float>(dopplerShift); +} + +float AudioPannerNode::distanceConeGain() +{ + Vector3 listenerPosition = listener()->position(); + + double listenerDistance = distance(m_position, listenerPosition); + double distanceGain = m_distanceEffect.gain(listenerDistance); + + m_distanceGain->setValue(static_cast<float>(distanceGain)); + + // FIXME: could optimize by caching coneGain + double coneGain = m_coneEffect.gain(m_position, m_orientation, listenerPosition); + + m_coneGain->setValue(static_cast<float>(coneGain)); + + return float(distanceGain * coneGain); +} + +void AudioPannerNode::notifyAudioSourcesConnectedToNode(AudioNode* node) +{ + ASSERT(node); + if (!node) + return; + + // First check if this node is an AudioBufferSourceNode. If so, let it know about us so that doppler shift pitch can be taken into account. + if (node->type() == NodeTypeAudioBufferSource) { + AudioBufferSourceNode* bufferSourceNode = reinterpret_cast<AudioBufferSourceNode*>(node); + bufferSourceNode->setPannerNode(this); + } else { + // Go through all inputs to this node. + for (unsigned i = 0; i < node->numberOfInputs(); ++i) { + AudioNodeInput* input = node->input(i); + + // For each input, go through all of its connections, looking for AudioBufferSourceNodes. + for (unsigned j = 0; j < input->numberOfConnections(); ++j) { + AudioNodeOutput* connectedOutput = input->output(j); + AudioNode* connectedNode = connectedOutput->node(); + notifyAudioSourcesConnectedToNode(connectedNode); // recurse + } + } + } +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/AudioPannerNode.h b/WebCore/webaudio/AudioPannerNode.h new file mode 100644 index 0000000..144b61b --- /dev/null +++ b/WebCore/webaudio/AudioPannerNode.h @@ -0,0 +1,154 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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 AudioPannerNode_h +#define AudioPannerNode_h + +#include "AudioBus.h" +#include "AudioGain.h" +#include "AudioListener.h" +#include "AudioNode.h" +#include "Cone.h" +#include "Distance.h" +#include "Panner.h" +#include <wtf/OwnPtr.h> +#include <wtf/Vector3.h> + +namespace WebCore { + +// AudioPannerNode is an AudioNode with one input and one output. +// It positions a sound in 3D space, with the exact effect dependent on the panning model. +// It has a position and an orientation in 3D space which is relative to the position and orientation of the context's AudioListener. +// A distance effect will attenuate the gain as the position moves away from the listener. +// A cone effect will attenuate the gain as the orientation moves away from the listener. +// All of these effects follow the OpenAL specification very closely. + +class AudioPannerNode : public AudioNode { +public: + enum { + PASSTHROUGH = 0, + EQUALPOWER = 1, + HRTF = 2, + SOUNDFIELD = 3, + MATRIXMIX = 4 + }; + + static PassRefPtr<AudioPannerNode> create(AudioContext* context, double sampleRate) + { + return adoptRef(new AudioPannerNode(context, sampleRate)); + } + + virtual ~AudioPannerNode(); + + // AudioNode + virtual void process(size_t framesToProcess); + virtual void pullInputs(size_t framesToProcess); + virtual void reset(); + virtual void initialize(); + virtual void uninitialize(); + + // Listener + AudioListener* listener(); + + // Panning model + unsigned short panningModel() const { return m_panningModel; } + void setPanningModel(unsigned short); + + // Position + Vector3 position() const { return m_position; } + void setPosition(float x, float y, float z) { m_position = Vector3(x, y, z); } + + // Orientation + Vector3 orientation() const { return m_position; } + void setOrientation(float x, float y, float z) { m_orientation = Vector3(x, y, z); } + + // Velocity + Vector3 velocity() const { return m_velocity; } + void setVelocity(float x, float y, float z) { m_velocity = Vector3(x, y, z); } + + // Distance parameters + unsigned short distanceModel() { return m_distanceEffect.model(); } + void setDistanceModel(unsigned short model) { m_distanceEffect.setModel(static_cast<DistanceEffect::ModelType>(model), true); } + + float refDistance() { return static_cast<float>(m_distanceEffect.refDistance()); } + void setRefDistance(float refDistance) { m_distanceEffect.setRefDistance(refDistance); } + + float maxDistance() { return static_cast<float>(m_distanceEffect.maxDistance()); } + void setMaxDistance(float maxDistance) { m_distanceEffect.setMaxDistance(maxDistance); } + + float rolloffFactor() { return static_cast<float>(m_distanceEffect.rolloffFactor()); } + void setRolloffFactor(float rolloffFactor) { m_distanceEffect.setRolloffFactor(rolloffFactor); } + + // Sound cones - angles in degrees + float coneInnerAngle() const { return static_cast<float>(m_coneEffect.innerAngle()); } + void setConeInnerAngle(float angle) { m_coneEffect.setInnerAngle(angle); } + + float coneOuterAngle() const { return static_cast<float>(m_coneEffect.outerAngle()); } + void setConeOuterAngle(float angle) { m_coneEffect.setOuterAngle(angle); } + + float coneOuterGain() const { return static_cast<float>(m_coneEffect.outerGain()); } + void setConeOuterGain(float angle) { m_coneEffect.setOuterGain(angle); } + + void getAzimuthElevation(double* outAzimuth, double* outElevation); + float dopplerRate(); + + // Accessors for dynamically calculated gain values. + AudioGain* distanceGain() { return m_distanceGain.get(); } + AudioGain* coneGain() { return m_coneGain.get(); } + +private: + AudioPannerNode(AudioContext*, double sampleRate); + + // Returns the combined distance and cone gain attenuation. + float distanceConeGain(); + + // Notifies any AudioBufferSourceNodes connected to us either directly or indirectly about our existence. + // This is in order to handle the pitch change necessary for the doppler shift. + void notifyAudioSourcesConnectedToNode(AudioNode*); + + OwnPtr<Panner> m_panner; + unsigned m_panningModel; + + // FIXME: upgrade to FloatPoint3D from Vector3. + Vector3 m_position; + Vector3 m_orientation; + Vector3 m_velocity; + + // Gain + RefPtr<AudioGain> m_distanceGain; + RefPtr<AudioGain> m_coneGain; + DistanceEffect m_distanceEffect; + ConeEffect m_coneEffect; + double m_lastGain; + + unsigned m_connectionCount; +}; + +} // namespace WebCore + +#endif // AudioPannerNode_h diff --git a/WebCore/webaudio/AudioPannerNode.idl b/WebCore/webaudio/AudioPannerNode.idl new file mode 100644 index 0000000..eb6db40 --- /dev/null +++ b/WebCore/webaudio/AudioPannerNode.idl @@ -0,0 +1,64 @@ +/* + * 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. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 + * 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, + GenerateConstructor, + GenerateToJS + ] AudioPannerNode : AudioNode { + // Panning model + const unsigned short PASSTHROUGH = 0; + const unsigned short EQUALPOWER = 1; + const unsigned short HRTF = 2; + const unsigned short SOUNDFIELD = 3; + + // Default model for stereo is HRTF + attribute unsigned long panningModel; // FIXME: use unsigned short when glue generation supports it + + // Uses a 3D cartesian coordinate system + void setPosition(in float x, in float y, in float z); + void setOrientation(in float x, in float y, in float z); + void setVelocity(in float x, in float y, in float z); + + // Distance model + attribute unsigned long distanceModel; // FIXME: use unsigned short when glue generation supports it + attribute float refDistance; + attribute float maxDistance; + attribute float rolloffFactor; + + // Directional sound cone + attribute float coneInnerAngle; + attribute float coneOuterAngle; + attribute float coneOuterGain; + + // Dynamically calculated gain values + readonly attribute AudioGain coneGain; + readonly attribute AudioGain distanceGain; + }; +} diff --git a/WebCore/webaudio/BiquadDSPKernel.cpp b/WebCore/webaudio/BiquadDSPKernel.cpp new file mode 100644 index 0000000..a4b28be --- /dev/null +++ b/WebCore/webaudio/BiquadDSPKernel.cpp @@ -0,0 +1,77 @@ +/* + * 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 "BiquadDSPKernel.h" + +#include "BiquadProcessor.h" + +namespace WebCore { + +void BiquadDSPKernel::process(const float* source, float* destination, size_t framesToProcess) +{ + ASSERT(source && destination && biquadProcessor()); + + // Recompute filter coefficients if any of the parameters have changed. + // FIXME: as an optimization, implement a way that a Biquad object can simply copy its internal filter coefficients from another Biquad object. + // Then re-factor this code to only run for the first BiquadDSPKernel of each BiquadProcessor. + if (biquadProcessor()->filterCoefficientsDirty()) { + double value1 = biquadProcessor()->parameter1()->smoothedValue(); + double value2 = biquadProcessor()->parameter2()->smoothedValue(); + + // Convert from Hertz to normalized frequency 0 -> 1. + double nyquist = this->nyquist(); + double normalizedValue1 = value1 / nyquist; + + // Configure the biquad with the new filter parameters for the appropriate type of filter. + switch (biquadProcessor()->type()) { + case BiquadProcessor::LowPass2: + m_biquad.setLowpassParams(normalizedValue1, value2); + break; + + case BiquadProcessor::HighPass2: + m_biquad.setHighpassParams(normalizedValue1, value2); + break; + + case BiquadProcessor::LowShelf: + m_biquad.setLowShelfParams(normalizedValue1, value2); + break; + + // FIXME: add other biquad filter types... + case BiquadProcessor::Peaking: + case BiquadProcessor::Allpass: + case BiquadProcessor::HighShelf: + break; + } + } + + m_biquad.process(source, destination, framesToProcess); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/BiquadDSPKernel.h b/WebCore/webaudio/BiquadDSPKernel.h new file mode 100644 index 0000000..47d0f34 --- /dev/null +++ b/WebCore/webaudio/BiquadDSPKernel.h @@ -0,0 +1,56 @@ +/* + * 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 BiquadDSPKernel_h +#define BiquadDSPKernel_h + +#include "AudioDSPKernel.h" +#include "Biquad.h" +#include "BiquadProcessor.h" + +namespace WebCore { + +class BiquadProcessor; + +// BiquadDSPKernel is an AudioDSPKernel and is responsible for filtering one channel of a BiquadProcessor using a Biquad object. + +class BiquadDSPKernel : public AudioDSPKernel { +public: + BiquadDSPKernel(BiquadProcessor* processor) + : AudioDSPKernel(processor) + { + } + + // AudioDSPKernel + virtual void process(const float* source, float* dest, size_t framesToProcess); + virtual void reset() { m_biquad.reset(); } + +protected: + Biquad m_biquad; + BiquadProcessor* biquadProcessor() { return static_cast<BiquadProcessor*>(processor()); } +}; + +} // namespace WebCore + +#endif // BiquadDSPKernel_h diff --git a/WebCore/webaudio/BiquadProcessor.cpp b/WebCore/webaudio/BiquadProcessor.cpp new file mode 100644 index 0000000..97a480e --- /dev/null +++ b/WebCore/webaudio/BiquadProcessor.cpp @@ -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. + */ + +#include "config.h" + +#if ENABLE(WEB_AUDIO) + +#include "BiquadProcessor.h" + +#include "BiquadDSPKernel.h" + +namespace WebCore { + +BiquadProcessor::BiquadProcessor(FilterType type, double sampleRate, size_t numberOfChannels, bool autoInitialize) + : AudioDSPKernelProcessor(sampleRate, numberOfChannels) + , m_type(type) + , m_parameter1(0) + , m_parameter2(0) + , m_parameter3(0) + , m_filterCoefficientsDirty(true) +{ + double nyquist = 0.5 * this->sampleRate(); + + switch (type) { + // Highpass and lowpass share the same parameters and only differ in filter type. + case LowPass2: + case HighPass2: + m_parameter1 = AudioParam::create("frequency", 350.0, 20.0, nyquist); + m_parameter2 = AudioParam::create("resonance", 0.0, -20.0, 20.0); + m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); + break; + + case Peaking: + m_parameter1 = AudioParam::create("frequency", 2500.0, 20.0, nyquist); + m_parameter2 = AudioParam::create("gain", 0.0, -20.0, 20.0); + m_parameter3 = AudioParam::create("Q", 0.5, 0.0, 1000.0); + break; + case Allpass: + m_parameter1 = AudioParam::create("frequency", 2500.0, 20.0, nyquist); + m_parameter2 = AudioParam::create("Q", 0.5, 0.0, 1000.0); + m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); + break; + case LowShelf: + m_parameter1 = AudioParam::create("frequency", 80.0, 20.0, nyquist); + m_parameter2 = AudioParam::create("gain", 0.0, 0.0, 1.0); + m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); + break; + case HighShelf: + m_parameter1 = AudioParam::create("frequency", 10000.0, 20.0, nyquist); + m_parameter2 = AudioParam::create("gain", 0.0, 0.0, 1.0); + m_parameter3 = AudioParam::create("unused", 0.0, 0.0, 1.0); + break; + } + + if (autoInitialize) + initialize(); +} + +BiquadProcessor::~BiquadProcessor() +{ + if (isInitialized()) + uninitialize(); +} + +PassOwnPtr<AudioDSPKernel> BiquadProcessor::createKernel() +{ + return adoptPtr(new BiquadDSPKernel(this)); +} + +void BiquadProcessor::process(AudioBus* source, AudioBus* destination, size_t framesToProcess) +{ + if (!isInitialized()) { + destination->zero(); + return; + } + + // Deal with smoothing / de-zippering. Start out assuming filter parameters are not changing. + // The BiquadDSPKernel objects rely on this value to see if they need to re-compute their internal filter coefficients. + m_filterCoefficientsDirty = false; + + if (m_hasJustReset) { + // Snap to exact values first time after reset, then smooth for subsequent changes. + m_parameter1->resetSmoothedValue(); + m_parameter2->resetSmoothedValue(); + m_parameter3->resetSmoothedValue(); + m_filterCoefficientsDirty = true; + m_hasJustReset = false; + } else { + // Smooth all of the filter parameters. If they haven't yet converged to their target value then mark coefficients as dirty. + bool isStable1 = m_parameter1->smooth(); + bool isStable2 = m_parameter2->smooth(); + bool isStable3 = m_parameter3->smooth(); + if (!(isStable1 && isStable2 && isStable3)) + m_filterCoefficientsDirty = true; + } + + // For each channel of our input, process using the corresponding BiquadDSPKernel into the output channel. + for (unsigned i = 0; i < m_kernels.size(); ++i) + m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->data(), framesToProcess); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/BiquadProcessor.h b/WebCore/webaudio/BiquadProcessor.h new file mode 100644 index 0000000..55dca33 --- /dev/null +++ b/WebCore/webaudio/BiquadProcessor.h @@ -0,0 +1,78 @@ +/* + * 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 BiquadProcessor_h +#define BiquadProcessor_h + +#include "AudioDSPKernel.h" +#include "AudioDSPKernelProcessor.h" +#include "AudioNode.h" +#include "AudioParam.h" +#include "Biquad.h" +#include <wtf/RefPtr.h> + +namespace WebCore { + +// BiquadProcessor is an AudioDSPKernelProcessor which uses Biquad objects to implement several common filters. + +class BiquadProcessor : public AudioDSPKernelProcessor { +public: + enum FilterType { + LowPass2, + HighPass2, + Peaking, + Allpass, + LowShelf, + HighShelf + }; + + BiquadProcessor(FilterType, double sampleRate, size_t numberOfChannels, bool autoInitialize = true); + virtual ~BiquadProcessor(); + + virtual PassOwnPtr<AudioDSPKernel> createKernel(); + + virtual void process(AudioBus* source, AudioBus* destination, size_t framesToProcess); + + bool filterCoefficientsDirty() const { return m_filterCoefficientsDirty; } + + AudioParam* parameter1() { return m_parameter1.get(); } + AudioParam* parameter2() { return m_parameter2.get(); } + AudioParam* parameter3() { return m_parameter3.get(); } + + FilterType type() const { return m_type; } + +private: + FilterType m_type; + + RefPtr<AudioParam> m_parameter1; + RefPtr<AudioParam> m_parameter2; + RefPtr<AudioParam> m_parameter3; + + // so DSP kernels know when to re-compute coefficients + bool m_filterCoefficientsDirty; +}; + +} // namespace WebCore + +#endif // BiquadProcessor_h diff --git a/WebCore/webaudio/DelayDSPKernel.cpp b/WebCore/webaudio/DelayDSPKernel.cpp new file mode 100644 index 0000000..9cb0450 --- /dev/null +++ b/WebCore/webaudio/DelayDSPKernel.cpp @@ -0,0 +1,140 @@ +/* + * 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 "DelayDSPKernel.h" + +#include "AudioUtilities.h" +#include <algorithm> + +using namespace std; + +const double DefaultMaxDelayTime = 1.0; +const double SmoothingTimeConstant = 0.020; // 20ms + +namespace WebCore { + +DelayDSPKernel::DelayDSPKernel(DelayProcessor* processor) + : AudioDSPKernel(processor) + , m_maxDelayTime(DefaultMaxDelayTime) + , m_writeIndex(0) + , m_firstTime(true) +{ + ASSERT(processor && processor->sampleRate() > 0); + if (!processor) + return; + + m_buffer.resize(static_cast<size_t>(processor->sampleRate() * DefaultMaxDelayTime)); + m_buffer.zero(); + + m_smoothingRate = AudioUtilities::discreteTimeConstantForSampleRate(SmoothingTimeConstant, processor->sampleRate()); +} + +DelayDSPKernel::DelayDSPKernel(double maxDelayTime, double sampleRate) + : AudioDSPKernel(sampleRate) + , m_maxDelayTime(maxDelayTime) + , m_writeIndex(0) + , m_firstTime(true) +{ + ASSERT(maxDelayTime > 0.0); + if (maxDelayTime <= 0.0) + return; + + size_t bufferLength = static_cast<size_t>(sampleRate * maxDelayTime); + ASSERT(bufferLength); + if (!bufferLength) + return; + + m_buffer.resize(bufferLength); + m_buffer.zero(); + + m_smoothingRate = AudioUtilities::discreteTimeConstantForSampleRate(SmoothingTimeConstant, sampleRate); +} + +void DelayDSPKernel::process(const float* source, float* destination, size_t framesToProcess) +{ + size_t bufferLength = m_buffer.size(); + float* buffer = m_buffer.data(); + + ASSERT(bufferLength); + if (!bufferLength) + return; + + ASSERT(source && destination); + if (!source || !destination) + return; + + double sampleRate = this->sampleRate(); + double delayTime = delayProcessor() ? delayProcessor()->delayTime()->value() : m_desiredDelayFrames / sampleRate; + + // Make sure the delay time is in a valid range. + delayTime = min(maxDelayTime(), delayTime); + delayTime = max(0.0, delayTime); + + if (m_firstTime) { + m_currentDelayTime = delayTime; + m_firstTime = false; + } + + int n = framesToProcess; + while (n--) { + // Approach desired delay time. + m_currentDelayTime += (delayTime - m_currentDelayTime) * m_smoothingRate; + + double desiredDelayFrames = m_currentDelayTime * sampleRate; + + double readPosition = m_writeIndex + bufferLength - desiredDelayFrames; + if (readPosition > bufferLength) + readPosition -= bufferLength; + + // Linearly interpolate in-between delay times. + int readIndex1 = static_cast<int>(readPosition); + int readIndex2 = (readIndex1 + 1) % bufferLength; + double interpolationFactor = readPosition - readIndex1; + + double input = static_cast<float>(*source++); + buffer[m_writeIndex] = static_cast<float>(input); + m_writeIndex = (m_writeIndex + 1) % bufferLength; + + double sample1 = buffer[readIndex1]; + double sample2 = buffer[readIndex2]; + + double output = (1.0 - interpolationFactor) * sample1 + interpolationFactor * sample2; + + *destination++ = static_cast<float>(output); + } +} + +void DelayDSPKernel::reset() +{ + m_firstTime = true; + m_buffer.zero(); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/DelayDSPKernel.h b/WebCore/webaudio/DelayDSPKernel.h new file mode 100644 index 0000000..2ae36cb --- /dev/null +++ b/WebCore/webaudio/DelayDSPKernel.h @@ -0,0 +1,62 @@ +/* + * 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 DelayDSPKernel_h +#define DelayDSPKernel_h + +#include "AudioArray.h" +#include "AudioDSPKernel.h" +#include "DelayProcessor.h" + +namespace WebCore { + +class DelayProcessor; + +class DelayDSPKernel : public AudioDSPKernel { +public: + DelayDSPKernel(DelayProcessor*); + DelayDSPKernel(double maxDelayTime, double sampleRate); + + virtual void process(const float* source, float* destination, size_t framesToProcess); + virtual void reset(); + + double maxDelayTime() const { return m_maxDelayTime; } + + void setDelayFrames(double numberOfFrames) { m_desiredDelayFrames = numberOfFrames; } + +private: + AudioFloatArray m_buffer; + double m_maxDelayTime; + int m_writeIndex; + double m_currentDelayTime; + double m_smoothingRate; + bool m_firstTime; + double m_desiredDelayFrames; + + DelayProcessor* delayProcessor() { return static_cast<DelayProcessor*>(processor()); } +}; + +} // namespace WebCore + +#endif // DelayDSPKernel_h diff --git a/WebCore/webaudio/HighPass2FilterNode.cpp b/WebCore/webaudio/HighPass2FilterNode.cpp new file mode 100644 index 0000000..ca33784 --- /dev/null +++ b/WebCore/webaudio/HighPass2FilterNode.cpp @@ -0,0 +1,42 @@ +/* + * 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 "HighPass2FilterNode.h" + +namespace WebCore { + +HighPass2FilterNode::HighPass2FilterNode(AudioContext* context, double sampleRate) + : AudioBasicProcessorNode(context, sampleRate) +{ + m_processor = adoptPtr(new BiquadProcessor(BiquadProcessor::HighPass2, sampleRate, 1, false)); + setType(NodeTypeHighPass2Filter); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/HighPass2FilterNode.h b/WebCore/webaudio/HighPass2FilterNode.h new file mode 100644 index 0000000..be0beb6 --- /dev/null +++ b/WebCore/webaudio/HighPass2FilterNode.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 HighPass2FilterNode_h +#define HighPass2FilterNode_h + +#include "AudioBasicProcessorNode.h" +#include "BiquadProcessor.h" + +namespace WebCore { + +class AudioParam; + +class HighPass2FilterNode : public AudioBasicProcessorNode { +public: + static PassRefPtr<HighPass2FilterNode> create(AudioContext* context, double sampleRate) + { + return adoptRef(new HighPass2FilterNode(context, sampleRate)); + } + + AudioParam* cutoff() { return biquadProcessor()->parameter1(); } + AudioParam* resonance() { return biquadProcessor()->parameter2(); } + +private: + HighPass2FilterNode(AudioContext*, double sampleRate); + + BiquadProcessor* biquadProcessor() { return static_cast<BiquadProcessor*>(processor()); } +}; + +} // namespace WebCore + +#endif // HighPass2FilterNode_h diff --git a/WebCore/webaudio/HighPass2FilterNode.idl b/WebCore/webaudio/HighPass2FilterNode.idl new file mode 100644 index 0000000..399f9b5 --- /dev/null +++ b/WebCore/webaudio/HighPass2FilterNode.idl @@ -0,0 +1,35 @@ +/* + * 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 { + // Two-pole highpass filter + // FIXME: design BiquadNode and use instead of this + interface [ + Conditional=WEB_AUDIO, + GenerateToJS + ] HighPass2FilterNode : AudioNode { + readonly attribute AudioParam cutoff; + readonly attribute AudioParam resonance; + }; +} diff --git a/WebCore/webaudio/LowPass2FilterNode.cpp b/WebCore/webaudio/LowPass2FilterNode.cpp new file mode 100644 index 0000000..691f4ed --- /dev/null +++ b/WebCore/webaudio/LowPass2FilterNode.cpp @@ -0,0 +1,42 @@ +/* + * 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 "LowPass2FilterNode.h" + +namespace WebCore { + +LowPass2FilterNode::LowPass2FilterNode(AudioContext* context, double sampleRate) + : AudioBasicProcessorNode(context, sampleRate) +{ + m_processor = adoptPtr(new BiquadProcessor(BiquadProcessor::LowPass2, sampleRate, 1, false)); + setType(NodeTypeLowPass2Filter); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_AUDIO) diff --git a/WebCore/webaudio/LowPass2FilterNode.h b/WebCore/webaudio/LowPass2FilterNode.h new file mode 100644 index 0000000..43d7051 --- /dev/null +++ b/WebCore/webaudio/LowPass2FilterNode.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 LowPass2FilterNode_h +#define LowPass2FilterNode_h + +#include "AudioBasicProcessorNode.h" +#include "BiquadProcessor.h" + +namespace WebCore { + +class AudioParam; + +class LowPass2FilterNode : public AudioBasicProcessorNode { +public: + static PassRefPtr<LowPass2FilterNode> create(AudioContext* context, double sampleRate) + { + return adoptRef(new LowPass2FilterNode(context, sampleRate)); + } + + AudioParam* cutoff() { return biquadProcessor()->parameter1(); } + AudioParam* resonance() { return biquadProcessor()->parameter2(); } + +private: + LowPass2FilterNode(AudioContext*, double sampleRate); + + BiquadProcessor* biquadProcessor() { return static_cast<BiquadProcessor*>(processor()); } +}; + +} // namespace WebCore + +#endif // LowPass2FilterNode_h diff --git a/WebCore/webaudio/LowPass2FilterNode.idl b/WebCore/webaudio/LowPass2FilterNode.idl new file mode 100644 index 0000000..310c21e --- /dev/null +++ b/WebCore/webaudio/LowPass2FilterNode.idl @@ -0,0 +1,35 @@ +/* + * 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 { + // Two-pole lowpass filter + // FIXME: design BiquadNode and use instead of this + interface [ + Conditional=WEB_AUDIO, + GenerateToJS + ] LowPass2FilterNode : AudioNode { + readonly attribute AudioParam cutoff; + readonly attribute AudioParam resonance; + }; +} |