shithub: aubio

Download patch

ref: 18c6b2020965ecbc48929cdb56451968fd6c4750
parent: ab7d1002918618b57d1741e4bcdbea6c73a27c38
author: Paul Brossier <piem@piem.org>
date: Mon Jul 16 08:19:31 EDT 2012

src/io/source_sndfile.c: improve resampling, clarify

--- a/src/io/source_sndfile.c
+++ b/src/io/source_sndfile.c
@@ -33,25 +33,31 @@
 
 #define MAX_CHANNELS 6
 #define MAX_SIZE 4096
+#define MAX_SAMPLES MAX_CHANNELS * MAX_SIZE
 
 struct _aubio_source_sndfile_t {
   uint_t hop_size;
   uint_t samplerate;
   uint_t channels;
+
+  // some data about the file
+  char_t *path;
+  SNDFILE *handle;
   int input_samplerate;
   int input_channels;
   int input_format;
-  char_t *path;
-  SNDFILE *handle;
-  uint_t scratch_size;
-  smpl_t *scratch_data;
 
+  // resampling stuff
   smpl_t ratio;
-
+  uint_t input_hop_size;
 #ifdef HAVE_SAMPLERATE
   aubio_resampler_t *resampler;
-  fvec_t *resampled_data;
+  fvec_t *input_data;
 #endif /* HAVE_SAMPLERATE */
+
+  // some temporary memory for sndfile to write at
+  uint_t scratch_size;
+  smpl_t *scratch_data;
 };
 
 aubio_source_sndfile_t * new_aubio_source_sndfile(char_t * path, uint_t samplerate, uint_t hop_size) {
@@ -75,68 +81,72 @@
   if (s->handle == NULL) {
     /* show libsndfile err msg */
     AUBIO_ERR("Failed opening %s: %s\n", s->path, sf_strerror (NULL));
-    return NULL;
+    goto beach;
   }	
 
-  if (sfinfo.channels > MAX_CHANNELS) {
-    AUBIO_ERR("Not able to process more than %d channels\n", MAX_CHANNELS);
-    return NULL;
-  }
-
   /* get input specs */
   s->input_samplerate = sfinfo.samplerate;
   s->input_channels   = sfinfo.channels;
   s->input_format     = sfinfo.format;
 
+  /* compute input block size required before resampling */
   s->ratio = s->samplerate/(float)s->input_samplerate;
+  s->input_hop_size = (uint_t)FLOOR(s->hop_size / s->ratio + .5);
 
-  if (s->ratio != 1) {
+  if (s->input_hop_size * s->input_channels > MAX_SAMPLES) {
+    AUBIO_ERR("Not able to process more than %d frames of %d channels\n",
+        MAX_SAMPLES / s->input_channels, s->input_channels);
+    goto beach;
+  }
+
 #ifdef HAVE_SAMPLERATE
+  s->resampler = NULL;
+  s->input_data = NULL;
+  if (s->ratio != 1) {
+    s->input_data = new_fvec(s->input_hop_size);
     s->resampler = new_aubio_resampler(s->ratio, 0);
-    s->resampled_data = new_fvec(s->hop_size / s->ratio);
     if (s-> ratio > 1) {
-      AUBIO_WRN("upsampling from %d to % d\n", s->input_samplerate, s->samplerate);
+      AUBIO_WRN("upsampling %s from %d to % d\n", s->path, s->input_samplerate, s->samplerate);
     }
+  }
 #else
-    AUBIO_ERR("can not read %s at samplerate %dHz\n", s->path, s->samplerate);
+  if (s->ratio != 1) {
     AUBIO_ERR("aubio was compiled without aubio_resampler\n");
-    return NULL;
-#endif /* HAVE_SAMPLERATE */
+    goto beach;
   }
+#endif /* HAVE_SAMPLERATE */
 
-  s->scratch_size = s->hop_size * s->input_channels / s->ratio;
   /* allocate data for de/interleaving reallocated when needed. */
-  if (s->scratch_size >= MAX_SIZE * MAX_CHANNELS) {
-    AUBIO_ERR("%d x %d exceeds maximum aubio_source_sndfile buffer size %d\n",
-        s->hop_size, s->input_channels, MAX_CHANNELS * MAX_CHANNELS);
-    return NULL;
-  }
+  s->scratch_size = s->input_hop_size * s->input_channels;
   s->scratch_data = AUBIO_ARRAY(float,s->scratch_size);
 
   return s;
+
+beach:
+  AUBIO_ERR("can not read %s at samplerate %dHz with hop_size of %d\n",
+      s->path, s->samplerate, s->hop_size);
+  del_aubio_source_sndfile(s);
+  return NULL;
 }
 
 void aubio_source_sndfile_do(aubio_source_sndfile_t * s, fvec_t * read_data, uint_t * read){
-  sf_count_t read_frames;
-  int i,j, input_channels = s->input_channels;
-  int aread;
+  uint_t i,j, input_channels = s->input_channels;
   /* do actual reading */
-  read_frames = sf_read_float (s->handle, s->scratch_data, s->scratch_size);
+  sf_count_t read_samples = sf_read_float (s->handle, s->scratch_data, s->scratch_size);
 
   smpl_t *data;
 
 #ifdef HAVE_SAMPLERATE
-  if (s->resampler) {
-    data = s->resampled_data->data;
+  if (s->ratio != 1) {
+    data = s->input_data->data;
   } else
 #endif /* HAVE_SAMPLERATE */
   {
     data = read_data->data;
   }
-  aread = (int)FLOOR(s->ratio * read_frames / (float)input_channels + .5);
 
   /* de-interleaving and down-mixing data  */
-  for (j = 0; j < read_frames; j++) {
+  for (j = 0; j < read_samples / input_channels; j++) {
     data[j] = 0;
     for (i = 0; i < input_channels; i++) {
       data[j] += (smpl_t)s->scratch_data[input_channels*j+i];
@@ -146,12 +156,11 @@
 
 #ifdef HAVE_SAMPLERATE
   if (s->resampler) {
-    aubio_resampler_do(s->resampler, s->resampled_data, read_data);
-    data = s->resampled_data->data;
+    aubio_resampler_do(s->resampler, s->input_data, read_data);
   }
 #endif /* HAVE_SAMPLERATE */
 
-  *read = aread;
+  *read = (int)FLOOR(s->ratio * read_samples / input_channels + .5);
 }
 
 void del_aubio_source_sndfile(aubio_source_sndfile_t * s){
@@ -160,11 +169,11 @@
     AUBIO_ERR("Error closing file %s: %s", s->path, sf_strerror (NULL));
   }
 #ifdef HAVE_SAMPLERATE
-  if (s->resampler) {
+  if (s->resampler != NULL) {
     del_aubio_resampler(s->resampler);
   }
-  if (s->resampled_data) {
-    del_fvec(s->resampled_data);
+  if (s->input_data) {
+    del_fvec(s->input_data);
   }
 #endif /* HAVE_SAMPLERATE */
   AUBIO_FREE(s->scratch_data);