OSDN Git Service

Update audio primitives for floating point conversion speed
authorAndy Hung <hunga@google.com>
Sat, 18 Nov 2017 00:02:19 +0000 (16:02 -0800)
committerAndy Hung <hunga@google.com>
Tue, 28 Nov 2017 20:41:40 +0000 (12:41 -0800)
Floats now round-half-up instead of round-half-to-even.
This returns 25% gain in performance for slightly worse rounding.

Also a cosmetic change to convert an if to an add with boolean.

Bug: 69479669
Test: primitives_tests
Change-Id: I15dc17f5732e41594c23831622d0c1642881a711

audio_utils/include/audio_utils/primitives.h
audio_utils/primitives.c

index 5f14a57..a3727d7 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef ANDROID_AUDIO_PRIMITIVES_H
 #define ANDROID_AUDIO_PRIMITIVES_H
 
+#include <math.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/cdefs.h>
@@ -721,10 +722,12 @@ static inline int32_t clamp32(int64_t sample)
  * depending on the sign bit inside NaN (whose representation is not unique).
  * Nevertheless, strictly speaking, NaN behavior should be considered undefined.
  *
- * Rounding of 0.5 lsb is to even (default for IEEE 754).
+ * OLD code disabled: Rounding of 0.5 lsb is to even (default for IEEE 754).
+ * NEW code enabled: Rounding of 0.5 lsb is away from 0.
  */
 static inline int16_t clamp16_from_float(float f)
 {
+#if 0
     /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the
      * floating point significand. The normal shift is 3<<22, but the -15 offset
      * is used to multiply by 32768.
@@ -748,6 +751,10 @@ static inline int16_t clamp16_from_float(float f)
     else if (u.i > limpos)
         u.i = 32767;
     return u.i; /* Return lower 16 bits, the part of interest in the significand. */
+#else
+    static const float scale = 1 << 15;
+    return roundf(fmaxf(fminf(f * scale, scale - 1.f), -scale));
+#endif
 }
 
 /**
@@ -760,10 +767,12 @@ static inline int16_t clamp16_from_float(float f)
  * depending on the sign bit inside NaN (whose representation is not unique).
  * Nevertheless, strictly speaking, NaN behavior should be considered undefined.
  *
- * Rounding of 0.5 lsb is to even (default for IEEE 754).
+ * OLD code disabled: Rounding of 0.5 lsb is to even (default for IEEE 754).
+ * NEW code enabled: Rounding of 0.5 lsb is away from 0.
  */
 static inline uint8_t clamp8_from_float(float f)
 {
+#if 0
     /* Offset is used to expand the valid range of [-1.0, 1.0) into the 16 lsbs of the
      * floating point significand. The normal shift is 3<<22, but the -7 offset
      * is used to multiply by 128.
@@ -787,13 +796,17 @@ static inline uint8_t clamp8_from_float(float f)
     if (u.i > limpos)
         return 255;
     return u.i; /* Return lower 8 bits, the part of interest in the significand. */
+#else
+    return roundf(fmaxf(fminf(f * 128.f + 128.f, 255.f), 0.f));
+#endif
 }
 
 /**
  * Convert a single-precision floating point value to a Q0.23 integer value, stored in a
  * 32 bit signed integer (technically stored as Q8.23, but clamped to Q0.23).
  *
- * Rounds to nearest, ties away from 0.
+ * OLD code disabled: Rounds to nearest, ties away from 0.
+ * NEW code enabled: Rounding of 0.5 lsb is away from 0.
  *
  * Values outside the range [-1.0, 1.0) are properly clamped to -8388608 and 8388607,
  * including -Inf and +Inf. NaN values are considered undefined, and behavior may change
@@ -801,6 +814,7 @@ static inline uint8_t clamp8_from_float(float f)
  */
 static inline int32_t clamp24_from_float(float f)
 {
+#if 0
     static const float scale = (float)(1 << 23);
     static const float limpos = 0x7fffff / scale;
     static const float limneg = -0x800000 / scale;
@@ -815,6 +829,10 @@ static inline int32_t clamp24_from_float(float f)
      * ensure that we round to nearest, ties away from 0.
      */
     return f > 0 ? f + 0.5 : f - 0.5;
+#else
+    static const float scale = 1 << 23;
+    return roundf(fmaxf(fminf(f * scale, scale - 1.f), -scale));
+#endif
 }
 
 /**
index 67fb740..d88d701 100644 (file)
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <math.h>
 #include <cutils/bitops.h>  /* for popcount() */
 #include <audio_utils/primitives.h>
 #include "private/private.h"
@@ -332,9 +331,7 @@ size_t nonZeroMono32(const int32_t *samples, size_t count)
 {
     size_t nonZero = 0;
     for (; count > 0; --count) {
-        if (*samples++ != 0) {
-            nonZero++;
-        }
+        nonZero += *samples++ != 0;
     }
     return nonZero;
 }
@@ -343,9 +340,7 @@ size_t nonZeroMono16(const int16_t *samples, size_t count)
 {
     size_t nonZero = 0;
     for (; count > 0; --count) {
-        if (*samples++ != 0) {
-            nonZero++;
-        }
+        nonZero += *samples++ != 0;
     }
     return nonZero;
 }
@@ -354,9 +349,7 @@ size_t nonZeroStereo32(const int32_t *frames, size_t count)
 {
     size_t nonZero = 0;
     for (; count > 0; --count) {
-        if (frames[0] != 0 || frames[1] != 0) {
-            nonZero++;
-        }
+        nonZero += frames[0] != 0 || frames[1] != 0;
         frames += 2;
     }
     return nonZero;
@@ -366,9 +359,7 @@ size_t nonZeroStereo16(const int16_t *frames, size_t count)
 {
     size_t nonZero = 0;
     for (; count > 0; --count) {
-        if (frames[0] != 0 || frames[1] != 0) {
-            nonZero++;
-        }
+        nonZero += frames[0] != 0 || frames[1] != 0;
         frames += 2;
     }
     return nonZero;