src/spectral/phasevoc.c: improve, accept that hop_s == buf_s
authorPaul Brossier <piem@piem.org>
Sat, 22 Feb 2014 19:00:02 +0000 (16:00 -0300)
committerPaul Brossier <piem@piem.org>
Sat, 22 Feb 2014 19:00:02 +0000 (16:00 -0300)
src/spectral/phasevoc.c

index e1b3474..b83474a 100644 (file)
@@ -30,10 +30,10 @@ struct _aubio_pvoc_t {
   uint_t win_s;       /** grain length */
   uint_t hop_s;       /** overlap step */
   aubio_fft_t * fft;  /** fft object */
-  fvec_t * synth;     /** cur output grain [win_s] */
-  fvec_t * synthold;  /** last input frame [win_s-hop_s] */
-  fvec_t * data;      /** current input grain [win_s] */
-  fvec_t * dataold;   /** last input frame [win_s-hop_s] */
+  fvec_t * data;      /** current input grain, [win_s] frames */
+  fvec_t * dataold;   /** memory of past grain, [win_s-hop_s] frames */
+  fvec_t * synth;     /** current output grain, [win_s] frames */
+  fvec_t * synthold;  /** memory of past grain, [win_s-hop_s] frames */
   fvec_t * w;         /** grain window [win_s] */
 };
 
@@ -80,8 +80,8 @@ aubio_pvoc_t * new_aubio_pvoc (uint_t win_s, uint_t hop_s) {
   } else if (win_s < 1) {
     AUBIO_ERR("got buffer_size %d, but can not be < 2\n", win_s);
     goto beach;
-  } else if (win_s < hop_s + 1) {
-    AUBIO_ERR("hop size (%d) is larger than or equal to win size (%d)\n", win_s, hop_s);
+  } else if (win_s < hop_s) {
+    AUBIO_ERR("hop size (%d) is larger than win size (%d)\n", win_s, hop_s);
     goto beach;
   }
 
@@ -92,8 +92,13 @@ aubio_pvoc_t * new_aubio_pvoc (uint_t win_s, uint_t hop_s) {
   pv->synth    = new_fvec (win_s);
 
   /* new input output */
-  pv->dataold  = new_fvec  (win_s-hop_s);
-  pv->synthold = new_fvec (win_s-hop_s);
+  if (win_s > hop_s) {
+    pv->dataold  = new_fvec  (win_s-hop_s);
+    pv->synthold = new_fvec (win_s-hop_s);
+  } else {
+    pv->dataold  = new_fvec  (1);
+    pv->synthold = new_fvec (1);
+  }
   pv->w        = new_aubio_window ("hanningz", win_s);
 
   pv->hop_s    = hop_s;
@@ -140,17 +145,31 @@ static void aubio_pvoc_swapbuffers(smpl_t * data, smpl_t * dataold,
 static void aubio_pvoc_addsynth(const smpl_t * synth, smpl_t * synthold, 
                 smpl_t * synthnew, uint_t win_s, uint_t hop_s)
 {
-  uint_t i;
-  smpl_t scale = 2 * hop_s / (win_s + .0);
-  /* add new synth to old one and put result in synthnew */
+  uint_t i, start;
+  smpl_t scale = hop_s * 2. / win_s;
+
+  /* put new result in synthnew */
+  for (i = 0; i < hop_s; i++)
+    synthnew[i] = synth[i] * scale;
+  /* no overlap, nothing else to do */
+  if (win_s <= hop_s) return;
+
+  /* add new synth to old one and */
   for (i = 0; i < hop_s; i++)
-    synthnew[i] = synthold[i] + synth[i] * scale;
+    synthnew[i] += synthold[i];
+
   /* shift synthold */
-  for (i = 0; i < win_s - 2 * hop_s; i++)
-    synthold[i] = synthold[i + hop_s];
+  for (i = hop_s; i < win_s - hop_s; i++)
+    synthold[i - hop_s] = synthold[i];
+
+  /* more than 50% overlap, overlap anyway */
+  if (win_s < 2 * hop_s) start = 0;
+  /* less than 50% overlap, reset latest grain trail */
+  else start = win_s - hop_s - hop_s;
   /* erase last frame in synthold */
-  for (i = win_s - hop_s; i < win_s; i++)
-    synthold[i - hop_s] = 0.;
+  for (i = start; i < win_s - hop_s; i++)
+    synthold[i] = 0.;
+
   /* additive synth */
   for (i = 0; i < win_s - hop_s; i++)
     synthold[i] += synth[i + hop_s] * scale;