2011-06-03 Chris Rogers <crogers@google.com>
authorcrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Jun 2011 23:03:04 +0000 (23:03 +0000)
committercrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Jun 2011 23:03:04 +0000 (23:03 +0000)
        Reviewed by Kenneth Russell.

        Allow existing AudioParams to use scheduled parameter changes
        https://bugs.webkit.org/show_bug.cgi?id=62046

        No new tests since audio API is not yet implemented.

        * platform/audio/AudioBus.cpp:
        (WebCore::AudioBus::processWithGainFrom):
        (WebCore::AudioBus::copyWithSampleAccurateGainValuesFrom):
        * platform/audio/AudioBus.h:
        * webaudio/AudioBufferSourceNode.cpp:
        (WebCore::AudioBufferSourceNode::AudioBufferSourceNode):
        * webaudio/AudioGainNode.cpp:
        (WebCore::AudioGainNode::AudioGainNode):
        (WebCore::AudioGainNode::process):
        * webaudio/AudioGainNode.h:
        * webaudio/HighPass2FilterNode.cpp:
        (WebCore::HighPass2FilterNode::HighPass2FilterNode):
        * webaudio/LowPass2FilterNode.cpp:
        (WebCore::LowPass2FilterNode::LowPass2FilterNode):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@88074 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/audio/AudioBus.cpp
Source/WebCore/platform/audio/AudioBus.h
Source/WebCore/webaudio/AudioBufferSourceNode.cpp
Source/WebCore/webaudio/AudioGainNode.cpp
Source/WebCore/webaudio/AudioGainNode.h
Source/WebCore/webaudio/HighPass2FilterNode.cpp
Source/WebCore/webaudio/LowPass2FilterNode.cpp

index 857ee4cbbaa66c3f018f3c2e0f68fd697266d93e..2e8fa687dbe427e3b23ea889b4ba3d7f2780ea51 100644 (file)
@@ -1,3 +1,27 @@
+2011-06-03  Chris Rogers  <crogers@google.com>
+
+        Reviewed by Kenneth Russell.
+
+        Allow existing AudioParams to use scheduled parameter changes
+        https://bugs.webkit.org/show_bug.cgi?id=62046
+
+        No new tests since audio API is not yet implemented.
+
+        * platform/audio/AudioBus.cpp:
+        (WebCore::AudioBus::processWithGainFrom):
+        (WebCore::AudioBus::copyWithSampleAccurateGainValuesFrom):
+        * platform/audio/AudioBus.h:
+        * webaudio/AudioBufferSourceNode.cpp:
+        (WebCore::AudioBufferSourceNode::AudioBufferSourceNode):
+        * webaudio/AudioGainNode.cpp:
+        (WebCore::AudioGainNode::AudioGainNode):
+        (WebCore::AudioGainNode::process):
+        * webaudio/AudioGainNode.h:
+        * webaudio/HighPass2FilterNode.cpp:
+        (WebCore::HighPass2FilterNode::HighPass2FilterNode):
+        * webaudio/LowPass2FilterNode.cpp:
+        (WebCore::LowPass2FilterNode::LowPass2FilterNode):
+
 2011-06-03  Chris Rogers  <crogers@google.com>
 
         Reviewed by Kenneth Russell.
index 36a5e633ea07291b54835e3b8712d77de28c6340..e34f7dbd5e70c25ccdc75311a8927533797b77eb 100644 (file)
@@ -336,8 +336,10 @@ void AudioBus::processWithGainFrom(const AudioBus &sourceBus, double* lastMixGai
 {
     // Make sure we're summing from same type of bus.
     // We *are* able to sum from mono -> stereo
-    if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus))
+    if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
+        ASSERT_NOT_REACHED();
         return;
+    }
 
     // Dispatch for different channel layouts
     switch (numberOfChannels()) {
@@ -353,6 +355,32 @@ void AudioBus::processWithGainFrom(const AudioBus &sourceBus, double* lastMixGai
     }
 }
 
+void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
+{
+    // Make sure we're processing from the same type of bus.
+    // We *are* able to process from mono -> stereo
+    if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    if (!gainValues || numberOfGainValues > sourceBus.length()) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    // FIXME: this can potentially use SIMD optimizations with vector libraries.
+    // We handle both the 1 -> N and N -> N case here.
+    const float* source = sourceBus.channel(0)->data();
+    for (unsigned channelIndex = 0; channelIndex < numberOfChannels(); ++channelIndex) {
+        if (sourceBus.numberOfChannels() == numberOfChannels())
+            source = sourceBus.channel(channelIndex)->data();
+        float* destination = channel(channelIndex)->data();
+        for (unsigned i = 0; i < numberOfGainValues; ++i)
+            destination[i] = source[i] * gainValues[i];
+    }
+}
+
 void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain)
 {
     processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
index 1943c0d164a46670ccc100b568db3bb5c14c7f46..a87f55d3132ec3a956e2e946fb64f1a045791e75 100644 (file)
@@ -124,6 +124,9 @@ public:
     void copyWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
     void sumWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain);
 
+    // Copies the sourceBus by scaling with sample-accurate gain values.
+    void copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues);
+
     // Returns maximum absolute value across all channels (useful for normalization).
     float maxAbsValue() const;
 
index fd1bda7a13cc1817839e9d543a0906b08482d8c9..2fab888e3a961cbc6b1d87caf35d77a21a3c2656 100644 (file)
@@ -66,6 +66,9 @@ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* context, double sampl
 
     m_gain = AudioGain::create("gain", 1.0, 0.0, 1.0);
     m_playbackRate = AudioParam::create("playbackRate", 1.0, 0.0, AudioResampler::MaxRate);
+    
+    m_gain->setContext(context);
+    m_playbackRate->setContext(context);
 
     // Default to mono.  A call to setBuffer() will set the number of output channels to that of the buffer.
     addOutput(adoptPtr(new AudioNodeOutput(this, 1)));
index 5b9af07ee405b1695e42dc4846cbd81bec1624f6..d5f130181b8ccc65c38992945725dbea552dd20f 100644 (file)
@@ -37,8 +37,10 @@ namespace WebCore {
 AudioGainNode::AudioGainNode(AudioContext* context, double sampleRate)
     : AudioNode(context, sampleRate)
     , m_lastGain(1.0)
+    , m_sampleAccurateGainValues(AudioNode::ProcessingSizeInFrames) // FIXME: can probably share temp buffer in context
 {
     m_gain = AudioGain::create("gain", 1.0, 0.0, 1.0);
+    m_gain->setContext(context);
 
     addInput(adoptPtr(new AudioNodeInput(this)));
     addOutput(adoptPtr(new AudioNodeOutput(this, 1)));
@@ -48,9 +50,9 @@ AudioGainNode::AudioGainNode(AudioContext* context, double sampleRate)
     initialize();
 }
 
-void AudioGainNode::process(size_t /*framesToProcess*/)
+void AudioGainNode::process(size_t framesToProcess)
 {
-    // FIXME: there is a nice optimization to avoid processing here, and let the gain change
+    // FIXME: for some cases 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:
 
@@ -64,8 +66,18 @@ void AudioGainNode::process(size_t /*framesToProcess*/)
         else {
             AudioBus* inputBus = input(0)->bus();
 
-            // Apply the gain with de-zippering into the output bus.
-            outputBus->copyWithGainFrom(*inputBus, &m_lastGain, gain()->value());
+            if (gain()->hasTimelineValues()) {
+                // Apply sample-accurate gain scaling for precise envelopes, grain windows, etc.
+                ASSERT(framesToProcess <= m_sampleAccurateGainValues.size());
+                if (framesToProcess <= m_sampleAccurateGainValues.size()) {
+                    float* gainValues = m_sampleAccurateGainValues.data();
+                    gain()->calculateSampleAccurateValues(gainValues, framesToProcess);
+                    outputBus->copyWithSampleAccurateGainValuesFrom(*inputBus, gainValues, framesToProcess);
+                }
+            } else {
+                // Apply the gain with de-zippering into the output bus.
+                outputBus->copyWithGainFrom(*inputBus, &m_lastGain, gain()->value());
+            }
         }
 
         m_processLock.unlock();
index 3710472f359c9e30cd4a13e793bdbbf2098fb212..a0d3c2b208aa8cef3717d53f062f47b3f520b87e 100644 (file)
@@ -60,6 +60,8 @@ private:
     double m_lastGain; // for de-zippering
     RefPtr<AudioGain> m_gain;
 
+    AudioFloatArray m_sampleAccurateGainValues;
+    
     // 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;
index ca33784d6248547f6e903dbfebd143fc760b59e1..12d58a8edf804f83f61bd4739c30ab50e2a3a709 100644 (file)
@@ -34,6 +34,9 @@ HighPass2FilterNode::HighPass2FilterNode(AudioContext* context, double sampleRat
     : AudioBasicProcessorNode(context, sampleRate)
 {
     m_processor = adoptPtr(new BiquadProcessor(BiquadProcessor::HighPass2, sampleRate, 1, false));
+    biquadProcessor()->parameter1()->setContext(context);
+    biquadProcessor()->parameter2()->setContext(context);
+    biquadProcessor()->parameter3()->setContext(context);
     setType(NodeTypeHighPass2Filter);
 }
 
index 691f4ed73ff2b1ad6431b15113f1d0fa5d4f0c7b..8e627634daffaa5b2d5d73f409c90bddab12068e 100644 (file)
@@ -34,6 +34,9 @@ LowPass2FilterNode::LowPass2FilterNode(AudioContext* context, double sampleRate)
     : AudioBasicProcessorNode(context, sampleRate)
 {
     m_processor = adoptPtr(new BiquadProcessor(BiquadProcessor::LowPass2, sampleRate, 1, false));
+    biquadProcessor()->parameter1()->setContext(context);
+    biquadProcessor()->parameter2()->setContext(context);
+    biquadProcessor()->parameter3()->setContext(context);
     setType(NodeTypeLowPass2Filter);
 }