Title: [116596] trunk/Source/WebCore
Revision
116596
Author
[email protected]
Date
2012-05-09 19:32:46 -0700 (Wed, 09 May 2012)

Log Message

Add multi-channels support for CopyWithGainFrom in AudioBus
https://bugs.webkit.org/show_bug.cgi?id=80675

Patch by Raymond Liu <[email protected]> on 2012-05-09
Reviewed by Chris Rogers.

* platform/audio/AudioBus.cpp:
(WebCore):
(WebCore::AudioBus::AudioBus):
(WebCore::AudioBus::copyWithGainFrom):
* platform/audio/AudioBus.h:
(AudioBus):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (116595 => 116596)


--- trunk/Source/WebCore/ChangeLog	2012-05-10 02:00:38 UTC (rev 116595)
+++ trunk/Source/WebCore/ChangeLog	2012-05-10 02:32:46 UTC (rev 116596)
@@ -1,3 +1,17 @@
+2012-05-09  Raymond Liu  <[email protected]>
+
+        Add multi-channels support for CopyWithGainFrom in AudioBus
+        https://bugs.webkit.org/show_bug.cgi?id=80675
+
+        Reviewed by Chris Rogers.
+
+        * platform/audio/AudioBus.cpp:
+        (WebCore):
+        (WebCore::AudioBus::AudioBus):
+        (WebCore::AudioBus::copyWithGainFrom):
+        * platform/audio/AudioBus.h:
+        (AudioBus):
+
 2012-05-09  Jessie Berlin  <[email protected]>
 
         Crash using the new WKBundleDOMWindowExtensions APIs.

Modified: trunk/Source/WebCore/platform/audio/AudioBus.cpp (116595 => 116596)


--- trunk/Source/WebCore/platform/audio/AudioBus.cpp	2012-05-10 02:00:38 UTC (rev 116595)
+++ trunk/Source/WebCore/platform/audio/AudioBus.cpp	2012-05-10 02:32:46 UTC (rev 116596)
@@ -45,13 +45,19 @@
 namespace WebCore {
 
 using namespace VectorMath;
-    
+
+const unsigned MaxBusChannels = 32;
+
 AudioBus::AudioBus(unsigned numberOfChannels, size_t length, bool allocate)
     : m_length(length)
     , m_busGain(1)
     , m_isFirstTime(true)
     , m_sampleRate(0)
 {
+    ASSERT(numberOfChannels <= MaxBusChannels);
+    if (numberOfChannels > MaxBusChannels)
+        return;
+
     m_channels.reserveInitialCapacity(numberOfChannels);
 
     for (unsigned i = 0; i < numberOfChannels; ++i) {
@@ -307,106 +313,37 @@
     }
 }
 
-// Slowly change gain to desired gain.
-#define GAIN_DEZIPPER \
-    gain += (totalDesiredGain - gain) * DezipperRate; \
-    gain = DenormalDisabler::flushDenormalFloatToZero(gain);
-
-// De-zipper for the first framesToDezipper frames and skip de-zippering for the remaining frames
-// because the gain is close enough to the target gain.
-#define PROCESS_WITH_GAIN(OP) \
-    for (k = 0; k < framesToDezipper; ++k) { \
-        OP \
-        GAIN_DEZIPPER \
-    } \
-    if (!framesToDezipper) \
-        gain = totalDesiredGain; \
-    OP##_V 
-
-#define STEREO_SUM \
-    { \
-        float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
-        float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + gain * *sourceR++); \
-        *destinationL++ = sumL; \
-        *destinationR++ = sumR; \
+void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
+{
+    if (!topologyMatches(sourceBus)) {
+        ASSERT_NOT_REACHED();
+        zero();
+        return;
     }
 
-#define STEREO_SUM_V \
-    { \
-        vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
-        vsma(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
+    if (sourceBus.isSilent()) {
+        zero();
+        return;
     }
 
-// Mono -> stereo (mix equally into L and R)
-// FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
-#define MONO2STEREO_SUM \
-    { \
-        float scaled = gain * *sourceL++; \
-        float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + scaled); \
-        float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + scaled); \
-        *destinationL++ = sumL; \
-        *destinationR++ = sumR; \
-    }
+    unsigned numberOfChannels = this->numberOfChannels();
+    ASSERT(numberOfChannels <= MaxBusChannels);
+    if (numberOfChannels > MaxBusChannels)
+        return;
 
-#define MONO2STEREO_SUM_V \
-    { \
-        vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
-        vsma(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
-    }
-    
-#define MONO_SUM \
-    { \
-        float sum = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
-        *destinationL++ = sum; \
-    }
+    // If it is copying from the same bus and no need to change gain, just return.
+    if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1)
+        return;
 
-#define MONO_SUM_V \
-    { \
-        vsma(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
-    } 
+    AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
+    const float* sources[MaxBusChannels];
+    float* destinations[MaxBusChannels];
 
-#define STEREO_NO_SUM \
-    { \
-        float sampleL = *sourceL++; \
-        float sampleR = *sourceR++; \
-        *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
-        *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleR); \
+    for (unsigned i = 0; i < numberOfChannels; ++i) {
+        sources[i] = sourceBusSafe.channel(i)->data();
+        destinations[i] = channel(i)->mutableData();
     }
 
-#define STEREO_NO_SUM_V \
-    { \
-        vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
-        vsmul(sourceR, 1, &gain, destinationR, 1, framesToProcess - k); \
-    }
-
-// Mono -> stereo (mix equally into L and R)
-// FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center...
-#define MONO2STEREO_NO_SUM \
-    { \
-        float sample = *sourceL++; \
-        *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \
-        *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample); \
-    }
-
-#define MONO2STEREO_NO_SUM_V \
-    { \
-        vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
-        vsmul(sourceL, 1, &gain, destinationR, 1, framesToProcess - k); \
-    }
-
-#define MONO_NO_SUM \
-    { \
-        float sampleL = *sourceL++; \
-        *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
-    }
-
-#define MONO_NO_SUM_V \
-    { \
-        vsmul(sourceL, 1, &gain, destinationL, 1, framesToProcess - k); \
-    } 
-
-void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
-{
     // We don't want to suddenly change the gain from mixing one time slice to the next,
     // so we "de-zipper" by slowly changing the gain each sample-frame until we've achieved the target gain.
     
@@ -417,24 +354,8 @@
     float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain);
     m_isFirstTime = false;
 
-    int numberOfSourceChannels = sourceBus.numberOfChannels();
-    int numberOfDestinationChannels = numberOfChannels();
-
-    AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
-    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;
-
     const float DezipperRate = 0.005f;
-    int framesToProcess = length();
+    unsigned framesToProcess = length();
 
     // If the gain is within epsilon of totalDesiredGain, we can skip dezippering. 
     // FIXME: this value may need tweaking.
@@ -442,66 +363,41 @@
     float gainDiff = fabs(totalDesiredGain - gain);
 
     // Number of frames to de-zipper before we are close enough to the target gain.
-    int framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess; 
+    // FIXME: framesToDezipper could be smaller when target gain is close enough within this process loop.
+    unsigned framesToDezipper = (gainDiff < epsilon) ? 0 : framesToProcess; 
 
-    int k = 0;
+    if (framesToDezipper) {
+        if (!m_dezipperGainValues.get() || m_dezipperGainValues->size() < framesToDezipper)
+            m_dezipperGainValues = adoptPtr(new AudioFloatArray(framesToDezipper));
 
-    if (sumToBus) {
-        // Sum to our bus
-        if (sourceR && destinationR) {
-            // Stereo
-            PROCESS_WITH_GAIN(STEREO_SUM)
-        } else if (destinationR) {
-            // Mono -> stereo 
-            PROCESS_WITH_GAIN(MONO2STEREO_SUM)
-        } else {
-            // Mono
-            PROCESS_WITH_GAIN(MONO_SUM)
+        float* gainValues = m_dezipperGainValues->data();
+        for (unsigned i = 0; i < framesToDezipper; ++i) {
+            gain += (totalDesiredGain - gain) * DezipperRate;
+        
+            // FIXME: If we are clever enough in calculating the framesToDezipper value, we can probably get
+            // rid of this DenormalDisabler::flushDenormalFloatToZero() call.
+            gain = DenormalDisabler::flushDenormalFloatToZero(gain);
+            *gainValues++ = gain;
         }
-    } else {
-        // Process directly (without summing) to our bus
-        if (sourceR && destinationR) {
-            // Stereo
-            PROCESS_WITH_GAIN(STEREO_NO_SUM)
-        } else if (destinationR) {
-            // Mono -> stereo 
-            PROCESS_WITH_GAIN(MONO2STEREO_NO_SUM)
-        } else {
-            // Mono
-            PROCESS_WITH_GAIN(MONO_NO_SUM)
+
+        for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
+            vmul(sources[channelIndex], 1, m_dezipperGainValues->data(), 1, destinations[channelIndex], 1, framesToDezipper);
+            sources[channelIndex] += framesToDezipper;
+            destinations[channelIndex] += framesToDezipper;
         }
+    } else
+        gain = totalDesiredGain;
+
+    // Apply constant gain after de-zippering has converged on target gain.
+    if (framesToDezipper < framesToProcess) {
+        for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex)
+            vsmul(sources[channelIndex], 1, &gain, destinations[channelIndex], 1, framesToProcess - framesToDezipper);
     }
 
     // Save the target gain as the starting point for next time around.
     *lastMixGain = gain;
 }
 
-void AudioBus::processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus)
-{
-    // Make sure we're summing from same type of bus.
-    // We *are* able to sum from mono -> stereo
-    if (sourceBus.numberOfChannels() != 1 && !topologyMatches(sourceBus)) {
-        ASSERT_NOT_REACHED();
-        return;
-    }
-    // If it is copying from the same bus and no need to change gain, just return
-    if (!sumToBus && this == &sourceBus && *lastMixGain == targetGain && targetGain == 1.0)
-        return;
-
-    // Dispatch for different channel layouts
-    switch (numberOfChannels()) {
-    case 1: // mono
-    case 2: // stereo
-        processWithGainFromMonoStereo(sourceBus, lastMixGain, targetGain, sumToBus);
-        break;
-    case 4: // FIXME: implement quad
-    case 5: // FIXME: implement 5.0
-    default:
-        ASSERT_NOT_REACHED();
-        break;
-    }
-}
-
 void AudioBus::copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues)
 {
     // Make sure we're processing from the same type of bus.
@@ -531,16 +427,6 @@
     }
 }
 
-void AudioBus::copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
-{
-    processWithGainFrom(sourceBus, lastMixGain, targetGain, false);
-}
-
-void AudioBus::sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain)
-{
-    processWithGainFrom(sourceBus, lastMixGain, targetGain, true);
-}
-
 PassOwnPtr<AudioBus> AudioBus::createBySampleRateConverting(const AudioBus* sourceBus, bool mixToMono, double newSampleRate)
 {
     // sourceBus's sample-rate must be known.

Modified: trunk/Source/WebCore/platform/audio/AudioBus.h (116595 => 116596)


--- trunk/Source/WebCore/platform/audio/AudioBus.h	2012-05-10 02:00:38 UTC (rev 116595)
+++ trunk/Source/WebCore/platform/audio/AudioBus.h	2012-05-10 02:32:46 UTC (rev 116596)
@@ -109,10 +109,6 @@
     // Scales all samples by the same amount.
     void scale(float scale);
 
-    // Master gain for this bus - used with sumWithGainFrom() below
-    void setGain(float gain) { m_busGain = gain; }
-    float gain() const { return m_busGain; }
-
     void reset() { m_isFirstTime = true; } // for de-zippering
 
     // Assuming sourceBus has the same topology, copies sample data from each channel of sourceBus to our corresponding channel.
@@ -122,12 +118,11 @@
     // Our own internal gain m_busGain is ignored.
     void sumFrom(const AudioBus &sourceBus);
 
-    // Copy or sum each channel from sourceBus into our corresponding channel.
+    // Copy each channel from sourceBus into our corresponding channel.
     // We scale by targetGain (and our own internal gain m_busGain), performing "de-zippering" to smoothly change from *lastMixGain to (targetGain*m_busGain).
-    // The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be summed to this bus.
+    // The caller is responsible for setting up lastMixGain to point to storage which is unique for every "stream" which will be applied to this bus.
     // This represents the dezippering memory.
     void copyWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
-    void sumWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain);
 
     // Copies the sourceBus by scaling with sample-accurate gain values.
     void copyWithSampleAccurateGainValuesFrom(const AudioBus &sourceBus, float* gainValues, unsigned numberOfGainValues);
@@ -143,16 +138,11 @@
 protected:
     AudioBus() { };
 
-    void processWithGainFrom(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);
-    void processWithGainFromMonoStereo(const AudioBus &sourceBus, float* lastMixGain, float targetGain, bool sumToBus);
-
     size_t m_length;
-
     Vector<OwnPtr<AudioChannel> > m_channels;
-
     int m_layout;
-
     float m_busGain;
+    OwnPtr<AudioFloatArray> m_dezipperGainValues;
     bool m_isFirstTime;
     float m_sampleRate; // 0.0 if unknown or N/A
 };
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to