shithub: sox

Download patch

ref: d75d78ae28fee905f82fb5d8b01aa57aaf0965d1
parent: 2ac72452933289412d3998810ba64627d4d2b5a4
author: cbagwell <cbagwell>
date: Thu Jan 25 17:45:10 EST 2001

Updating OSS driver to attempt to use multiple endian types if one fails.
Found some endian code that wasn't updated in a few handlers.

--- a/Changelog
+++ b/Changelog
@@ -27,6 +27,9 @@
     dropped under heavy CPU loads.  Moved GETBLKSIZE operation
     until after setting up the format (SBLive! was modify the block size
     after changing formats).
+  o With help from David Blythe, updated OSS drivers to use newer format
+    interface.  OSS driver will now attempt to detect a valid endian type
+    to use with sound card.
 
 sox-12.17.1
 -----------
--- a/src/oss.c
+++ b/src/oss.c
@@ -5,9 +5,8 @@
  * any purpose.  This copyright notice must be maintained.
  * Chris Bagwell And Sundry Contributors are not
  * responsible for the consequences of using this software.
- */
-
-/* Direct to Open Sound System (OSS) sound driver
+ *
+ * Direct to Open Sound System (OSS) sound driver
  * OSS is a popular unix sound driver for Intel x86 unices (eg. Linux)
  * and several other unixes (such as SunOS/Solaris).
  * This driver is compatible with OSS original source that was called
@@ -44,12 +43,13 @@
 static int ossdspinit(ft)
 ft_t ft;
 {
-    int samplesize = 8, dsp_stereo;
-    int tmp;
+    int sampletype, samplesize, dsp_stereo;
+    int tmp, rc;
 
     if (ft->info.rate == 0.0) ft->info.rate = 8000;
     if (ft->info.size == -1) ft->info.size = ST_SIZE_BYTE;
     if (ft->info.size == ST_SIZE_BYTE) {
+	sampletype = AFMT_U8;
 	samplesize = 8;
 	if (ft->info.encoding == -1)
 	    ft->info.encoding = ST_ENCODING_UNSIGNED;
@@ -60,6 +60,10 @@
 	}
     }
     else if (ft->info.size == ST_SIZE_WORD) {
+	if (ST_IS_BIGENDIAN)
+	    sampletype = AFMT_S16_BE;
+	else
+	    sampletype = AFMT_S16_LE;
 	samplesize = 16;
 	if (ft->info.encoding == -1)
 	    ft->info.encoding = ST_ENCODING_SIGN2;
@@ -90,6 +94,79 @@
 	return (ST_EOF);
     }
 
+#ifdef SNDCTL_DSP_SETFMT
+    tmp = sampletype;
+    rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SAMPLESIZE, &tmp);
+
+    /* If we are unable to set format type, then we should try a few
+     * other format that we can handle.
+     */
+    if (rc < 0)
+    {
+	/* If using 16-bits, the sound card may just prefer to use
+	 * an endian format different then the machine type.
+	 * Try swaping data endian.
+	 */
+	if (sampletype == AFMT_S16_LE || sampletype == AFMT_S16_BE)
+	{
+	    if (sampletype == AFMT_S16_LE)
+		sampletype = AFMT_S16_BE;
+	    else
+		sampletype = AFMT_S16_LE;
+
+            rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SAMPLESIZE, &tmp);
+	    if (rc < 0)
+	    {
+		/* Must not like 16-bits, try 8-bits */
+                ft->info.size = ST_SIZE_WORD;
+	        ft->info.encoding = ST_ENCODING_SIGN2;
+	        st_report("OSS driver doesn't like signed words");
+	        st_report("Forcing to unsigned bytes");
+	        sampletype = AFMT_U8;
+                rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SAMPLESIZE, &tmp);
+	    }
+	    else
+		/* That was successful so store that we need to swap */
+		ft->swap = ft->swap ? 0 : 1;
+
+	}
+	else
+	{
+            ft->info.size = ST_SIZE_WORD;
+	    ft->info.encoding = ST_ENCODING_SIGNED2;
+	    st_report("OSS driver doesn't like unsigned bytes");
+	    st_report("Forcing to signed words");
+            if (ST_IS_BIGENDIAN)
+		sampletype = AFMT_S16_BE;
+	    else
+	        sampletype = AFMT_S16_LE;
+
+            rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SAMPLESIZE, &tmp);
+
+	    /* If it doesn't like that, try swaping endians */
+	    if (sampletype == AFMT_S16_LE || sampletype == AFMT_S16_BE)
+	    {
+	        if (sampletype == AFMT_S16_LE)
+		    sampletype = AFMT_S16_BE;
+	        else
+		    sampletype = AFMT_S16_LE;
+
+                rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SAMPLESIZE, &tmp);
+		if (rc >= 0)
+		    /* That was successful so store that we need to swap */
+		    ft->swap = ft->swap ? 0 : 1;
+	    }
+
+	}
+	/* Give up and exit */
+	if (rc < 0)
+	{
+	    st_fail("Unable to set the sample size to %d", samplesize);
+	    return (ST_EOF);
+	}
+    }
+#else
+    /* Odd dumb interface */
     tmp = samplesize;
     if (ioctl(fileno(ft->fp), SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
     {
@@ -96,6 +173,7 @@
 	st_fail("Unable to set the sample size to %d", samplesize);
 	return (ST_EOF);
     }
+#endif
 
     if (tmp != samplesize)
     {
--- a/src/sf.c
+++ b/src/sf.c
@@ -139,8 +139,6 @@
 	SFHEADER sfhead;
 	SFCODE *sfcodep;
 	char *sfcharp;
-	int littlendian = 1;
-	char *endptr;
 	int rc;
 
 	/* Needed for rawwrite() */
@@ -151,14 +149,13 @@
 	sf->info.magic_union._magic_bytes.sf_magic1 = SF_MAGIC1;
 	sf->info.magic_union._magic_bytes.sf_magic2 = SF_MAGIC2;
 	sf->info.magic_union._magic_bytes.sf_param = 0;
-	/* computer musicians can't code worth a damn */
-	/* you don't see this kind of junk in any other format */
-	endptr = (char *) &littlendian;
-	*endptr = 1;
-	if (littlendian == 1)
-		sf->info.magic_union._magic_bytes.sf_machine = SF_VAX;
+
+	/* This file handler can handle both big and little endian data */
+	if (ST_IS_LITTLEENDIAN)
+	    sf->info.magic_union._magic_bytes.sf_machine = SF_VAX;
 	else
-		sf->info.magic_union._magic_bytes.sf_machine = SF_SUN;
+	    sf->info.magic_union._magic_bytes.sf_machine = SF_SUN;
+
 	sf->info.sf_srate = ft->info.rate;
 	if (ft->info.size == ST_SIZE_FLOAT) {
 		sf->info.sf_packmode = SF_FLOAT;
--- a/src/smp.c
+++ b/src/smp.c
@@ -183,8 +183,6 @@
 ft_t ft;
 {
 	smp_t smp = (smp_t) ft->priv;
-	int littlendian = 1;
-	char *endptr;
 	int i;
 	int namelen, commentlen;
 	LONG samplestart;
@@ -191,10 +189,9 @@
 	struct smpheader header;
 	struct smptrailer trailer;
 
-	endptr = (char *) &littlendian;
 	/* SMP is in Little Endian format.  Swap whats read in on */
 	/* Big Endian machines.			                  */
-	if (!*endptr)
+	if (ST_IS_LITTLEENDIAN)
 	{
 		ft->swap = ft->swap ? 0 : 1;
 	}
@@ -341,16 +338,12 @@
 int st_smpstartwrite(ft) 
 ft_t ft;
 {
-	int littlendian = 1;
-	char *endptr;
-
 	smp_t smp = (smp_t) ft->priv;
 	struct smpheader header;
 
-	endptr = (char *) &littlendian;
 	/* SMP is in Little Endian format.  Swap whats read in on */
 	/* Big Endian machines.			                  */
-	if (!*endptr)
+	if (ST_IS_LITTLEENDIAN)
 	{
 		ft->swap = ft->swap ? 0 : 1;
 	}
--- a/src/sndrtool.c
+++ b/src/sndrtool.c
@@ -142,8 +142,6 @@
 int st_sndrstartwrite(ft)
 ft_t ft;
 {
-	int littlendian = 1;
-	char *endptr;
 	int rc;
 
 	/* Needed for rawread() */
@@ -151,11 +149,10 @@
 	if (rc)
 	    return rc;
 
-	endptr = (char *) &littlendian;
 	/* sndr is in little endian format so
 	 * swap bytes on big endian machines
 	 */
-	if (!*endptr)
+	if (ST_IS_BIGENDIAN)
 	{
 		ft->swap = ft->swap ? 0 : 1;
 	}