shithub: sox

Download patch

ref: 31cbdafeade02c8df05ab506f713a032890e92c4
parent: 40ad2f19bc2ec47e7b3b1e08a9903e82e8624954
author: robs <robs>
date: Sun Mar 16 04:11:11 EDT 2008

Can now write Sounder files
Can now write DEC-variant au files (with -x)
Comments support for SoundTool files
Fix IRCAM SF header processing; support all (modern) variants
Fix 24-bit read/write on big-endian systems
For some file-types, warn if file size seems too short
Added auto-detect for caf, sndr, txw & sf files
Fix endian selection (-B, -L, -x) in some circumstances
Reimplement (separately) SoundTool & Sounder format handlers

--- a/src/soxio.c
+++ b/src/soxio.c
@@ -139,27 +139,19 @@
 
 void set_signal_defaults(sox_signalinfo_t * signal)
 {
-  if (!signal->rate    ) signal->rate     = SOX_DEFAULT_RATE;
-  if (!signal->precision    ) signal->precision     = SOX_DEFAULT_PRECISION;
-  if (!signal->channels) signal->channels = SOX_DEFAULT_CHANNELS;
+  if (!signal->rate     ) signal->rate      = SOX_DEFAULT_RATE;
+  if (!signal->precision) signal->precision = SOX_DEFAULT_PRECISION;
+  if (!signal->channels ) signal->channels  = SOX_DEFAULT_CHANNELS;
 }
 
 static void set_endianness_if_not_already_set(sox_format_t * ft)
 {
-  if (ft->encoding.reverse_bytes == SOX_OPTION_DEFAULT) {
-    if (ft->handler.flags & SOX_FILE_ENDIAN)
-    {
-        /* Set revere_bytes if we are running on opposite endian
-         * machine compared to file format.
-         */
-        if (ft->handler.flags & SOX_FILE_ENDBIG)
-            ft->encoding.reverse_bytes = SOX_IS_LITTLEENDIAN;
-        else
-            ft->encoding.reverse_bytes = SOX_IS_BIGENDIAN;
-    }
-    else
-      ft->encoding.reverse_bytes = SOX_OPTION_NO;
-  }
+  if (ft->encoding.opposite_endian)
+    ft->encoding.reverse_bytes = (ft->handler.flags & SOX_FILE_ENDIAN)?
+      !(ft->handler.flags & SOX_FILE_ENDBIG) != SOX_IS_BIGENDIAN : sox_true;
+  if (ft->encoding.reverse_bytes == SOX_OPTION_DEFAULT)
+    ft->encoding.reverse_bytes = (ft->handler.flags & SOX_FILE_ENDIAN)?
+      !(ft->handler.flags & SOX_FILE_ENDBIG) == SOX_IS_BIGENDIAN : sox_false;
   if (ft->encoding.reverse_bits == SOX_OPTION_DEFAULT)
     ft->encoding.reverse_bits = !!(ft->handler.flags & SOX_FILE_BIT_REV);
   else if (ft->encoding.reverse_bits != !!(ft->handler.flags & SOX_FILE_BIT_REV))
@@ -195,7 +187,7 @@
   return SOX_SUCCESS;
 }
 
-static char const * detect_magic(sox_format_t * ft)
+static char const * detect_magic(sox_format_t * ft, char const * ext)
 {
   char data[256];
   size_t len = sox_readbuf(ft, data, sizeof(data));
@@ -209,7 +201,7 @@
   MAGIC(sph   , 0, 0, ""     , 0,  7, "NIST_1A")
   MAGIC(amr-nb, 0, 0, ""     , 0,  6, "#!AMR\n")
   MAGIC(txw   , 0, 0, ""     , 0,  6, "LM8953")
-  MAGIC(sndt  , 0, 0, ""     , 0,  5, "SOUND")
+  MAGIC(sndt  , 0, 0, ""     , 0,  6, "SOUND\x1a")
   MAGIC(vorbis, 0, 4, "OggS" , 29, 6, "vorbis")
   MAGIC(speex , 0, 4, "OggS" , 28, 6, "Speex")
   MAGIC(hcom  ,65, 4, "FSSD" , 128,4, "HCOM")
@@ -222,13 +214,24 @@
   MAGIC(xa    , 0, 0, ""     , 0,  4, "XA\0\0")
   MAGIC(xa    , 0, 0, ""     , 0,  4, "XAI\0")
   MAGIC(xa    , 0, 0, ""     , 0,  4, "XAJ\0")
-  MAGIC(au    , 0, 0, ""     , 0,  4, "\0ds.")
   MAGIC(au    , 0, 0, ""     , 0,  4, ".snd")
+  MAGIC(au    , 0, 0, ""     , 0,  4, "dns.")
+  MAGIC(au    , 0, 0, ""     , 0,  4, "\0ds.")
+  MAGIC(au    , 0, 0, ""     , 0,  4, ".sd\0")
   MAGIC(flac  , 0, 0, ""     , 0,  4, "fLaC")
   MAGIC(avr   , 0, 0, ""     , 0,  4, "2BIT")
   MAGIC(caf   , 0, 0, ""     , 0,  4, "caff")
   MAGIC(paf   , 0, 0, ""     , 0,  4, " paf")
-  MAGIC(sf    , 3, 1, ""     , 0,  2, "\144\243")
+  MAGIC(sf    , 0, 0, ""     , 0,  4, "\144\243\001\0")
+  MAGIC(sf    , 0, 0, ""     , 0,  4, "\0\001\243\144")
+  MAGIC(sf    , 0, 0, ""     , 0,  4, "\144\243\002\0")
+  MAGIC(sf    , 0, 0, ""     , 0,  4, "\0\002\243\144")
+  MAGIC(sf    , 0, 0, ""     , 0,  4, "\144\243\003\0")
+  MAGIC(sf    , 0, 0, ""     , 0,  4, "\0\003\243\144")
+  MAGIC(sf    , 0, 0, ""     , 0,  4, "\144\243\004\0")
+
+  if (ext && !strcasecmp(ext, "snd"))
+  MAGIC(sndr  , 7, 1, ""     , 0,  2, "\0")
   #undef MAGIC
   return NULL;
 }
@@ -269,7 +272,7 @@
 
   if (!filetype) {
     if (ft->seekable) {
-      filetype = detect_magic(ft);
+      filetype = detect_magic(ft, find_file_extension(path));
       sox_rewind(ft);
     }
     if (filetype) {
@@ -662,9 +665,7 @@
       sox_format_t * ft, ctype *buf, sox_size_t len) \
   { \
     sox_size_t n, nread; \
-    if ((nread = sox_readbuf(ft, buf, len * size)) != len * size && sox_error(ft)) \
-      sox_fail_errno(ft, errno, sox_readerr); \
-    nread /= size; \
+    nread = sox_readbuf(ft, buf, len * size) / size; \
     for (n = 0; n < nread; n++) \
       twiddle(buf[n], type); \
     return nread; \
@@ -671,7 +672,9 @@
   }
 
 /* Unpack a 3-byte value from a uint8_t * */
-#define sox_unpack3(p) ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16))
+#define sox_unpack3(p) (ft->encoding.reverse_bytes == SOX_IS_BIGENDIAN? \
+  ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16)) : \
+  ((p)[2] | ((p)[1] << 8) | ((p)[0] << 16)))
 
 /* This (slower) macro works for unaligned types (e.g. 3-byte types)
    that need to be unpacked. */
@@ -681,14 +684,9 @@
   { \
     sox_size_t n, nread; \
     uint8_t *data = xmalloc(size * len); \
-    if ((nread = sox_readbuf(ft, data, len * size)) != len * size && sox_error(ft)) \
-      sox_fail_errno(ft, errno, sox_readerr); \
-    nread /= size; \
-    for (n = 0; n < nread; n++) { \
-      ctype datum = sox_unpack ## size(data + n * size); \
-      twiddle(datum, type); \
-      buf[n] = datum; \
-    } \
+    nread = sox_readbuf(ft, data, len * size) / size; \
+    for (n = 0; n < nread; n++) \
+      buf[n] = sox_unpack ## size(data + n * size); \
     free(data); \
     return n; \
   }
@@ -700,6 +698,34 @@
 READ_FUNC(f, sizeof(float), float, TWIDDLE_FLOAT)
 READ_FUNC(df, sizeof(double), double, TWIDDLE_WORD)
 
+#define READ1_FUNC(type, ctype) \
+int sox_read ## type(sox_format_t * ft, ctype * datum) { \
+  if (sox_read_ ## type ## _buf(ft, datum, 1) == 1) \
+    return SOX_SUCCESS; \
+  if (!sox_error(ft)) \
+    sox_fail_errno(ft, errno, premature_eof); \
+  return SOX_EOF; \
+}
+
+static char const premature_eof[] = "premature EOF";
+
+READ1_FUNC(b,  uint8_t)
+READ1_FUNC(w,  uint16_t)
+READ1_FUNC(3,  uint24_t)
+READ1_FUNC(dw, uint32_t)
+READ1_FUNC(f,  float)
+READ1_FUNC(df, double)
+
+int sox_readchars(sox_format_t * ft, char * chars, sox_size_t len)
+{
+  size_t ret = sox_readbuf(ft, chars, len);
+  if (ret == len)
+    return SOX_SUCCESS;
+  if (!sox_error(ft))
+    sox_fail_errno(ft, errno, premature_eof);
+  return SOX_EOF;
+}
+
 /* N.B. This macro doesn't work for unaligned types (e.g. 3-byte
    types). */
 #define WRITE_FUNC(type, size, ctype, twiddle) \
@@ -714,10 +740,10 @@
   }
 
 /* Pack a 3-byte value to a uint8_t * */
-#define sox_pack3(p, v) \
-  (p)[0] = v & 0xff; \
-  (p)[1] = (v >> 8) & 0xff; \
-  (p)[2] = (v >> 16) & 0xff;
+#define sox_pack3(p, v) do {if (ft->encoding.reverse_bytes == SOX_IS_BIGENDIAN)\
+{(p)[0] = v & 0xff; (p)[1] = (v >> 8) & 0xff; (p)[2] = (v >> 16) & 0xff;} else \
+{(p)[2] = v & 0xff; (p)[1] = (v >> 8) & 0xff; (p)[0] = (v >> 16) & 0xff;} \
+} while (0)
 
 /* This (slower) macro works for unaligned types (e.g. 3-byte types)
    that need to be packed. */
@@ -727,11 +753,8 @@
   { \
     sox_size_t n, nwritten; \
     uint8_t *data = xmalloc(size * len); \
-    for (n = 0; n < len; n++) { \
-      ctype datum = buf[n]; \
-      twiddle(datum, type); \
-      sox_pack ## size(data + n * size, datum); \
-    } \
+    for (n = 0; n < len; n++) \
+      sox_pack ## size(data + n * size, buf[n]); \
     nwritten = sox_writebuf(ft, data, len * size); \
     free(data); \
     return nwritten / size; \
@@ -768,8 +791,13 @@
 WRITE1U_FUNC(dw, uint32_t)
 WRITE1S_FUNC(b, uint8_t)
 WRITE1S_FUNC(w, uint16_t)
-WRITE1_FUNC(f, float)
 WRITE1_FUNC(df, double)
+
+int sox_writef(sox_format_t * ft, double datum)
+{
+  float f = datum;
+  return sox_write_f_buf(ft, &f, 1) == 1 ? SOX_SUCCESS : SOX_EOF;
+}
 
 /* N.B. The file (if any) may already have been deleted. */
 int sox_close(sox_format_t * ft)