[io] sink_sndfile: try guessing format according to file extension
authorPaul Brossier <piem@piem.org>
Tue, 18 Dec 2018 12:01:35 +0000 (13:01 +0100)
committerPaul Brossier <piem@piem.org>
Tue, 18 Dec 2018 12:01:35 +0000 (13:01 +0100)
src/io/sink_sndfile.c
src/io/sink_sndfile.h

index 35e2215..9427752 100644 (file)
@@ -48,10 +48,15 @@ struct _aubio_sink_sndfile_t {
   SNDFILE *handle;
   uint_t scratch_size;
   smpl_t *scratch_data;
+  int format;
 };
 
 uint_t aubio_sink_sndfile_open(aubio_sink_sndfile_t *s);
 
+uint_t aubio_str_extension_matches(const char_t *ext,
+    const char_t *pattern);
+const char_t *aubio_str_get_extension(const char_t *filename);
+
 aubio_sink_sndfile_t * new_aubio_sink_sndfile(const char_t * path, uint_t samplerate) {
   aubio_sink_sndfile_t * s = AUBIO_NEW(aubio_sink_sndfile_t);
   s->max_size = MAX_SIZE;
@@ -67,6 +72,8 @@ aubio_sink_sndfile_t * new_aubio_sink_sndfile(const char_t * path, uint_t sample
   s->samplerate = 0;
   s->channels = 0;
 
+  aubio_sink_sndfile_preset_format(s, aubio_str_get_extension(path));
+
   // zero samplerate given. do not open yet
   if ((sint_t)samplerate == 0) {
     return s;
@@ -115,6 +122,28 @@ uint_t aubio_sink_sndfile_preset_channels(aubio_sink_sndfile_t *s, uint_t channe
   return AUBIO_OK;
 }
 
+uint_t aubio_sink_sndfile_preset_format(aubio_sink_sndfile_t *s,
+    const char_t *fmt)
+{
+  if (aubio_str_extension_matches(fmt, "wav")) {
+    s->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+  } else if (aubio_str_extension_matches(fmt, "aiff")) {
+    s->format = SF_FORMAT_AIFF | SF_FORMAT_PCM_16;
+  } else if (aubio_str_extension_matches(fmt, "flac")) {
+    s->format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
+  } else if (aubio_str_extension_matches(fmt, "ogg")) {
+    s->format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
+  } else if (atoi(fmt) > 0x010000) {
+    s->format = atoi(fmt);
+  } else {
+    AUBIO_WRN("sink_sndfile: could not guess format for %s,"
+       " using default (wav)\n", s->path);
+    s->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+    return AUBIO_FAIL;
+  }
+  return AUBIO_OK;
+}
+
 uint_t aubio_sink_sndfile_get_samplerate(const aubio_sink_sndfile_t *s)
 {
   return s->samplerate;
@@ -131,7 +160,7 @@ uint_t aubio_sink_sndfile_open(aubio_sink_sndfile_t *s) {
   AUBIO_MEMSET(&sfinfo, 0, sizeof (sfinfo));
   sfinfo.samplerate = s->samplerate;
   sfinfo.channels   = s->channels;
-  sfinfo.format     = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
+  sfinfo.format     = s->format;
 
   /* try creating the file */
   s->handle = sf_open (s->path, SFM_WRITE, &sfinfo);
index 083c4ca..d12ff55 100644 (file)
@@ -95,6 +95,39 @@ uint_t aubio_sink_sndfile_preset_channels(aubio_sink_sndfile_t *s, uint_t channe
 
 /**
 
+  preset sink format
+
+  \param s sink, created with ::new_aubio_sink_sndfile
+  \param fmt format of the file to create
+
+  \return 0 on success, 1 on error
+
+  Preset the format of the sink. Supported format strings:
+   - "wav": 16 bit (default)
+   - "aiff": aiff, 16 bit
+   - "flac": flac, 16 bit
+   - "ogg": ogg vorbis stream
+
+  Alternatively, any sndfile format can be set by passing the corresponding
+  integer as a string:
+
+  \code{.c}
+  char_t fmt[10];
+  snprintf(fmt, sizeof(fmt), "%d", SF_FORMAT_FLAC | SF_FORMAT_PCM_24);
+  aubio_sink_sndfile_preset_format(s, fmt);
+  \endcode
+
+  The file should have been created using a samplerate of 0.
+
+  This function should be called before aubio_sink_sndfile_preset_samplerate()
+  and aubio_sink_sndfile_preset_channels().
+
+*/
+uint_t aubio_sink_sndfile_preset_format(aubio_sink_sndfile_t *s,
+        const char_t* fmt);
+
+/**
+
   get samplerate of sink object
 
   \param s sink object, created with ::new_aubio_sink_sndfile