shithub: sox

Download patch

ref: 269fe345e41fbff0ef56c8095e3f1d752517345c
parent: 7cfe6fdb10ec6fe6cb9c7e80b28df0ed9abfd1e5
author: cbagwell <cbagwell>
date: Wed Jan 31 12:20:43 EST 2001

Change OSS code to query driver for supported formats instead of guessing.

--- a/src/oss.c
+++ b/src/oss.c
@@ -43,12 +43,11 @@
 static int ossdspinit(ft)
 ft_t ft;
 {
-    int sampletype=AFMT_U8, samplesize=8, dsp_stereo;
+    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;
@@ -61,10 +60,7 @@
 	}
     }
     else if (ft->info.size == ST_SIZE_WORD) {
-	if (ST_IS_BIGENDIAN)
-	    sampletype = AFMT_S16_BE;
-	else
-	    sampletype = AFMT_S16_LE;
+	sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
 	samplesize = 16;
 	if (ft->info.encoding == -1)
 	    ft->info.encoding = ST_ENCODING_SIGN2;
@@ -75,6 +71,8 @@
 	}
     }
     else {
+	sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
+	samplesize = 16;
         ft->info.size = ST_SIZE_WORD;
 	ft->info.encoding = ST_ENCODING_SIGN2;
 	st_report("OSS driver only supports bytes and words");
@@ -95,101 +93,51 @@
 	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.
+    /* Query the supported formats and find the best match
      */
-    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)
+    rc = ioctl(fileno(ft->fp), SNDCTL_DSP_GETFMTS, &tmp);
+    if (rc == 0) {
+    	if ((tmp & sampletype) == 0)
 	{
-	    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)
+	    /* is 16-bit supported? */
+	    if (samplesize == 16 && (tmp & (AFMT_S16_LE|AFMT_S16_BE)) == 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);
+		ft->info.size = ST_SIZE_BYTE;
+		ft->info.encoding = ST_ENCODING_UNSIGNED;
+		st_report("OSS driver doesn't like signed words");
+		st_report("Forcing to unsigned bytes");
+		tmp = sampletype = AFMT_U8;
+		samplesize = 8;
 	    }
-	    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_SIGN2;
-	    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)
+	    /* is 8-bit supported */
+	    else if (samplesize == 8 && (tmp & AFMT_U8) == 0)
 	    {
-	        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->info.size = ST_SIZE_WORD;
+		ft->info.encoding = ST_ENCODING_SIGN2;
+		st_report("OSS driver doesn't like unsigned bytes");
+		st_report("Forcing to signed words");
+		sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_BE : AFMT_S16_LE;
+		samplesize = 16;
+	    }
+	    /* determine which 16-bit format to use */
+	    if (samplesize == 16)
+	    {
+	    	if ((tmp & sampletype) == 0)
+		{
+		    sampletype = (ST_IS_BIGENDIAN) ? AFMT_S16_LE : AFMT_S16_BE;
 		    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);
-	}
+	tmp = sampletype;
+	rc = ioctl(fileno(ft->fp), SNDCTL_DSP_SETFMT, &tmp);
     }
-#else
-    /* Odd dumb interface */
-    tmp = samplesize;
-    if (ioctl(fileno(ft->fp), SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
+    /* Give up and exit */
+    if (rc < 0 || tmp != sampletype)
     {
 	st_fail("Unable to set the sample size to %d", samplesize);
 	return (ST_EOF);
-    }
-#endif
-
-    if (tmp != samplesize)
-    {
-	if (tmp == 16)
-	{
-	    st_warn("Sound card appears to only support singled word samples.  Overriding format");
-	    ft->info.size = ST_SIZE_WORD;
-	    ft->info.encoding = ST_ENCODING_SIGN2;
-	}
-	else if (tmp == 8)
-	{
-	    st_warn("Sound card appears to only support unsigned byte samples. Overriding format");
-	    ft->info.size = ST_SIZE_BYTE;
-	    ft->info.encoding = ST_ENCODING_UNSIGNED;
-	}
     }
 
     if (ft->info.channels == 2) dsp_stereo = 1;