Title: [113728] trunk/Source/WebCore
Revision
113728
Author
jer.no...@apple.com
Date
2012-04-10 10:04:41 -0700 (Tue, 10 Apr 2012)

Log Message

WebAudio: propagate a silence hint through the AudioNode graph.
https://bugs.webkit.org/show_bug.cgi?id=74553

Reviewed by Chris Rogers.

No new tests; optimization of existing code path, so covered by existing tests.

Introduce the concept of a "silent" channel:
* platform/audio/AudioChannel.h:
(WebCore::AudioChannel::AudioChannel):
(WebCore::AudioChannel::set): Clear silent bit.
(WebCore::AudioChannel::zero): Set silent bit.
(WebCore::AudioChannel::clearSilentFlag): Clear silent bit.
(WebCore::AudioChannel::isSilent): Accessor.

Optimize a few channel operations when the source or destination channels are silent.
* platform/audio/AudioChannel.cpp:
(WebCore::AudioChannel::scale): No-op on a silent channel.
(WebCore::AudioChannel::copyFrom): zero() when source is silent.
(WebCore::AudioChannel::copyFromRange): possibly zero() when source is silent.
(WebCore::AudioChannel::sumFrom): No-op when source is silent.
(WebCore::AudioChannel::maxAbsValue): 0 on a silent channel.

Optimize a few bus operations when the source or destination channels are silent.
* platform/audio/AudioBus.cpp:
(WebCore::AudioBus::processWithGainFromMonoStereo): No-op if source is silent and either
    the destination bus is silent, or the output is not summed to the destination.
(WebCore::AudioBus::copyWithSampleAccurateGainValuesFrom): zero() if the source is silent
    and the lengths of the gain values, source, and destination match.
(WebCore::AudioBus::createBySampleRateConverting): Return an empty bus if the source is silent.
(WebCore::AudioBus::createByMixingToMono): Ditto; clear the destination's silent bit otherwise.
(WebCore::AudioBus::isSilent): Return whether all channels are silent.
(WebCore::AudioBus::clearSilentFlag): Clear silent bit of constituent channels.
* platform/audio/AudioBus.h:

Make sure that classes which generate audio clear their busses' silent bit.
* webaudio/AudioBufferSourceNode.cpp:
(WebCore::AudioBufferSourceNode::process): Ditto.
(WebCore::AudioBufferSourceNode::renderFromBuffer): Ditto.
(WebCore::AudioBufferSourceNode::propagatesSilence): Propagate silence only when the source node
    has nothing left to render.
* webaudio/AudioBufferSourceNode.h:
(WebCore::AudioBufferSourceNode::playbackState): Made const correct.
(WebCore::AudioBufferSourceNode::isPlaying): Added simple accessor.
(WebCore::AudioBufferSourceNode::hasFinished): Ditto.
* webaudio/AudioDestinationNode.h:
(WebCore::AudioDestinationNode::currentSampleFrame): Made const correct.
(WebCore::AudioDestinationNode::currentTime): Ditto.

Audio nodes should not process audio data when the input is silent and the nodes will propagate silences.
* webaudio/AudioNode.cpp:
(WebCore::AudioNode::processIfNecessary):
(WebCore::AudioNode::inputsAreSilent): Convenience function which walk over the node's inputs.
(WebCore::AudioNode::silenceOutputs): Ditto.
(WebCore::AudioNode::unsilenceOutputs): Ditto.
* webaudio/AudioNode.h:
(WebCore::AudioNode::propagatesSilence):

These Nodes can generate audio when given silent input, so return false from propagatesSilence.
* Modules/webaudio/Oscillator.h:
(WebCore::Oscillator::propagatesSilence): Added.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (113727 => 113728)


--- trunk/Source/WebCore/ChangeLog	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/ChangeLog	2012-04-10 17:04:41 UTC (rev 113728)
@@ -1,3 +1,67 @@
+2011-12-14  Jer Noble  <jer.no...@apple.com>
+
+        WebAudio: propagate a silence hint through the AudioNode graph.
+        https://bugs.webkit.org/show_bug.cgi?id=74553
+
+        Reviewed by Chris Rogers.
+
+        No new tests; optimization of existing code path, so covered by existing tests.
+
+        Introduce the concept of a "silent" channel:
+        * platform/audio/AudioChannel.h:
+        (WebCore::AudioChannel::AudioChannel):
+        (WebCore::AudioChannel::set): Clear silent bit.
+        (WebCore::AudioChannel::zero): Set silent bit.
+        (WebCore::AudioChannel::clearSilentFlag): Clear silent bit.
+        (WebCore::AudioChannel::isSilent): Accessor.
+
+        Optimize a few channel operations when the source or destination channels are silent.
+        * platform/audio/AudioChannel.cpp:
+        (WebCore::AudioChannel::scale): No-op on a silent channel.
+        (WebCore::AudioChannel::copyFrom): zero() when source is silent.
+        (WebCore::AudioChannel::copyFromRange): possibly zero() when source is silent.
+        (WebCore::AudioChannel::sumFrom): No-op when source is silent.
+        (WebCore::AudioChannel::maxAbsValue): 0 on a silent channel.
+
+        Optimize a few bus operations when the source or destination channels are silent.
+        * platform/audio/AudioBus.cpp:
+        (WebCore::AudioBus::processWithGainFromMonoStereo): No-op if source is silent and either
+            the destination bus is silent, or the output is not summed to the destination.
+        (WebCore::AudioBus::copyWithSampleAccurateGainValuesFrom): zero() if the source is silent
+            and the lengths of the gain values, source, and destination match.
+        (WebCore::AudioBus::createBySampleRateConverting): Return an empty bus if the source is silent.
+        (WebCore::AudioBus::createByMixingToMono): Ditto; clear the destination's silent bit otherwise.
+        (WebCore::AudioBus::isSilent): Return whether all channels are silent.
+        (WebCore::AudioBus::clearSilentFlag): Clear silent bit of constituent channels.
+        * platform/audio/AudioBus.h:
+
+        Make sure that classes which generate audio clear their busses' silent bit.
+        * webaudio/AudioBufferSourceNode.cpp:
+        (WebCore::AudioBufferSourceNode::process): Ditto.
+        (WebCore::AudioBufferSourceNode::renderFromBuffer): Ditto.
+        (WebCore::AudioBufferSourceNode::propagatesSilence): Propagate silence only when the source node
+            has nothing left to render.
+        * webaudio/AudioBufferSourceNode.h:
+        (WebCore::AudioBufferSourceNode::playbackState): Made const correct.
+        (WebCore::AudioBufferSourceNode::isPlaying): Added simple accessor.
+        (WebCore::AudioBufferSourceNode::hasFinished): Ditto.
+        * webaudio/AudioDestinationNode.h:
+        (WebCore::AudioDestinationNode::currentSampleFrame): Made const correct.
+        (WebCore::AudioDestinationNode::currentTime): Ditto.
+
+        Audio nodes should not process audio data when the input is silent and the nodes will propagate silences.
+        * webaudio/AudioNode.cpp:
+        (WebCore::AudioNode::processIfNecessary): 
+        (WebCore::AudioNode::inputsAreSilent): Convenience function which walk over the node's inputs.
+        (WebCore::AudioNode::silenceOutputs): Ditto.
+        (WebCore::AudioNode::unsilenceOutputs): Ditto.
+        * webaudio/AudioNode.h:
+        (WebCore::AudioNode::propagatesSilence):
+
+        These Nodes can generate audio when given silent input, so return false from propagatesSilence.
+        * Modules/webaudio/Oscillator.h:
+        (WebCore::Oscillator::propagatesSilence): Added.
+
 2012-04-10  Yi Shen  <yi.4.s...@nokia.com>
 
         Pressing enter on blank line after bullet deletes entire bulleted line.

Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp (113727 => 113728)


--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp	2012-04-10 17:04:41 UTC (rev 113728)
@@ -158,6 +158,10 @@
 
             finish();
         }
+
+        outputBus->clearSilentFlag();
+
+        m_processLock.unlock();
     } else {
         // Too bad - the tryLock() failed.  We must be in the middle of changing buffers and were already outputting silence anyway.
         outputBus->zero();
@@ -331,7 +335,10 @@
                     break;
             }
         }
-    } 
+    }
+
+    bus->clearSilentFlag();
+
     m_virtualReadIndex = virtualReadIndex;
 }
 
@@ -499,6 +506,12 @@
 
     m_isLooping = looping;
 }
+
+bool AudioBufferSourceNode::propagatesSilence() const
+{
+    return !isPlayingOrScheduled() || hasFinished() || !m_buffer;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(WEB_AUDIO)

Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h (113727 => 113728)


--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h	2012-04-10 17:04:41 UTC (rev 113728)
@@ -84,7 +84,9 @@
     void noteGrainOn(double when, double grainOffset, double grainDuration);
     void noteOff(double when);
 
-    unsigned short playbackState() { return static_cast<unsigned short>(m_playbackState); }
+    unsigned short playbackState() const { return static_cast<unsigned short>(m_playbackState); }
+    bool isPlayingOrScheduled() const { return m_playbackState == PLAYING_STATE || m_playbackState == SCHEDULED_STATE; }
+    bool hasFinished() const { return m_playbackState == FINISHED_STATE; }
 
     // Note: the attribute was originally exposed as .looping, but to be more consistent in naming with <audio>
     // and with how it's described in the specification, the proper attribute name is .loop
@@ -102,6 +104,9 @@
     // If a panner node is set, then we can incorporate doppler shift into the playback pitch rate.
     void setPannerNode(PassRefPtr<AudioPannerNode> pannerNode) { m_pannerNode = pannerNode; }
 
+    // If we are no longer playing, propogate silence ahead to downstream nodes.
+    virtual bool propagatesSilence() const;
+
 private:
     AudioBufferSourceNode(AudioContext*, float sampleRate);
 

Modified: trunk/Source/WebCore/Modules/webaudio/AudioContext.h (113727 => 113728)


--- trunk/Source/WebCore/Modules/webaudio/AudioContext.h	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/Modules/webaudio/AudioContext.h	2012-04-10 17:04:41 UTC (rev 113728)
@@ -93,10 +93,10 @@
     bool hasDocument();
 
     AudioDestinationNode* destination() { return m_destinationNode.get(); }
-    size_t currentSampleFrame() { return m_destinationNode->currentSampleFrame(); }
-    double currentTime() { return m_destinationNode->currentTime(); }
-    float sampleRate() { return m_destinationNode->sampleRate(); }
-    unsigned long activeSourceCount() { return static_cast<unsigned long>(m_activeSourceCount); }
+    size_t currentSampleFrame() const { return m_destinationNode->currentSampleFrame(); }
+    double currentTime() const { return m_destinationNode->currentTime(); }
+    float sampleRate() const { return m_destinationNode->sampleRate(); }
+    unsigned long activeSourceCount() const { return static_cast<unsigned long>(m_activeSourceCount); }
 
     void incrementActiveSourceCount();
     void decrementActiveSourceCount();

Modified: trunk/Source/WebCore/Modules/webaudio/AudioDestinationNode.h (113727 => 113728)


--- trunk/Source/WebCore/Modules/webaudio/AudioDestinationNode.h	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/Modules/webaudio/AudioDestinationNode.h	2012-04-10 17:04:41 UTC (rev 113728)
@@ -46,8 +46,8 @@
     // The audio hardware calls here periodically to gets its input stream.
     virtual void provideInput(AudioBus*, size_t numberOfFrames);
 
-    size_t currentSampleFrame() { return m_currentSampleFrame; }
-    double currentTime() { return currentSampleFrame() / static_cast<double>(sampleRate()); }
+    size_t currentSampleFrame() const { return m_currentSampleFrame; }
+    double currentTime() const { return currentSampleFrame() / static_cast<double>(sampleRate()); }
 
     virtual unsigned numberOfChannels() const { return 2; } // FIXME: update when multi-channel (more than stereo) is supported
 

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp (113727 => 113728)


--- trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp	2012-04-10 17:04:41 UTC (rev 113728)
@@ -42,7 +42,8 @@
     , m_nodeType(NodeTypeUnknown)
     , m_context(context)
     , m_sampleRate(sampleRate)
-    , m_lastProcessingTime(-1.0)
+    , m_lastProcessingTime(-1)
+    , m_lastNonSilentTime(-1)
     , m_normalRefCount(1) // start out with normal refCount == 1 (like WTF::RefCounted class)
     , m_connectionRefCount(0)
     , m_disabledRefCount(0)
@@ -177,8 +178,19 @@
     double currentTime = context()->currentTime();
     if (m_lastProcessingTime != currentTime) {
         m_lastProcessingTime = currentTime; // important to first update this time because of feedback loops in the rendering graph
+
         pullInputs(framesToProcess);
-        process(framesToProcess);
+
+        bool silentInputs = inputsAreSilent();
+        if (!silentInputs)
+            m_lastNonSilentTime = (context()->currentSampleFrame() + framesToProcess) / static_cast<double>(m_sampleRate);
+
+        if (silentInputs && propagatesSilence())
+            silenceOutputs();
+        else {
+            process(framesToProcess);
+            unsilenceOutputs();
+        }
     }
 }
 
@@ -193,6 +205,11 @@
     input->updateInternalBus();
 }
 
+bool AudioNode::propagatesSilence() const
+{
+    return m_lastNonSilentTime + latencyTime() + tailTime() < context()->currentTime();
+}
+
 void AudioNode::pullInputs(size_t framesToProcess)
 {
     ASSERT(context()->isAudioThread());
@@ -202,6 +219,27 @@
         input(i)->pull(0, framesToProcess);
 }
 
+bool AudioNode::inputsAreSilent()
+{
+    for (unsigned i = 0; i < m_inputs.size(); ++i) {
+        if (!input(i)->bus()->isSilent())
+            return false;
+    }
+    return true;
+}
+
+void AudioNode::silenceOutputs()
+{
+    for (unsigned i = 0; i < m_outputs.size(); ++i)
+        output(i)->bus()->zero();
+}
+
+void AudioNode::unsilenceOutputs()
+{
+    for (unsigned i = 0; i < m_outputs.size(); ++i)
+        output(i)->bus()->clearSilentFlag();
+}
+
 void AudioNode::ref(RefType refType)
 {
     switch (refType) {

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNode.h (113727 => 113728)


--- trunk/Source/WebCore/Modules/webaudio/AudioNode.h	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNode.h	2012-04-10 17:04:41 UTC (rev 113728)
@@ -54,6 +54,7 @@
     virtual ~AudioNode();
 
     AudioContext* context() { return m_context.get(); }
+    const AudioContext* context() const { return m_context.get(); }
 
     enum NodeType {
         NodeTypeUnknown,
@@ -143,6 +144,13 @@
     // example, a "delay" effect is expected to delay the signal, and thus would not be considered latency.
     virtual double latencyTime() const = 0;
 
+    // propagatesSilence() should return true if the node will generate silent output when given silent input. By default, AudioNode
+    // will take tailTime() and latencyTime() into account when determining whether the node will propagate silence.
+    virtual bool propagatesSilence() const;
+    bool inputsAreSilent();
+    void silenceOutputs();
+    void unsilenceOutputs();
+
 protected:
     // Inputs and outputs must be created before the AudioNode is initialized.
     void addInput(PassOwnPtr<AudioNodeInput>);
@@ -162,6 +170,7 @@
     Vector<OwnPtr<AudioNodeOutput> > m_outputs;
 
     double m_lastProcessingTime;
+    double m_lastNonSilentTime;
 
     // Ref-counting
     volatile int m_normalRefCount;

Modified: trunk/Source/WebCore/Modules/webaudio/Oscillator.h (113727 => 113728)


--- trunk/Source/WebCore/Modules/webaudio/Oscillator.h	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/Modules/webaudio/Oscillator.h	2012-04-10 17:04:41 UTC (rev 113728)
@@ -74,6 +74,9 @@
     // Returns true if there are sample-accurate timeline parameter changes.
     bool calculateSampleAccuratePhaseIncrements(size_t framesToProcess);
 
+    // As a pure generator, Oscillator will never propagate silence.
+    virtual bool propagatesSilence() const OVERRIDE { return false; }
+
     // One of the waveform types defined in the enum.
     unsigned short m_type;
     

Modified: trunk/Source/WebCore/platform/audio/AudioBus.cpp (113727 => 113728)


--- trunk/Source/WebCore/platform/audio/AudioBus.cpp	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/platform/audio/AudioBus.cpp	2012-04-10 17:04:41 UTC (rev 113728)
@@ -424,6 +424,12 @@
     const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
     const float* sourceR = numberOfSourceChannels > 1 ? sourceBusSafe.channelByType(ChannelRight)->data() : 0;
 
+    if (sourceBusSafe.isSilent()) {
+        if (!sumToBus)
+            zero();
+        return;
+    }
+
     float* destinationL = channelByType(ChannelLeft)->mutableData();
     float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->mutableData() : 0;
 
@@ -510,6 +516,11 @@
         return;
     }
 
+    if (sourceBus.length() == numberOfGainValues && sourceBus.length() == length() && sourceBus.isSilent()) {
+        zero();
+        return;
+    }
+
     // 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) {
@@ -539,6 +550,7 @@
 
     double sourceSampleRate = sourceBus->sampleRate();
     double destinationSampleRate = newSampleRate;
+    double sampleRateRatio = sourceSampleRate / destinationSampleRate;
     unsigned numberOfSourceChannels = sourceBus->numberOfChannels();
 
     if (numberOfSourceChannels == 1)
@@ -552,7 +564,13 @@
         // Return exact copy.
         return AudioBus::createBufferFromRange(sourceBus, 0, sourceBus->length());
     }
-    
+
+    if (sourceBus->isSilent()) {
+        OwnPtr<AudioBus> silentBus = adoptPtr(new AudioBus(numberOfSourceChannels, sourceBus->length() / sampleRateRatio));
+        silentBus->setSampleRate(newSampleRate);
+        return silentBus.release();
+    }
+
     // First, mix to mono (if necessary) then sample-rate convert.
     const AudioBus* resamplerSourceBus;
     OwnPtr<AudioBus> mixedMonoBus;
@@ -565,7 +583,6 @@
     }
 
     // Calculate destination length based on the sample-rates.
-    double sampleRateRatio = sourceSampleRate / destinationSampleRate;
     int sourceLength = resamplerSourceBus->length();
     int destinationLength = sourceLength / sampleRateRatio;
 
@@ -582,12 +599,16 @@
         resampler.process(source, destination, sourceLength);
     }
 
+    destinationBus->clearSilentFlag();
     destinationBus->setSampleRate(newSampleRate);    
     return destinationBus.release();
 }
 
 PassOwnPtr<AudioBus> AudioBus::createByMixingToMono(const AudioBus* sourceBus)
 {
+    if (sourceBus->isSilent())
+        return adoptPtr(new AudioBus(1, sourceBus->length()));
+
     switch (sourceBus->numberOfChannels()) {
     case 1:
         // Simply create an exact copy.
@@ -605,6 +626,7 @@
             for (unsigned i = 0; i < n; ++i)
                 destination[i] = (sourceL[i] + sourceR[i]) / 2;
 
+            destinationBus->clearSilentFlag();
             destinationBus->setSampleRate(sourceBus->sampleRate());    
             return destinationBus.release();
         }
@@ -614,6 +636,21 @@
     return nullptr;
 }
 
+bool AudioBus::isSilent() const
+{
+    for (size_t i = 0; i < m_channels.size(); ++i) {
+        if (!m_channels[i]->isSilent())
+            return false;
+    }
+    return true;
+}
+
+void AudioBus::clearSilentFlag()
+{
+    for (size_t i = 0; i < m_channels.size(); ++i)
+        m_channels[i]->clearSilentFlag();
+}
+
 } // WebCore
 
 #endif // ENABLE(WEB_AUDIO)

Modified: trunk/Source/WebCore/platform/audio/AudioBus.h (113727 => 113728)


--- trunk/Source/WebCore/platform/audio/AudioBus.h	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/platform/audio/AudioBus.h	2012-04-10 17:04:41 UTC (rev 113728)
@@ -83,6 +83,12 @@
     // Zeroes all channels.
     void zero();
 
+    // Clears the silent flag on all channels.
+    void clearSilentFlag();
+
+    // Returns true if the silent bit is set on all channels.
+    bool isSilent() const;
+
     // Returns true if the channel count and frame-size match.
     bool topologyMatches(const AudioBus &sourceBus) const;
 

Modified: trunk/Source/WebCore/platform/audio/AudioChannel.cpp (113727 => 113728)


--- trunk/Source/WebCore/platform/audio/AudioChannel.cpp	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/platform/audio/AudioChannel.cpp	2012-04-10 17:04:41 UTC (rev 113728)
@@ -43,6 +43,9 @@
 
 void AudioChannel::scale(float scale)
 {
+    if (isSilent())
+        return;
+
     vsmul(data(), 1, &scale, mutableData(), 1, length());
 }
 
@@ -53,11 +56,18 @@
     if (!isSafe)
         return;
 
+    if (sourceChannel->isSilent()) {
+        zero();
+        return;
+    }
     memcpy(mutableData(), sourceChannel->data(), sizeof(float) * length());
 }
 
 void AudioChannel::copyFromRange(const AudioChannel* sourceChannel, unsigned startFrame, unsigned endFrame)
 {
+    if (sourceChannel->isSilent() && isSilent())
+        return;
+
     // Check that range is safe for reading from sourceChannel.
     bool isRangeSafe = sourceChannel && startFrame < endFrame && endFrame <= sourceChannel->length();
     ASSERT(isRangeSafe);
@@ -73,23 +83,39 @@
 
     const float* source = sourceChannel->data();
     float* destination = mutableData();
-    memcpy(destination, source + startFrame, sizeof(float) * rangeLength);
+
+    if (sourceChannel->isSilent()) {
+        if (rangeLength == length())
+            zero();
+        else
+            memset(destination, 0, sizeof(float) * rangeLength);
+    } else
+        memcpy(destination, source + startFrame, sizeof(float) * rangeLength);
 }
 
 void AudioChannel::sumFrom(const AudioChannel* sourceChannel)
 {
+    if (sourceChannel->isSilent())
+        return;
+
     bool isSafe = sourceChannel && sourceChannel->length() >= length();
     ASSERT(isSafe);
     if (!isSafe)
         return;
 
-    vadd(data(), 1, sourceChannel->data(), 1, mutableData(), 1, length());
+    if (isSilent())
+        copyFrom(sourceChannel);
+    else
+        vadd(data(), 1, sourceChannel->data(), 1, mutableData(), 1, length());
 }
 
 float AudioChannel::maxAbsValue() const
 {
-    float max = 0.0f;
+    if (isSilent())
+        return 0;
 
+    float max = 0;
+
     vmaxmgv(data(), 1, &max, length());
 
     return max;

Modified: trunk/Source/WebCore/platform/audio/AudioChannel.h (113727 => 113728)


--- trunk/Source/WebCore/platform/audio/AudioChannel.h	2012-04-10 16:40:46 UTC (rev 113727)
+++ trunk/Source/WebCore/platform/audio/AudioChannel.h	2012-04-10 17:04:41 UTC (rev 113728)
@@ -43,12 +43,17 @@
 
     // Reference an external buffer.
     AudioChannel(float* storage, size_t length)
-        : m_length(length), m_rawPointer(storage) { }
+        : m_length(length)
+        , m_rawPointer(storage)
+        , m_silent(false)
+    {
+    }
 
     // Manage storage for us.
     explicit AudioChannel(size_t length)
         : m_length(length)
         , m_rawPointer(0)
+        , m_silent(true)
     {
         m_memBuffer = adoptPtr(new AudioFloatArray(length));
     }
@@ -57,6 +62,7 @@
     AudioChannel()
         : m_length(0)
         , m_rawPointer(0)
+        , m_silent(true)
     {
     }
 
@@ -67,24 +73,40 @@
         m_memBuffer.clear(); // cleanup managed storage
         m_rawPointer = storage;
         m_length = length;
+        m_silent = false;
     }
 
     // How many sample-frames do we contain?
     size_t length() const { return m_length; }
 
-    // Direct access to PCM sample data
-    float* mutableData() { return m_rawPointer ? m_rawPointer : m_memBuffer->data(); }
+    // Direct access to PCM sample data. Non-const accessor clears silent flag.
+    float* mutableData()
+    {
+        clearSilentFlag();
+        return m_rawPointer ? m_rawPointer : m_memBuffer->data(); 
+    }
+
     const float* data() const { return m_rawPointer ? m_rawPointer : m_memBuffer->data(); }
 
     // Zeroes out all sample values in buffer.
     void zero()
     {
+        if (m_silent)
+            return;
+
+        m_silent = true;
+
         if (m_memBuffer.get())
             m_memBuffer->zero();
         else
             memset(m_rawPointer, 0, sizeof(float) * m_length);
     }
 
+    // Clears the silent flag.
+    void clearSilentFlag() { m_silent = false; }
+
+    bool isSilent() const { return m_silent; }
+
     // Scales all samples by the same amount.
     void scale(float scale);
 
@@ -105,6 +127,7 @@
 
     float* m_rawPointer;
     OwnPtr<AudioFloatArray> m_memBuffer;
+    bool m_silent;
 };
 
 } // WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to