Title: [102888] trunk/Source/WebCore
Revision
102888
Author
[email protected]
Date
2011-12-14 22:14:11 -0800 (Wed, 14 Dec 2011)

Log Message

fast path to accelerate processing in AudioBus::processWithGainFromMonoStereo
https://bugs.webkit.org/show_bug.cgi?id=74054

Patch by Wei James <[email protected]> on 2011-12-14
Reviewed by Kenneth Russell.

Avoid de-zippering when the gain has converged on the targetGain.
It can get about 75% performance gain at most when all frames don't need
de-zippering.

* platform/audio/AudioBus.cpp:
(WebCore::AudioBus::processWithGainFromMonoStereo):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (102887 => 102888)


--- trunk/Source/WebCore/ChangeLog	2011-12-15 06:14:08 UTC (rev 102887)
+++ trunk/Source/WebCore/ChangeLog	2011-12-15 06:14:11 UTC (rev 102888)
@@ -1,3 +1,17 @@
+2011-12-14  Wei James  <[email protected]>
+
+        fast path to accelerate processing in AudioBus::processWithGainFromMonoStereo
+        https://bugs.webkit.org/show_bug.cgi?id=74054
+
+        Reviewed by Kenneth Russell.
+
+        Avoid de-zippering when the gain has converged on the targetGain. 
+        It can get about 75% performance gain at most when all frames don't need
+        de-zippering.
+
+        * platform/audio/AudioBus.cpp:
+        (WebCore::AudioBus::processWithGainFromMonoStereo):
+
 2011-12-14  Adam Klein  <[email protected]>
 
         Optimize MutationObserverInterestGroup construction

Modified: trunk/Source/WebCore/platform/audio/AudioBus.cpp (102887 => 102888)


--- trunk/Source/WebCore/platform/audio/AudioBus.cpp	2011-12-15 06:14:08 UTC (rev 102887)
+++ trunk/Source/WebCore/platform/audio/AudioBus.cpp	2011-12-15 06:14:11 UTC (rev 102888)
@@ -231,15 +231,76 @@
     }
 }
 
+// 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 \
+    } \
+    gain = totalDesiredGain; \
+    for (; k < framesToProcess; ++k)  \
+        OP
+
+#define STEREO_SUM \
+    { \
+        float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
+        float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + gain * *sourceR++); \
+        *destinationL++ = sumL; \
+        *destinationR++ = sumR; \
+    }
+
+// 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; \
+    }
+
+#define MONO_SUM \
+    { \
+        float sum = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++); \
+        *destinationL++ = sum; \
+    }
+
+#define STEREO_NO_SUM \
+    { \
+        float sampleL = *sourceL++; \
+        float sampleR = *sourceR++; \
+        *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
+        *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleR); \
+    }
+
+// 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 MONO_NO_SUM \
+    { \
+        float sampleL = *sourceL++; \
+        *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL); \
+    }
+
 void AudioBus::processWithGainFromMonoStereo(const AudioBus &sourceBus, double* lastMixGain, double 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.
 
     // FIXME: optimize this method (SSE, etc.)
-    // FIXME: Need fast path here when gain has converged on targetGain. In this case, de-zippering is no longer needed.
-    // FIXME: Need fast path when this==sourceBus && lastMixGain==targetGain==1.0 && sumToBus==false (this is a NOP)
-
     // FIXME: targetGain and lastMixGain should be changed to floats instead of doubles.
     
     // Take master bus gain into account as well as the targetGain.
@@ -262,82 +323,45 @@
     const float DezipperRate = 0.005f;
     int framesToProcess = length();
 
+    // If the gain is within epsilon of totalDesiredGain, we can skip dezippering. 
+    // FIXME: this value may need tweaking.
+    const float epsilon = 0.001f; 
+    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; 
+
+    int k = 0;
+
     if (sumToBus) {
         // Sum to our bus
         if (sourceR && destinationR) {
             // Stereo
-            while (framesToProcess--) {
-                float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++);
-                float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + gain * *sourceR++);
-                *destinationL++ = sumL;
-                *destinationR++ = sumR;
-
-                // Slowly change gain to desired gain.
-                gain += (totalDesiredGain - gain) * DezipperRate;
-                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
-            }
+            PROCESS_WITH_GAIN(STEREO_SUM)
         } else if (destinationR) {
-            // 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...
-            while (framesToProcess--) {
-                float scaled = gain * *sourceL++;
-                float sumL = DenormalDisabler::flushDenormalFloatToZero(*destinationL + scaled);
-                float sumR = DenormalDisabler::flushDenormalFloatToZero(*destinationR + scaled);
-
-                *destinationL++ = sumL;
-                *destinationR++ = sumR;
-
-                // Slowly change gain to desired gain.
-                gain += (totalDesiredGain - gain) * DezipperRate;
-                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
-            }
+            // Mono -> stereo 
+            PROCESS_WITH_GAIN(MONO2STEREO_SUM)
         } else {
             // Mono
-            while (framesToProcess--) {
-                float sum = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++);
-                *destinationL++ = sum;
-
-                // Slowly change gain to desired gain.
-                gain += (totalDesiredGain - gain) * DezipperRate;
-                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
-            }
+            PROCESS_WITH_GAIN(MONO_SUM)
         }
     } else {
         // Process directly (without summing) to our bus
+        // If it is from the same bus and no need to change gain, just return
+        if (this == &sourceBus && *lastMixGain == targetGain && targetGain == 1.0)
+            return;
+
+        // FIXME: if (framesToDezipper == 0) and DenormalDisabler::flushDenormalFloatToZero() is a NOP (gcc vs. Visual Studio) 
+        // then we can further optimize the PROCESS_WITH_GAIN codepaths below using vsmul().
         if (sourceR && destinationR) {
             // Stereo
-            while (framesToProcess--) {
-                float sampleL = *sourceL++;
-                float sampleR = *sourceR++;
-                *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL);
-                *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleR);
-
-                // Slowly change gain to desired gain.
-                gain += (totalDesiredGain - gain) * DezipperRate;
-                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
-            }
+            PROCESS_WITH_GAIN(STEREO_NO_SUM)
         } else if (destinationR) {
-            // 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...
-            while (framesToProcess--) {
-                float sample = *sourceL++;
-                *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample);
-                *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample);
-
-                // Slowly change gain to desired gain.
-                gain += (totalDesiredGain - gain) * DezipperRate;
-                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
-            }
+            // Mono -> stereo 
+            PROCESS_WITH_GAIN(MONO2STEREO_NO_SUM)
         } else {
             // Mono
-            while (framesToProcess--) {
-                float sampleL = *sourceL++;
-                *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL);
-
-                // Slowly change gain to desired gain.
-                gain += (totalDesiredGain - gain) * DezipperRate;
-                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
-            }
+            PROCESS_WITH_GAIN(MONO_NO_SUM)
         }
     }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to