Title: [97912] trunk/Source/WebCore
Revision
97912
Author
[email protected]
Date
2011-10-19 18:52:17 -0700 (Wed, 19 Oct 2011)

Log Message

Flush denormals to zero on Windows.
https://bugs.webkit.org/show_bug.cgi?id=70140

Patch by Raymond Toy <[email protected]> on 2011-10-19
Reviewed by Kenneth Russell.

* platform/audio/AudioBus.cpp:
(WebCore::AudioBus::processWithGainFromMonoStereo):
Flush any denormals to zero before saving the result.  Change
double gain to float gain to match existing float operations.
* platform/audio/DenormalDisabler.h:
(WebCore::DenormalDisabler::flushDenormalFloatToZero):
New function to flush the given float to zero, if it is a denormal
number.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (97911 => 97912)


--- trunk/Source/WebCore/ChangeLog	2011-10-20 01:51:13 UTC (rev 97911)
+++ trunk/Source/WebCore/ChangeLog	2011-10-20 01:52:17 UTC (rev 97912)
@@ -1,3 +1,19 @@
+2011-10-19  Raymond Toy  <[email protected]>
+
+        Flush denormals to zero on Windows.
+        https://bugs.webkit.org/show_bug.cgi?id=70140
+
+        Reviewed by Kenneth Russell.
+
+        * platform/audio/AudioBus.cpp:
+        (WebCore::AudioBus::processWithGainFromMonoStereo):
+        Flush any denormals to zero before saving the result.  Change
+        double gain to float gain to match existing float operations.
+        * platform/audio/DenormalDisabler.h:
+        (WebCore::DenormalDisabler::flushDenormalFloatToZero):
+        New function to flush the given float to zero, if it is a denormal
+        number.
+
 2011-10-19  Raphael Kubo da Costa  <[email protected]>
 
         [EFL] Remove the empty paint() implementation in ScrollbarEfl.

Modified: trunk/Source/WebCore/platform/audio/AudioBus.cpp (97911 => 97912)


--- trunk/Source/WebCore/platform/audio/AudioBus.cpp	2011-10-20 01:51:13 UTC (rev 97911)
+++ trunk/Source/WebCore/platform/audio/AudioBus.cpp	2011-10-20 01:52:17 UTC (rev 97912)
@@ -32,6 +32,8 @@
 
 #include "AudioBus.h"
 
+#include "DenormalDisabler.h"
+
 #if !PLATFORM(MAC)
 #include "SincResampler.h"
 #endif
@@ -238,11 +240,13 @@
     // 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.
-    double totalDesiredGain = m_busGain * targetGain;
+    float totalDesiredGain = static_cast<float>(m_busGain * targetGain);
 
     // First time, snap directly to totalDesiredGain.
-    double gain = m_isFirstTime ? totalDesiredGain : *lastMixGain;
+    float gain = static_cast<float>(m_isFirstTime ? totalDesiredGain : *lastMixGain);
     m_isFirstTime = false;
 
     int numberOfSourceChannels = sourceBus.numberOfChannels();
@@ -255,7 +259,7 @@
     float* destinationL = channelByType(ChannelLeft)->data();
     float* destinationR = numberOfDestinationChannels > 1 ? channelByType(ChannelRight)->data() : 0;
 
-    const double DezipperRate = 0.005;
+    const float DezipperRate = 0.005f;
     int framesToProcess = length();
 
     if (sumToBus) {
@@ -263,33 +267,39 @@
         if (sourceR && destinationR) {
             // Stereo
             while (framesToProcess--) {
-                float sampleL = *sourceL++;
-                float sampleR = *sourceR++;
-                *destinationL++ += static_cast<float>(gain * sampleL);
-                *destinationR++ += static_cast<float>(gain * sampleR);
+                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);
             }
         } 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++ += static_cast<float>(gain * sample);
-                *destinationR++ += static_cast<float>(gain * sample);
+                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);
             }
         } else {
             // Mono
             while (framesToProcess--) {
-                float sampleL = *sourceL++;
-                *destinationL++ += static_cast<float>(gain * sampleL);
+                float sum = DenormalDisabler::flushDenormalFloatToZero(*destinationL + gain * *sourceL++);
+                *destinationL++ = sum;
 
                 // Slowly change gain to desired gain.
                 gain += (totalDesiredGain - gain) * DezipperRate;
+                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
             }
         }
     } else {
@@ -299,37 +309,40 @@
             while (framesToProcess--) {
                 float sampleL = *sourceL++;
                 float sampleR = *sourceR++;
-                *destinationL++ = static_cast<float>(gain * sampleL);
-                *destinationR++ = static_cast<float>(gain * sampleR);
+                *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL);
+                *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleR);
 
                 // Slowly change gain to desired gain.
                 gain += (totalDesiredGain - gain) * DezipperRate;
+                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
             }
         } 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++ = static_cast<float>(gain * sample);
-                *destinationR++ = static_cast<float>(gain * sample);
+                *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample);
+                *destinationR++ = DenormalDisabler::flushDenormalFloatToZero(gain * sample);
 
                 // Slowly change gain to desired gain.
                 gain += (totalDesiredGain - gain) * DezipperRate;
+                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
             }
         } else {
             // Mono
             while (framesToProcess--) {
                 float sampleL = *sourceL++;
-                *destinationL++ = static_cast<float>(gain * sampleL);
+                *destinationL++ = DenormalDisabler::flushDenormalFloatToZero(gain * sampleL);
 
                 // Slowly change gain to desired gain.
                 gain += (totalDesiredGain - gain) * DezipperRate;
+                gain = DenormalDisabler::flushDenormalFloatToZero(gain);
             }
         }
     }
 
     // Save the target gain as the starting point for next time around.
-    *lastMixGain = gain;
+    *lastMixGain = static_cast<double>(gain);
 }
 
 void AudioBus::processWithGainFrom(const AudioBus &sourceBus, double* lastMixGain, double targetGain, bool sumToBus)

Modified: trunk/Source/WebCore/platform/audio/DenormalDisabler.h (97911 => 97912)


--- trunk/Source/WebCore/platform/audio/DenormalDisabler.h	2011-10-20 01:51:13 UTC (rev 97911)
+++ trunk/Source/WebCore/platform/audio/DenormalDisabler.h	2011-10-20 01:52:17 UTC (rev 97912)
@@ -25,6 +25,8 @@
 #ifndef DenormalDisabler_h
 #define DenormalDisabler_h
 
+#include <wtf/MathExtras.h>
+
 namespace WebCore {
 
 // Deal with denormals. They can very seriously impact performance on x86.
@@ -43,6 +45,11 @@
         setCSR(m_savedCSR);
     }
 
+    // This is a nop if we can flush denormals to zero in hardware.
+    static inline float flushDenormalFloatToZero(float f)
+    {
+        return f;
+    }
 private:
     inline int getCSR()
     {
@@ -65,6 +72,18 @@
 class DenormalDisabler {
 public:
     DenormalDisabler() { }
+
+    static inline float flushDenormalFloatToZero(float f)
+    {
+#if OS(WINDOWS) && COMPILER(MSVC) && (!_M_IX86_FP)
+        // For systems using x87 instead of sse, there's no hardware support
+        // to flush denormals automatically. Hence, we need to flush
+        // denormals to zero manually.
+        return (fabs(f) < FLT_MIN) ? 0.0f : f;
+#else
+        return f;
+#endif
+    }
 };
 
 #endif
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to