shithub: sox

Download patch

ref: 82c6af3daeec9110f1ac43c0590df7a053b46499
parent: 2974df2573c875e2bf095804a8480466091665c7
author: rrt <rrt>
date: Mon Jan 22 18:47:37 EST 2007

Guess output subtype for writing files.

--- a/src/sndfile.c
+++ b/src/sndfile.c
@@ -48,8 +48,7 @@
   sf->sf_info = (SF_INFO *)xcalloc(1, sizeof(SF_INFO));
   /* We'd like to use sf_open, but auto file typing has already
      invoked stdio buffering. */
-  /* FIXME: Cope with raw files too: if format parameters are set,
-     assume file is raw. */
+  /* FIXME: If format parameters are set, assume file is raw. */
   if ((sf->sf_file = sf_open(ft->filename, SFM_READ, sf->sf_info)) == NULL) {
     st_fail("sndfile cannot open file for reading: %s %x", sf_strerror(sf->sf_file), sf->sf_info->format);
     free(sf->sf_file);
@@ -147,17 +146,70 @@
   return 0;
 }
 
+/* Make libsndfile subtype from sample encoding and size */
+static int sndfile_format(int encoding, int size)
+{
+  if (encoding < ST_ENCODING_SIZE_IS_WORD) {
+    switch (encoding) {
+    case ST_ENCODING_ULAW:
+      return SF_FORMAT_ULAW;
+    case ST_ENCODING_ALAW:
+      return SF_FORMAT_ALAW;
+    case ST_ENCODING_ADPCM:
+    case ST_ENCODING_MS_ADPCM:
+      return SF_FORMAT_MS_ADPCM;
+    case ST_ENCODING_IMA_ADPCM:
+      return SF_FORMAT_IMA_ADPCM;
+    case ST_ENCODING_OKI_ADPCM:
+      return SF_FORMAT_VOX_ADPCM;
+    default: /* Should be impossible */
+      return 0;
+    }
+  } else {
+    switch (encoding) {
+    case ST_ENCODING_UNSIGNED:
+      if (size == ST_SIZE_8BIT)
+        return SF_FORMAT_PCM_U8;
+      else
+        return 0;
+    case ST_ENCODING_SIGN2:
+    case ST_ENCODING_MP3:
+    case ST_ENCODING_VORBIS:
+    case ST_ENCODING_FLAC:
+      switch (size) {
+      case ST_SIZE_8BIT:
+        return SF_FORMAT_PCM_S8;
+      case ST_SIZE_16BIT:
+        return SF_FORMAT_PCM_16;
+      case ST_SIZE_24BIT:
+        return SF_FORMAT_PCM_24;
+      case ST_SIZE_32BIT:
+        return SF_FORMAT_PCM_32;
+      default: /* invalid size */
+        return 0;
+      }
+      break;
+    case ST_ENCODING_FLOAT:
+      return SF_FORMAT_FLOAT;
+    case ST_ENCODING_GSM:
+      return SF_FORMAT_GSM610;
+    default: /* Bad encoding */
+      return 0;
+    }
+  }
+}
+
 int st_sndfile_startwrite(ft_t ft)
 {
   sndfile_t sf = (sndfile_t)ft->priv;
+  int subtype = sndfile_format(ft->signal.encoding, ft->signal.size);
   sf->sf_info = (SF_INFO *)xmalloc(sizeof(SF_INFO));
 
   /* Copy format info */
-  /* FIXME: Need to have a table of suitable default subtypes */
   if (strcmp(ft->filetype, "sndfile") == 0)
-    sf->sf_info->format = name_to_format(ft->filename) | SF_FORMAT_PCM_16;
+    sf->sf_info->format = name_to_format(ft->filename) | subtype;
   else
-    sf->sf_info->format = name_to_format(ft->filetype) | SF_FORMAT_PCM_16;
+    sf->sf_info->format = name_to_format(ft->filetype) | subtype;
   sf->sf_info->samplerate = ft->signal.rate;
   sf->sf_info->channels = ft->signal.channels;
   sf->sf_info->frames = ft->length / ft->signal.channels;