src/synth/sampler.c: clean-up, move first read in reading thread
authorPaul Brossier <piem@piem.org>
Sun, 9 Oct 2016 18:04:35 +0000 (20:04 +0200)
committerPaul Brossier <piem@piem.org>
Sun, 9 Oct 2016 18:04:35 +0000 (20:04 +0200)
src/synth/sampler.c

index 45efd11..adce8a0 100644 (file)
@@ -64,6 +64,7 @@ struct _aubio_sampler_t {
   // reading from a table
   aubio_ringbuffer_t *ring;
   uint_t perfectloop;
+  uint_t eof_remaining;
   fvec_t *samples;
   fmat_t *msamples;
   // reading from a source
@@ -150,9 +151,10 @@ aubio_sampler_t *new_aubio_sampler(uint_t blocksize, uint_t samplerate)
   // FIXME: perfectloop fails if source_blocksize > 2048 with source_avcodec
   //s->source_blocksize = 8192;
 
-  if (s->perfectloop || s->source_blocksize != s->blocksize) {
+  if (s->threaded_read || s->perfectloop)
     s->source_output = new_fvec(s->source_blocksize);
-    s->ring = new_aubio_ringbuffer(s->source_blocksize, s->blocksize);
+  if (s->perfectloop || s->source_blocksize != s->blocksize) {
+    s->ring = new_aubio_ringbuffer(s->source_blocksize * 2, s->blocksize);
   }
   //s->channels = 1;
   //s->source_moutput = new_fmat(s->source_blocksize, s->channels);
@@ -235,6 +237,7 @@ uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri )
     o->uri = uri;
     o->finished = 0;
     o->eof = 0;
+    o->eof_remaining = 0;
     o->opened = 1;
     ret = AUBIO_OK;
     AUBIO_MSG("sampler: loaded %s\n", uri);
@@ -249,11 +252,12 @@ uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri )
     o->uri = NULL;
     o->finished = 1;
     o->eof = 0;
+    o->eof_remaining = 0;
     o->opened = 0;
     AUBIO_WRN("sampler: failed loading %s\n", uri);
   }
   if (o->ring) {
-    AUBIO_WRN("sampler: resetting ringbuffer\n");
+    //AUBIO_WRN("sampler: resetting ringbuffer\n");
     aubio_ringbuffer_reset(o->ring);
   }
   return ret;
@@ -368,39 +372,6 @@ done:
   pthread_mutex_unlock(&p->read_mutex);
   pthread_exit(NULL);
 }
-
-void *aubio_sampler_readfn_ring(void *z) {
-  aubio_sampler_t *p = z;
-  while(1) {
-    pthread_mutex_lock(&p->read_mutex);
-    if (p->open_thread_running) {
-      //AUBIO_WRN("sampler: readfn(): file is being opened\n");
-      pthread_cond_signal(&p->read_avail);
-      //pthread_cond_wait(&p->read_request, &p->read_mutex);
-    } else if (p->opened && !p->started && !p->finished) {
-      //AUBIO_WRN("sampler: readfn(): file started\n");
-      p->available = aubio_sampler_pull_from_source(p);
-      if (p->available < (sint_t)p->source_blocksize)
-        aubio_sampler_do_eof(p);
-      pthread_cond_signal(&p->read_avail);
-      if (!p->finished) {
-        pthread_cond_wait(&p->read_request, &p->read_mutex);
-      }
-    } else {
-      //AUBIO_WRN("sampler: readfn(): idle?\n");
-      //pthread_cond_signal(&p->read_avail);
-      pthread_cond_wait(&p->read_request, &p->read_mutex);
-      if (p->read_thread_finish) {
-        goto done;
-      }
-    }
-    pthread_mutex_unlock(&p->read_mutex);
-  }
-done:
-  //AUBIO_WRN("sampler: exiting reading thread\n");
-  pthread_mutex_unlock(&p->read_mutex);
-  pthread_exit(NULL);
-}
 #endif
 
 void
@@ -412,8 +383,6 @@ aubio_sampler_read(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
   }
 }
 
-static void aubio_sampler_do_perfectloop(aubio_sampler_t *s);
-
 static void
 aubio_sampler_reading_from_source_naive(aubio_sampler_t *s, fvec_t * output,
     uint_t *read)
@@ -437,34 +406,33 @@ aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s) {
   uint_t available = 0;
   if (ring_avail < (sint_t)s->blocksize) {
     available = aubio_sampler_pull_from_source(s);
-#if 0
-    //AUBIO_MSG("sampler: got %d / %d fetching from source\n", s->available,
-    //    s->source_blocksize);
-    if (s->available == 0) {
-      //aubio_sampler_do_eof(s);
-      //aubio_sampler_do_perfectloop(s, output);
-    }
-    if (s->available < s->source_blocksize) {
-      AUBIO_ERR("sampler: short read from source"
-          " s->available %d, ring_avail %d \n", s->available, ring_avail);
-      //s->eof = 0;
-      //abort();
-    }
-#endif
     if (available > 0) {
       aubio_ringbuffer_push(s->ring, s->source_output, available);
-    } else {
-      //if (s->playing && !s->finished)
-      //AUBIO_WRN("sampler: not reading anymore should do eof now %d\n", check_wrote);
-      // TODO: move eof fetch now
+    }
+    if (available < s->source_blocksize) {
+      if (ring_avail + available <= s->blocksize) {
+        s->eof_remaining = available + ring_avail;
+        if (s->eof_remaining == 0) s->eof_remaining = s->blocksize;
+        //AUBIO_ERR("sampler: marking special eof got: %d, in ring: %d, %d, eof remaining %d\n",
+        //    available, ring_avail, s->blocksize, s->eof_remaining);
+        if (s->loop) {
+          aubio_sampler_seek(s,0);
+          // read some frames from beginning of source for perfect looping
+          if (s->perfectloop) {
+            available = aubio_sampler_pull_from_source(s);
+            if (available <= 0) {
+              AUBIO_ERR("sampler: perfectloop but s->available = 0 !\n");
+            } else {
+              aubio_ringbuffer_push(s->ring, s->source_output, available);
+            }
+          }
+        }
+      }
     }
   }
   return available;
 }
 
-uint_t
-aubio_sampler_write_remaining_ring(aubio_sampler_t *s, fvec_t *output, uint_t wrote);
-
 static void
 aubio_sampler_reading_from_source_ring_pull(aubio_sampler_t *s, fvec_t *output,
     uint_t *read)
@@ -476,8 +444,16 @@ aubio_sampler_reading_from_source_ring_pull(aubio_sampler_t *s, fvec_t *output,
     aubio_ringbuffer_pull(s->ring, output, s->blocksize);
     check_wrote += s->blocksize;
     *read = s->blocksize;
+    if (s->eof_remaining > 0) {
+      if (s->eof_remaining <= s->blocksize) {
+        s->eof = 1;
+        s->eof_remaining = 0;
+      } else if (s->eof_remaining <= s->source_blocksize) {
+        s->eof_remaining -= s->blocksize;
+      }
+    }
   } else {
-    //AUBIO_MSG("sampler: last frame, pulling remaining %d left\n", ring_avail);
+    AUBIO_MSG("sampler: last frame, pulling remaining %d left\n", ring_avail);
     *read = 0;
     if (ring_avail > 0) {
       // pull remaining frames in ring buffer
@@ -485,12 +461,11 @@ aubio_sampler_reading_from_source_ring_pull(aubio_sampler_t *s, fvec_t *output,
       check_wrote += ring_avail;
       *read += ring_avail;
     }
-    // signal eof, seek to 0 if looping
+    // signal eof
     aubio_sampler_do_eof(s);
-    // read new frames from source early if needed
-    aubio_sampler_do_perfectloop(s);
-    // write the remaining frames
-    *read += aubio_sampler_write_remaining_ring(s, output, ring_avail);
+    // finished playing, reset ringbuffer for next read
+    if (!s->playing)
+      aubio_ringbuffer_reset(s->ring);
   }
 }
 
@@ -570,32 +545,6 @@ aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read)
   }
 }
 
-uint_t
-aubio_sampler_write_remaining_ring(aubio_sampler_t *s, fvec_t *output, uint_t wrote){
-  if (s->perfectloop && s->loop) {
-    fvec_t tmpout;
-    tmpout.data = output->data + wrote;
-    tmpout.length = s->blocksize - wrote;
-    aubio_ringbuffer_pull(s->ring, &tmpout, tmpout.length);
-    check_wrote += tmpout.length;
-    return tmpout.length;
-  }
-  return 0;
-}
-
-void
-aubio_sampler_do_perfectloop(aubio_sampler_t *s) {
-  // perfectloop fetched new samples from start of source to ringbuffer
-  if (s->perfectloop && s->loop) {
-    s->available = aubio_sampler_pull_from_source(s);
-    if (s->available <= 0) {
-      AUBIO_ERR("sampler: perfectloop but s->available = 0 !\n");
-    } else {
-      aubio_ringbuffer_push(s->ring, s->source_output, s->available);
-    }
-  }
-}
-
 void
 aubio_sampler_read_from_table(aubio_sampler_t *o, fvec_t *output, uint_t *read) {
   *read = 0;
@@ -777,7 +726,7 @@ void del_aubio_sampler( aubio_sampler_t * o )
   aubio_sampler_close_reading_thread(o);
 #endif
   //if (o->source_output) {
-  if (o->perfectloop || o->ring) {
+  if (o->source_output && (o->threaded_read || o->perfectloop)) {
     del_fvec(o->source_output);
   }
   if (o->source_moutput) {