shithub: sox

Download patch

ref: 35d8af3c8e61c8184955f8d953f8996954c7c63f
parent: 4c7a8b4bfd9d4c7d117d33a2322a42ee04cc4d92
author: robs <robs>
date: Sun Sep 13 11:25:22 EDT 2009

32-bit alsa

--- a/src/alsa.c
+++ b/src/alsa.c
@@ -25,32 +25,48 @@
   int                format;
 } priv_t;
 
-static const int bytes_size[] = {1, 2, 4}, encs[][3] = {
-  {SND_PCM_FORMAT_S8, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_S24},
-  {SND_PCM_FORMAT_U8, SND_PCM_FORMAT_U16, SND_PCM_FORMAT_U24}};
 #define NBYTES bytes_size[(ft->encoding.bits_per_sample >> 3) - 1]
+#define NSIZES array_length(bytes_size)
 
-static int select_format(sox_encoding_t * e, unsigned * bits, snd_pcm_format_mask_t const * mask, int * format)
+static const int bytes_size[] = {1, 2, 4, 4}, formats[][NSIZES] = {
+    {SND_PCM_FORMAT_S8, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_S24,
+         SND_PCM_FORMAT_S32},
+    {SND_PCM_FORMAT_U8, SND_PCM_FORMAT_U16, SND_PCM_FORMAT_U24,
+          SND_PCM_FORMAT_U32}};
+
+static int select_format(
+    sox_encoding_t              * encoding_,
+    unsigned                    * nbits_,
+    snd_pcm_format_mask_t const * mask,
+    int                         * format)
 {
-  unsigned does[3], i, j, k = (*bits >> 3) - 1;
-  
-  if (k > 2 || (*e != SOX_ENCODING_SIGN2 && *e != SOX_ENCODING_UNSIGNED)) {
-    lsx_warn("invalid encoding; trying 24-bit signed");
-    *bits = 24;
-    *e = SOX_ENCODING_SIGN2;
-    k = 2;
+  unsigned can_do[NSIZES], i, j, index = (*nbits_ >> 3) - 1, nbits;
+  sox_encoding_t encoding = *encoding_;
+
+  for (i = 0; i < NSIZES; ++i) for (can_do[i] = 0, j = 0; j < 2; ++j)
+    can_do[i] |= snd_pcm_format_mask_test(mask, formats[j][i]);
+
+  if (index >= NSIZES ||
+      (encoding != SOX_ENCODING_SIGN2 && encoding != SOX_ENCODING_UNSIGNED)){
+    encoding = SOX_ENCODING_SIGN2;
+    index = 2;
   }
-  for (i = 0; i < 3; ++i) for (does[i] = 0, j = 0; j < 2; ++j)
-    does[i] |= snd_pcm_format_mask_test(mask, encs[j][i]);
-  if (!does[k])
-    k = 1;
-  while (!does[k]) if ((k = (k + 1 ) % 3) == 1)
-    return -1;
-  *bits = (k + 1) << 3;
+  while (!can_do[index]) if (++index == NSIZES)           /* Search up */
+    for (--index; !can_do[index];) if (--index >= NSIZES) /* then down */
+      return -1;
+  nbits = (index + 1) << 3;
 
-  if (*e == SOX_ENCODING_SIGN2 && !snd_pcm_format_mask_test(mask, encs[0][k]))
-    *e = SOX_ENCODING_UNSIGNED;
-  *format = encs[*e == SOX_ENCODING_UNSIGNED][k];
+  if (encoding == SOX_ENCODING_SIGN2 &&
+      !snd_pcm_format_mask_test(mask, formats[0][index]))
+    encoding = SOX_ENCODING_UNSIGNED;
+
+  if (*nbits_ != nbits || *encoding_ != encoding) {
+    lsx_warn("can't encode %u-bit %s", *nbits_,
+        sox_encodings_info[*encoding_].desc);
+    *nbits_ = nbits;
+    *encoding_ = encoding;
+  }
+  *format = formats[encoding == SOX_ENCODING_UNSIGNED][index];
   return 0;
 }
 
@@ -179,7 +195,17 @@
         while (i--) *buf++ = SOX_UNSIGNED_24BIT_TO_SAMPLE(*buf1++,);
         break;
       }
-      default: lsx_fail_errno(ft, SOX_EFMT, "invalid format");
+      case SND_PCM_FORMAT_S32: {
+        int32_t * buf1 = (int32_t *)p->buf;
+        while (i--) *buf++ = SOX_SIGNED_32BIT_TO_SAMPLE(*buf1++,);
+        break;
+      }
+      case SND_PCM_FORMAT_U32: {
+        uint32_t * buf1 = (uint32_t *)p->buf;
+        while (i--) *buf++ = SOX_UNSIGNED_32BIT_TO_SAMPLE(*buf1++,);
+        break;
+      }
+     default: lsx_fail_errno(ft, SOX_EFMT, "invalid format");
         return 0;
     }
   }
@@ -232,6 +258,16 @@
         while (i--) *buf1++ = SOX_SAMPLE_TO_UNSIGNED_24BIT(*buf++, ft->clips);
         break;
       }
+      case SND_PCM_FORMAT_S32: {
+        int32_t * buf1 = (int32_t *)p->buf;
+        while (i--) *buf1++ = SOX_SAMPLE_TO_SIGNED_32BIT(*buf++, ft->clips);
+        break;
+      }
+      case SND_PCM_FORMAT_U32: {
+        uint32_t * buf1 = (uint32_t *)p->buf;
+        while (i--) *buf1++ = SOX_SAMPLE_TO_UNSIGNED_32BIT(*buf++, ft->clips);
+        break;
+      }
     }
     for (i = 0; i < n; i += actual * ft->signal.channels) do {
       actual = snd_pcm_writei(
@@ -270,7 +306,9 @@
 {
   static char const * const names[] = {"alsa", NULL};
   static unsigned const write_encodings[] = {
-    SOX_ENCODING_SIGN2, 24, 16, 8, 0, SOX_ENCODING_UNSIGNED, 24, 16, 8, 0, 0};
+    SOX_ENCODING_SIGN2   , 32, 24, 16, 8, 0,
+    SOX_ENCODING_UNSIGNED, 32, 24, 16, 8, 0,
+    0};
   static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
     "Advanced Linux Sound Architecture device driver",
     names, SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,