shithub: sox

Download patch

ref: 16fe5d505991945d595eb344600996cf291482b9
parent: ccae7ed955ff10cf4b08b06bcea9d892b950e7f4
author: cbagwell <cbagwell>
date: Sat Oct 23 20:45:18 EDT 2004

more overriding of unsupported formats.

--- a/Changelog
+++ b/Changelog
@@ -10,6 +10,9 @@
     and patches for sunaudio driver on openbsd.
   o Default volume for soxmix wrongly set to 0 instead
     of 1/#_input_files (float rounding error).
+  o Update to ALSA driver to do a better job of detecting
+    unsupported sample rate/size/encoding and change to
+    a supported one.
   o Guentcho Skordev pointed out ogg vorbis files were using
     the same value for serial numbers each time.
 
--- a/Makefile.in
+++ b/Makefile.in
@@ -35,7 +35,7 @@
 	$(srcdir)/mkinstalldirs $(mandir)/man1
 	$(INSTALL) -c -m 644 $(srcdir)/sox.1 $(mandir)/man1
 	if [ -f $(mandir)/man1/soxmix.1 ] ; then $(RM) $(mandir)/man1/soxmix.1; fi
-	cd $(mandir)/man && $(LN_S) sox.1 soxmix.1
+	cd $(mandir)/man1 && $(LN_S) sox.1 soxmix.1
 	$(INSTALL) -c -m 644 $(srcdir)/soxexam.1 $(mandir)/man1
 
 install-play:
--- a/src/alsa.c
+++ b/src/alsa.c
@@ -233,10 +233,11 @@
         st_fail_errno(ft,ST_ENOMEM,"unable to allocate output buffer of size %d", ft->file.size);
         return(ST_EOF);
     }
-    if (ft->info.rate < a_info.min_rate) ft->info.rate = 2 * a_info.min_rate;
+    if (ft->info.rate < a_info.min_rate) ft->info.rate = a_info.min_rate;
     else if (ft->info.rate > a_info.max_rate) ft->info.rate = a_info.max_rate;
     if (ft->info.channels == -1) ft->info.channels = a_info.min_channels;
     else if (ft->info.channels > a_info.max_channels) ft->info.channels = a_info.max_channels;
+    else if (ft->info.channels < a_info.min_channels) ft->info.channels = a_info.min_channels;
     if (get_format(ft, a_info.formats, &fmt) < 0)
         return (ST_EOF);
 
@@ -282,10 +283,11 @@
         st_fail_errno(ft,ST_ENOMEM,"unable to allocate output buffer of size %d", ft->file.size);
         return(ST_EOF);
     }
-    if (ft->info.rate < a_info.min_rate) ft->info.rate = 2 * a_info.min_rate;
+    if (ft->info.rate < a_info.min_rate) ft->info.rate = a_info.min_rate;
     else if (ft->info.rate > a_info.max_rate) ft->info.rate = a_info.max_rate;
     if (ft->info.channels == -1) ft->info.channels = a_info.min_channels;
     else if (ft->info.channels > a_info.max_channels) ft->info.channels = a_info.max_channels;
+    else if (ft->info.channels < a_info.min_channels) ft->info.channels = a_info.min_channels;
     if (get_format(ft, a_info.formats, &fmt) < 0)
         return (ST_EOF);
 
@@ -586,9 +588,7 @@
 
 #define EMSGFMT "ALSA driver does not support %s %s output"
 
-static int get_format(ft, formats, fmt)
-ft_t ft;
-int formats, *fmt;
+static int get_format(ft_t ft, int formats, int *fmt)
 {
     if (ft->info.size == -1) {
         if ((formats & SND_PCM_FMT_U8) || (formats & SND_PCM_FMT_S8))
@@ -596,16 +596,64 @@
         else
             ft->info.size = ST_SIZE_WORD;
     }
-    if (ft->info.encoding == -1) {
-        if ((formats & SND_PCM_FMT_S16) || (formats & SND_PCM_FMT_S8))
-            ft->info.encoding = ST_ENCODING_SIGN2;
-        else
-            ft->info.encoding = ST_ENCODING_UNSIGNED;
+    if (ft->info.size != ST_SIZE_BYTE && ft->info.size != ST_SIZE_WORD)
+    {
+        st_report("ALSA drive doesn't support %s.  Changin to 16-bits.", 
+                  st_sizes_str[(unsigned char)ft->info.encoding]);
+        ft->info.size = ST_SIZE_WORD;
     }
+    
+    /* Some hardware only wants to work with 8-bit or 16-bit data */
+    if (ft->info.size == ST_SIZE_BYTE)
+    {
+        if (!(formats & SND_PCM_FMT_U8) && !(formats & SND_PCM_FMT_S8))
+        {
+            st_report("ALSA driver doesn't supported byte samples.  Changing to words.");
+            ft->info.size = ST_SIZE_WORD;
+        }
+    }
+    else if (ft->info.size == ST_SIZE_WORD)
+    {
+        if (!(formats & SND_PCM_FMT_U16) && !(formats & SND_PCM_FMT_S16))
+        {
+            st_report("ALSA driver doesn't supported word samples.  Changing to bytes.");
+            ft->info.size = ST_SIZE_BYTE;
+        }
+    }
     if (ft->info.size == ST_SIZE_BYTE) {
         switch (ft->info.encoding)
         {
             case ST_ENCODING_SIGN2:
+                if (!(formats & SND_PCM_FMT_S8))
+                {
+                    st_report("ALSA driver doesn't supported signed byte samples.  Changing to unsigned bytes.");
+                    ft->info.encoding = ST_ENCODING_SIGN2;
+                }
+                break;
+            case ST_ENCODING_UNSIGNED:
+                if (!(formats & SND_PCM_FMT_U8))
+                {
+                    st_report("ALSA driver doesn't supported unsigned byte samples.  Changing to signed bytes.");
+                    ft->info.encoding = ST_ENCODING_UNSIGNED;
+                }
+                break;
+            default:
+                if (formats & SND_PCM_FMT_S8)
+                {
+                    st_report("ALSA drive doesn't support %s %s.  Changing to signed bytes.", 
+                            st_encodings_str[(unsigned char)ft->info.encoding], "byte");
+                    ft->info.encoding = ST_ENCODING_SIGN2;
+                }
+                else
+                {
+                    st_report("ALSA drive doesn't support %s %s.  Changing to unsigned bytes.", 
+                              st_encodings_str[(unsigned char)ft->info.encoding], "byte");
+                    ft->info.encoding = ST_ENCODING_UNSIGNED;
+                }
+        }
+        switch (ft->info.encoding)
+        {
+            case ST_ENCODING_SIGN2:
                 if (!(formats & SND_PCM_FMT_S8)) {
                     st_fail_errno(ft,ST_EFMT,"ALSA driver does not support signed byte samples");
                     return ST_EOF;
@@ -619,10 +667,6 @@
                 }
                 *fmt = SND_PCM_SFMT_U8;
                 break;
-            default:
-                st_fail_errno(ft,ST_EFMT,EMSGFMT,st_encodings_str[(unsigned char)ft->info.encoding],"byte");
-                return ST_EOF;
-                break;
         }
     }
     else if (ft->info.size == ST_SIZE_WORD) {
@@ -630,6 +674,26 @@
         {
             case ST_ENCODING_SIGN2:
                 if (!(formats & SND_PCM_FMT_S16)) {
+                    st_report("ALSA driver does not support signed word samples.  Changing to unsigned words.");
+                    ft->info.encoding = ST_ENCODING_UNSIGNED;
+                }
+                break;
+            case ST_ENCODING_UNSIGNED:
+                if (!(formats & SND_PCM_FMT_U16)) {
+                    st_report("ALSA driver does not support unsigned word samples.  Changing to signed words.");
+                    ft->info.encoding = ST_ENCODING_SIGN2;
+                }
+                break;
+            default:
+                st_report("ALSA drive doesn't support %s %s.  Changin to signed words.", 
+                        st_encodings_str[(unsigned char)ft->info.encoding], "byte");
+                ft->info.encoding = ST_ENCODING_SIGN2;
+                break;
+        }
+        switch (ft->info.encoding)
+        {
+            case ST_ENCODING_SIGN2:
+                if (!(formats & SND_PCM_FMT_S16)) {
                     st_fail_errno(ft,ST_EFMT,"ALSA driver does not support signed word samples");
                     return ST_EOF;
                 }
@@ -641,10 +705,6 @@
                     return ST_EOF;
                 }
                 *fmt = SND_PCM_SFMT_U16_LE;
-                break;
-            default:
-                st_fail_errno(ft,ST_EFMT,EMSGFMT,st_encodings_str[(unsigned char)ft->info.encoding],"word");
-                return ST_EOF;
                 break;
         }
     }