]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8853 enable change of resolution of fast arc cos table
authorPiotr Gregor <piotrek.gregor@gmail.com>
Fri, 11 Mar 2016 19:27:21 +0000 (19:27 +0000)
committerPiotr Gregor <piotrek.gregor@gmail.com>
Fri, 11 Mar 2016 19:27:21 +0000 (19:27 +0000)
It is possible now to apply lower resolution to mapping
of float-integer-float and decrease size of mapped file.

src/mod/applications/mod_avmd/fast_acosf.c

index 6c990d25202a3a74dcf2c989a2cce9b66867057f..9710c6abc2d55292d8e3d0fc4fa42cb0d2e25d9a 100644 (file)
 
 #ifdef FASTMATH
 
-#define SIGN_MASK (0x80000000)
-#define DATA_MASK (0x07FFFFF8)
-
-#define SIGN_UNPACK_MASK (0x01000000)
-#define DATA_UNPACK_MASK (0x00FFFFFF)
-
-#define VARIA_DATA_MASK (0x87FFFFF8)
-#define CONST_DATA_MASK (0x38000000)
-
-#define ACOS_TABLE_LENGTH (1 << 25)
-#define ACOS_TABLE_FILENAME "/tmp/acos_table.dat"
 
 typedef union {
     uint32_t i;
     float f;
 } float_conv_t;
 
-#ifdef FAST_ACOSF_TESTING
-static float strip_float(float f);
-#endif
+/* 
+ * Manipulate these parameters to change
+ * mapping's resolution. The sine tone
+ * of 1600Hz is detected even with 20
+ * bits discarded in float integer representation
+ * with only slightly increased amount of false
+ * positives (keeping variance threshold on 0.0001).
+ * 12 bits seem to be good choice when there is
+ * a need to compute faster and/or decrease mapped file
+ * size on disk while keeping false positives low.
+ */
+#define ACOS_TABLE_CONST_EXPONENT (0x70)
+#define ACOS_TABLE_CONST_EXPONENT_BITS (3)
+#define ACOS_TABLE_DISCARDED_BITS (3)
+/* rosolution:
+    3: 15 728 640 indices spreading range [0.0, 1.0], table size on disk 134 217 728 bytes (default)
+    4:  7 364 320 indices spreading range [0.0, 1.0], table size on disk  67 108 864 bytes
+    5:  3 932 160 indices spreading range [0.0, 1.0], table size on disk  33 554 432 bytes
+    12:    30 720 indices spreading range [0.0, 1.0], table size on disk     262 144 bytes
+    16:     1 920 indices spreading range [0.0, 1.0], table size on disk      16 384 bytes
+    20:       120 indices spreading range [0.0, 1.0], table size on disk       1 024 bytes
+    24:         7 indices spreading range [0.0, 1.0], table size on disk          64 bytes
+    26:         1 indices spreading range [0.0, 1.0], table size on disk          16 bytes
+*/
+#define ACOS_TABLE_FREE_EXPONENT_BITS (7 - ACOS_TABLE_CONST_EXPONENT_BITS)
+#define ACOS_TABLE_DATA_BITS (31 - ACOS_TABLE_CONST_EXPONENT_BITS - ACOS_TABLE_DISCARDED_BITS)
+#define ACOS_TABLE_LENGTH (1 << (31 - ACOS_TABLE_CONST_EXPONENT_BITS - ACOS_TABLE_DISCARDED_BITS))
+
+#define VARIA_DATA_MASK (0x87FFFFFF & ~((1 << ACOS_TABLE_DISCARDED_BITS) - 1))
+#define CONST_DATA_MASK (((1 << ACOS_TABLE_CONST_EXPONENT_BITS) - 1) \
+                                    << (ACOS_TABLE_DATA_BITS - 1 + ACOS_TABLE_DISCARDED_BITS))
+
+#define SIGN_UNPACK_MASK (1 << (ACOS_TABLE_DATA_BITS - 1))
+#define DATA_UNPACK_MASK ((1 << (ACOS_TABLE_DATA_BITS - 1)) - 1)
+
+#define SIGN_MASK  (0x80000000)
+#define DATA_MASK (DATA_UNPACK_MASK << ACOS_TABLE_DISCARDED_BITS)
+
+#define ACOS_TABLE_FILENAME "/tmp/acos_table.dat"
+
 static uint32_t index_from_float(float f);
 static float float_from_index(uint32_t d);
 static float *acos_table = NULL;
 static int acos_fd = -1;
 
+
 #ifdef FAST_ACOSF_TESTING
-static float strip_float(float f)
-{
-    float_conv_t d;
 
-    d.i = d.i & (VARIA_DATA_MASK | CONST_DATA_MASK);
+#define INF(x) printf("[%s] [%u]\n", #x, x)
+#define INFX(x) printf("[%s] [%08x]\n", #x, x)
+
+static void
+debug_print(void);
+
+static void
+dump_table_summary(void);
+
+#endif /* FAST_ACOSF_TESTING */
 
-    return d.i;
-}
-#endif
 
 extern void compute_table(void)
 {
@@ -114,23 +144,138 @@ extern float fast_acosf(float x)
     return acos_table[index_from_float(x)];
 }
 
-
 static uint32_t index_from_float(float f)
 {
     float_conv_t d;
-
     d.f = f;
-    return ((d.i & SIGN_MASK) >> 7) | ((d.i & DATA_MASK) >> 3);
+    return ((d.i & SIGN_MASK) >> (32 - ACOS_TABLE_DATA_BITS)) |
+        ((d.i & DATA_MASK) >> ACOS_TABLE_DISCARDED_BITS);
 }
 
-
 static float float_from_index(uint32_t d)
 {
     float_conv_t f;
-
-    f.i = ((d & SIGN_UNPACK_MASK) << 7) | ((d & DATA_UNPACK_MASK) << 3) | CONST_DATA_MASK;
+    f.i = ((d & SIGN_UNPACK_MASK) << (32 - ACOS_TABLE_DATA_BITS)) |
+        ((d & DATA_UNPACK_MASK) << ACOS_TABLE_DISCARDED_BITS) | CONST_DATA_MASK;
     return f.f;
 }
 
+#ifdef FAST_ACOSF_TESTING
+
+#define INF(x) printf("[%s] [%u]\n", #x, x)
+#define INFX(x) printf("[%s] [%08x]\n", #x, x)
+
+static void
+debug_print(void)
+{
+    INF(ACOS_TABLE_CONST_EXPONENT);
+    INF(ACOS_TABLE_CONST_EXPONENT_BITS);
+    INF(ACOS_TABLE_FREE_EXPONENT_BITS);
+    INF(ACOS_TABLE_DISCARDED_BITS);
+    INF(ACOS_TABLE_DATA_BITS);
+    INF(ACOS_TABLE_LENGTH);
+    INFX(VARIA_DATA_MASK);
+    INFX(CONST_DATA_MASK);
+    INFX(SIGN_UNPACK_MASK);
+    INFX(DATA_UNPACK_MASK);
+    INFX(SIGN_MASK);
+    INFX(DATA_MASK);
+}
+
+static void
+dump_table_summary(void)
+{
+    uint32_t i, i_0, i_1, di;
+    float f;
+
+    i = 1;
+    i_0 = index_from_float(0.0);
+    i_1 = index_from_float(1.0);
+    di = (i_1 - i_0)/100;
+    if (di == 0)  di = 1;
+    for (; i < ACOS_TABLE_LENGTH; i += di )
+    {
+        f = float_from_index(i);
+        printf("-01i[%.10u] : ffi[%f] fa[%f] acos[%f]\n",
+                i, f, fast_acosf(f), acos(f));
+    }
+
+    i = 1;
+    for (; i < ACOS_TABLE_LENGTH; i = (i << 1))
+    {
+        f = fast_acosf(float_from_index(i));
+        printf("--i[%.10u] : fa[%f] ffi[%f]\n",
+                i, f, float_from_index(i));
+    }
+
+    f = 0.0;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.1;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.2;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.3;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.4;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.5;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.6;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.7;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 7.5;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.8;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.9;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.95;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.99;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 1.0;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 1.1;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 1.2;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = 0.0;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.1;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.2;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.3;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.4;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.5;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.6;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.7;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -7.5;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.8;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.9;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.95;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -0.99;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -1.0;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -1.1;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+    f = -1.2;
+    printf("i [%d] from float [%f]\n", index_from_float(f), f);
+}
+
+#endif /* FAST_ACOSF_TESTING */
+
 
 #endif