shithub: sox

Download patch

ref: 47d73971bb09ec0a6073626c181d8fb095038179
parent: 0a33c800bb999148b32439fdfdc6bbbeaf5f898d
author: cbagwell <cbagwell>
date: Tue Sep 28 22:31:37 EDT 2004

Add float support to .au and make float routines work with normalized data

--- a/Changelog
+++ b/Changelog
@@ -54,6 +54,10 @@
   o Donnie Smith updated the silence effect so that its possible
     to remove silence from the middle of a sound file by
     using a negative value for stop_periods.
+  o Changed float routines to only work with normalized values
+    from -1:1.
+  o Modifed .au handler to be able to read and write 32-bit
+    and 64-bit float data.  Only tested reading so far.
 
 sox-12.17.5
 -----------
--- a/src/au.c
+++ b/src/au.c
@@ -94,6 +94,10 @@
             *encoding = ST_ENCODING_SIGN2;
             *size = ST_SIZE_WORD;
             break;
+    case SUN_FLOAT:
+            *encoding = ST_ENCODING_FLOAT;
+            *size = ST_SIZE_32BIT;
+            break;
     default:
             st_report("encoding: 0x%lx", encoding);
             return(ST_EOF);
@@ -208,7 +212,7 @@
         if(st_auencodingandsize(encoding, &(ft->info.encoding),
                              &(ft->info.size)) == ST_EOF)
         {
-            st_fail_errno(ft,ST_EFMT,"Unsupported encoding in Sun/NeXT header.\nOnly U-law, signed bytes, signed words, and ADPCM are supported.");
+            st_fail_errno(ft,ST_EFMT,"Unsupported encoding in Sun/NeXT header.\nOnly U-law, signed bytes, signed words, ADPCM, and 32-bit floats are supported.");
             return(ST_EOF);
         }
         switch (encoding) {
@@ -392,6 +396,8 @@
                 sun_encoding = SUN_LIN_8;
         else if (encoding == ST_ENCODING_SIGN2 && size == ST_SIZE_WORD)
                 sun_encoding = SUN_LIN_16;
+        else if (encoding == ST_ENCODING_FLOAT && size == ST_SIZE_32BIT)
+                sun_encoding = SUN_FLOAT;
         else
                 sun_encoding = -1;
         return sun_encoding;
--- a/src/misc.c
+++ b/src/misc.c
@@ -240,12 +240,16 @@
 /* Read float. */
 int st_readf(ft_t ft, float *f)
 {
-        if (st_read(ft, f, sizeof(float), 1) != 1)
+        uint32_t datum, *dp;
+
+        dp = &datum;
+        if (st_read(ft, dp, sizeof(float), 1) != 1)
         {
             return(ST_EOF);
         }
         if (ft->swap)
-                *f = st_swapf(*f);
+                datum = st_swapdw(datum);
+        *f = *((float *)dp);
         return ST_SUCCESS;
 }
 
@@ -267,12 +271,20 @@
 /* Read double. */
 int st_readdf(ft_t ft, double *d)
 {
-        if (st_read(ft, d, sizeof(double), 1) != 1)
+        uint32_t datum[2], *dp;
+
+        dp = &datum[0];
+        if (st_read(ft, dp, sizeof(double), 1) != 1)
         {
             return(ST_EOF);
         }
         if (ft->swap)
-                *d = st_swapd(*d);
+        {
+                datum[0] = st_swapd(datum[0]);
+                datum[1] = st_swapd(datum[1]);
+        }
+        *d = *((float *)dp);
+
         return ST_SUCCESS;
 }
 
--- a/src/raw.c
+++ b/src/raw.c
@@ -301,12 +301,17 @@
     while (len)
     {
         float datum;
+        uint32_t int_datum, *ip;
 
-        datum = *((float *)buf2);
+        /* If swapping is needed, do this before converting to a float. */
+        int_datum = *((uint32_t *)buf2);
         buf2++; buf2++; buf2++; buf2++;
         if (swap)
-            datum = st_swapf(datum);
+            int_datum = st_swapdw(int_datum);
 
+        ip = &int_datum;
+        datum = *((float *)ip);
+    
         *buf1++ = ST_FLOAT_DWORD_TO_SAMPLE(datum);
         len--;
     }
@@ -317,12 +322,23 @@
     while (len)
     {
         double datum;
+        uint32_t int_datum[2], *ip;
 
-        datum = *((double *)buf2);
+        /* If swapping needs to occur, do this before moving into
+         * float data.
+         */
+        int_datum[0] = *((uint32_t *)buf2);
         buf2++; buf2++; buf2++; buf2++;
+        if (swap)
+            int_datum[0] = st_swapdw(int_datum[0]);
+
+        int_datum[1] = *((uint32_t *)buf2);
         buf2++; buf2++; buf2++; buf2++;
         if (swap)
-            datum = st_swapd(datum);
+            int_datum[1] = st_swapdw(int_datum[1]);
+
+        ip = &int_datum[0];
+        datum = *((double *)ip);
 
         *buf1++ = ST_FLOAT_DDWORD_TO_SAMPLE(datum);
         len--;
--- a/src/st.h
+++ b/src/st.h
@@ -32,6 +32,15 @@
 #define ST_SAMPLE_MAX 0x7fffffffL
 #define ST_SAMPLE_MIN (-ST_SAMPLE_MAX - 1L)
 
+/* The following is the stepsize to be used when converting
+ * normalized float data (-1 to 1) to a 32-bit signed sample.
+ * FIXME: This is is an approximation because signed integers
+ * have one more value on the negative and so sample/SCALE
+ * doesn't map exactly to -1:1.
+ */
+#define ST_SAMPLE_FLOAT_DWORD_SCALE 2147483647.0
+#define ST_SAMPLE_FLOAT_DDWORD_SCALE 9223372036854775807.0
+
 #define ST_UNSIGNED_BYTE_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x80) << 24)
 #define ST_SIGNED_BYTE_TO_SAMPLE(d) ((st_sample_t)(d) << 24)
 #define ST_UNSIGNED_WORD_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x8000) << 16)
@@ -38,9 +47,10 @@
 #define ST_SIGNED_WORD_TO_SAMPLE(d) ((st_sample_t)(d) << 16)
 #define ST_UNSIGNED_DWORD_TO_SAMPLE(d) ((st_sample_t)((d) ^ 0x80000000L))
 #define ST_SIGNED_DWORD_TO_SAMPLE(d) ((st_sample_t)d)
-#define ST_FLOAT_DWORD_TO_SAMPLE(d) ((st_sample_t)d)
-#define ST_FLOAT_DDWORD_TO_SAMPLE(d) ((st_sample_t)d)
-
+/* FIXME: This is an approximation because it 
+ * doesn't account for -1.0 mapping to -FLOAT_SCALE-1. */
+#define ST_FLOAT_DWORD_TO_SAMPLE(d) ((st_sample_t)(d*ST_SAMPLE_FLOAT_DWORD_SCALE))
+#define ST_FLOAT_DDWORD_TO_SAMPLE(d) ((st_sample_t)(d*ST_SAMPLE_FLOAT_DDWORD_SCALE))
 #define ST_SAMPLE_TO_UNSIGNED_BYTE(d) ((uint8_t)((d) >> 24) ^ 0x80)
 #define ST_SAMPLE_TO_SIGNED_BYTE(d) ((int8_t)((d) >> 24))
 #define ST_SAMPLE_TO_UNSIGNED_WORD(d) ((uint16_t)((d) >> 16) ^ 0x8000)
@@ -47,9 +57,12 @@
 #define ST_SAMPLE_TO_SIGNED_WORD(d) ((int16_t)((d) >> 16))
 #define ST_SAMPLE_TO_UNSIGNED_DWORD(d) ((uint32_t)(d) ^ 0x80000000L)
 #define ST_SAMPLE_TO_SIGNED_DWORD(d) ((int32_t)(d))
-#define ST_SAMPLE_TO_FLOAT_DWORD(d) ((float)(d))
-#define ST_SAMPLE_TO_FLOAT_DDWORD(d) ((double)(d))
-
+/* FIXME: This is an approximation because its impossible to
+ * to reach 1.  Something like floor(d/(SCALE+0.5)) would probably
+ * get it right.
+ */
+#define ST_SAMPLE_TO_FLOAT_DWORD(d) ((float)(d/(ST_SAMPLE_FLOAT_DWORD_SCALE+1)))
+#define ST_SAMPLE_TO_FLOAT_DDWORD(d) ((double)((double)d/(ST_SAMPLE_FLOAT_DDWORD_SCALE+1)))
 
 /* Maximum value size type can hold. (Minimum is 0). */
 #define ST_SIZE_MAX 0xffffffffL