summaryrefslogtreecommitdiffstats
path: root/WebCore/webaudio
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/webaudio')
-rw-r--r--WebCore/webaudio/AudioBasicProcessorNode.cpp146
-rw-r--r--WebCore/webaudio/AudioBasicProcessorNode.h68
-rw-r--r--WebCore/webaudio/AudioChannelMerger.cpp102
-rw-r--r--WebCore/webaudio/AudioChannelMerger.h56
-rw-r--r--WebCore/webaudio/AudioChannelMerger.idl34
-rw-r--r--WebCore/webaudio/AudioChannelSplitter.cpp88
-rw-r--r--WebCore/webaudio/AudioChannelSplitter.h56
-rw-r--r--WebCore/webaudio/AudioChannelSplitter.idl34
-rw-r--r--WebCore/webaudio/AudioContext.cpp46
-rw-r--r--WebCore/webaudio/AudioContext.h28
-rw-r--r--WebCore/webaudio/AudioContext.idl24
-rw-r--r--WebCore/webaudio/AudioGainNode.cpp116
-rw-r--r--WebCore/webaudio/AudioGainNode.h74
-rw-r--r--WebCore/webaudio/AudioGainNode.idl37
-rw-r--r--WebCore/webaudio/AudioNode.cpp10
-rw-r--r--WebCore/webaudio/AudioNode.h7
-rw-r--r--WebCore/webaudio/AudioPannerNode.cpp321
-rw-r--r--WebCore/webaudio/AudioPannerNode.h154
-rw-r--r--WebCore/webaudio/AudioPannerNode.idl64
-rw-r--r--WebCore/webaudio/BiquadDSPKernel.cpp77
-rw-r--r--WebCore/webaudio/BiquadDSPKernel.h56
-rw-r--r--WebCore/webaudio/BiquadProcessor.cpp125
-rw-r--r--WebCore/webaudio/BiquadProcessor.h78
-rw-r--r--WebCore/webaudio/DelayDSPKernel.cpp140
-rw-r--r--WebCore/webaudio/DelayDSPKernel.h62
-rw-r--r--WebCore/webaudio/HighPass2FilterNode.cpp42
-rw-r--r--WebCore/webaudio/HighPass2FilterNode.h53
-rw-r--r--WebCore/webaudio/HighPass2FilterNode.idl35
-rw-r--r--WebCore/webaudio/LowPass2FilterNode.cpp42
-rw-r--r--WebCore/webaudio/LowPass2FilterNode.h53
-rw-r--r--WebCore/webaudio/LowPass2FilterNode.idl35
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;
+ };
+}