source: src/synth/sampler.c @ 1686fcf

sampler
Last change on this file since 1686fcf was 1686fcf, checked in by Paul Brossier <piem@piem.org>, 7 years ago

src/synth/sampler.h: add aubio_sampler_get_duration

  • Property mode set to 100644
File size: 30.0 KB
RevLine 
[a682dbe]1/*
[bff692e]2  Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org>
[a682dbe]3
4  This file is part of aubio.
5
6  aubio is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10
11  aubio is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with aubio.  If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
[88a774c]21#include <assert.h>
[a682dbe]22
23#include "aubio_priv.h"
24#include "fvec.h"
25#include "fmat.h"
26#include "io/source.h"
[88a774c]27#include "utils/ringbuffer.h"
[82ad1ed]28#include "effects/timestretch.h"
[a682dbe]29#include "synth/sampler.h"
30
[b4ff97e]31#ifdef HAVE_PTHREAD_H
[88042ef]32#define HAVE_THREADS 1
33#include <pthread.h>
[b4ff97e]34#else
[388c2e7]35#ifdef _MSC_VER
[95af88b]36#pragma message ("WARNING: compiling sampler without threading")
[388c2e7]37#else
[b4ff97e]38#warning "compiling sampler without threading"
[88042ef]39#endif
[388c2e7]40#endif
[88042ef]41
[88a774c]42typedef enum {
43  aubio_sampler_reading_from_source,
44  aubio_sampler_reading_from_table,
45  aubio_sampler_n_reading_methods
46} aubio_sampler_reading_method;
47
48
49typedef enum {
50  aubio_sampler_interp_pitchtime,
51  aubio_sampler_interp_quad,
52  aubio_sampler_interp_lin,
53  aubio_sampler_n_interp_methods
54} aubio_sampler_interp_method;
55
[a682dbe]56struct _aubio_sampler_t {
57  uint_t samplerate;
58  uint_t blocksize;
[1686fcf]59  uint_t duration;
[88a774c]60  // current reading mode (can be a file or an array)
61  uint_t reading_from;
62  // current interpolation mode (can be quadratic, timestretch, ...)
63  uint_t interp;
64  aubio_ringbuffer_t *ring;
65  uint_t perfectloop;
[f253b03]66  uint_t eof_remaining;
[2ca4b59]67  // reading from a table
68  fvec_t *table;
69  uint_t table_index;
[88a774c]70  // reading from a source
[a682dbe]71  aubio_source_t *source;
[ebed7e6]72  char_t *uri;
[a682dbe]73  uint_t playing;
[88042ef]74  uint_t opened;
75  uint_t loop;
[0a756ea]76  uint_t finished;              // end of file was reached
77  uint_t eof;                   // end of file is now
[82ad1ed]78  // time stretching
79  aubio_timestretch_t *ts;
[f8bdcb2]80  sint_t available;             // number of samples currently available
81  uint_t started;               // source warmed up
82  // source
83  uint_t source_blocksize;
84  uint_t channels;
85  fvec_t *source_output;
86  fmat_t *source_moutput;
87  //fvec_t *source_output_tmp;
88  //uint_t last_read;
89  uint_t threaded_read;         // use reading thread?
[88042ef]90#ifdef HAVE_THREADS
[b959a8f]91  // file reading thread
92  pthread_t read_thread;
[0a756ea]93  pthread_mutex_t read_mutex;
94  pthread_cond_t read_avail;
95  pthread_cond_t read_request;
[88a774c]96  // file opening thread
97  pthread_t open_thread;
[88042ef]98  pthread_mutex_t open_mutex;
99  uint_t waited;                // number of frames skipped while opening
[ebed7e6]100  char_t *next_uri;
[88042ef]101  uint_t open_thread_running;
[0a756ea]102  uint_t read_thread_finish;    // flag to tell reading thread to exit
[88042ef]103#endif
[a682dbe]104};
105
[88a774c]106static sint_t aubio_sampler_pull_from_source(aubio_sampler_t *s);
107
108static void aubio_sampler_do_eof(aubio_sampler_t *s);
109
110static void aubio_sampler_read(aubio_sampler_t *s, fvec_t *output, uint_t *read);
111static void aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read);
112static void aubio_sampler_read_from_table(aubio_sampler_t *s, fvec_t *output, uint_t *read);
113
[0a756ea]114#ifdef HAVE_THREADS
[b959a8f]115static void *aubio_sampler_openfn(void *p);
[0a756ea]116static void *aubio_sampler_readfn(void *p);
[b959a8f]117static void aubio_sampler_open_opening_thread(aubio_sampler_t *o);
118static void aubio_sampler_open_reading_thread(aubio_sampler_t *o);
119static void aubio_sampler_close_opening_thread(aubio_sampler_t *o);
120static void aubio_sampler_close_reading_thread(aubio_sampler_t *o);
[0a756ea]121#endif
122
[88042ef]123aubio_sampler_t *new_aubio_sampler(uint_t blocksize, uint_t samplerate)
[a682dbe]124{
125  aubio_sampler_t *s = AUBIO_NEW(aubio_sampler_t);
[79b54ea]126  if ((sint_t)blocksize < 1) {
127    AUBIO_ERR("sampler: got blocksize %d, but can not be < 1\n", blocksize);
128    goto beach;
129  }
[a682dbe]130  s->samplerate = samplerate;
131  s->blocksize = blocksize;
[1686fcf]132  s->duration = 0;
[a682dbe]133  s->source = NULL;
134  s->playing = 0;
[88042ef]135  s->loop = 0;
136  s->uri = NULL;
137  s->finished = 1;
138  s->eof = 0;
139  s->opened = 0;
[b959a8f]140  s->available = 0;
[88042ef]141
[fefbbd8]142  s->perfectloop = 0;
[88a774c]143#if 0 // naive mode
144  s->source_blocksize = s->blocksize;
[fefbbd8]145#elif 0 // threaded mode, no ringbuffer
[88a774c]146  s->source_blocksize = s->blocksize;
[fefbbd8]147  s->threaded_read = 1;
148#elif 0 // unthreaded, with ringbuffer
149  s->source_blocksize = 2048; //32 * s->blocksize;
150  s->perfectloop = 1;
151#elif 1 // threaded with ringhbuffer
[88a774c]152  s->source_blocksize = 2048; //32 * s->blocksize;
153  s->perfectloop = 1;
[f8bdcb2]154#endif
155
156#ifdef HAVE_THREADS
157  // disabled for now
158  s->threaded_read = 0;
159#else
[7dfd972]160  s->threaded_read = 0;
[88a774c]161#endif
[a006c5f]162
[f8bdcb2]163  s->perfectloop = 1;
164
[a006c5f]165  if (s->source_blocksize < s->blocksize) {
166    s->source_blocksize = s->blocksize;
167  }
[fefbbd8]168  // FIXME: perfectloop fails if source_blocksize > 2048 with source_avcodec
169  //s->source_blocksize = 8192;
[88a774c]170
[f253b03]171  if (s->perfectloop || s->source_blocksize != s->blocksize) {
172    s->ring = new_aubio_ringbuffer(s->source_blocksize * 2, s->blocksize);
[88a774c]173  }
[a69e7aa]174  if (s->threaded_read || s->perfectloop || s->ring)
175    s->source_output = new_fvec(s->source_blocksize);
[fefbbd8]176  //s->channels = 1;
177  //s->source_moutput = new_fmat(s->source_blocksize, s->channels);
[88a774c]178
[88042ef]179#ifdef HAVE_THREADS
[b959a8f]180  aubio_sampler_open_opening_thread(s);
[88a774c]181
[b959a8f]182  if (s->threaded_read) {
[fefbbd8]183    //AUBIO_WRN("sampler: starting reading thread\n");
[b959a8f]184    aubio_sampler_open_reading_thread(s);
185  }
186#endif
187
[2ca4b59]188#if 0
189  s->reading_from = aubio_sampler_reading_from_table;
190  s->perfectloop = 1;
191  s->threaded_read = 0;
192  s->opened = 1;
193  s->finished = 1;
194  s->table_index = 0;
195#endif
196
[82ad1ed]197  s->ts = new_aubio_timestretch("default", 1., s->blocksize, s->samplerate);
[f8bdcb2]198  //s->source_output_tmp = new_fvec(s->source_blocksize);
199  //s->last_read = 0;
[82ad1ed]200
[b959a8f]201  return s;
202beach:
203  AUBIO_FREE(s);
204  return NULL;
205}
206
207#ifdef HAVE_THREADS
208void aubio_sampler_open_opening_thread(aubio_sampler_t *s) {
[88042ef]209  pthread_mutex_init(&s->open_mutex, 0);
210  s->waited = 0;
211  s->open_thread = 0;
212  s->open_thread_running = 0;
[b959a8f]213}
[0a756ea]214
[b959a8f]215void aubio_sampler_open_reading_thread(aubio_sampler_t *s) {
[0a756ea]216  s->read_thread_finish = 0;
217  pthread_mutex_init(&s->read_mutex, 0);
218  pthread_cond_init (&s->read_avail, 0);
219  pthread_cond_init (&s->read_request, 0);
220  pthread_create(&s->read_thread, 0, aubio_sampler_readfn, s);
[a682dbe]221}
222
[b959a8f]223void aubio_sampler_close_opening_thread(aubio_sampler_t *o) {
224  // clean up opening thread
225  void *threadret;
[2ca4b59]226  if (!o->open_thread) return;
[b959a8f]227  pthread_mutex_destroy(&o->open_mutex);
228  if (o->open_thread_running) {
229    if (pthread_cancel(o->open_thread)) {
230      AUBIO_WRN("sampler: cancelling file opening thread failed\n");
231    }
232  }
233  if (o->open_thread && pthread_join(o->open_thread, &threadret)) {
234    AUBIO_WRN("sampler: joining file opening thread failed\n");
235  }
236  pthread_mutex_destroy(&o->open_mutex);
[2ca4b59]237  o->open_thread = 0;
[b959a8f]238}
239
240void aubio_sampler_close_reading_thread(aubio_sampler_t *o) {
241  // clean up reading thread
242  void *threadret;
243  if (!o->read_thread) return;
244  o->read_thread_finish = 1;
245  pthread_cond_signal(&o->read_request);
246  if (pthread_cancel(o->read_thread)) {
247    AUBIO_WRN("sampler: cancelling file reading thread failed\n");
248  }
249  if (pthread_join(o->read_thread, &threadret)) {
250    AUBIO_WRN("sampler: joining file reading thread failed\n");
251  }
252  pthread_mutex_destroy(&o->read_mutex);
253  pthread_cond_destroy(&o->read_avail);
254  pthread_cond_destroy(&o->read_request);
[2ca4b59]255  o->read_thread = 0;
[b959a8f]256}
257#endif
258
[eaee767]259uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri )
[a682dbe]260{
[88042ef]261  uint_t ret = AUBIO_FAIL;
262  aubio_source_t *oldsource = o->source, *newsource = NULL;
[88a774c]263  newsource = new_aubio_source(uri, o->samplerate, o->source_blocksize);
[88042ef]264  if (newsource) {
[a006c5f]265    uint_t duration = aubio_source_get_duration(newsource);
266    if (duration < o->blocksize) {
267      AUBIO_WRN("sampler: %s is %d frames long, but blocksize is %d\n",
268          uri, duration, o->blocksize);
269    }
[88042ef]270    o->source = newsource;
271    if (oldsource) del_aubio_source(oldsource);
272    if (o->samplerate == 0) {
273      o->samplerate = aubio_source_get_samplerate(o->source);
274    }
[ebed7e6]275    if (o->uri) AUBIO_FREE(o->uri);
276    o->uri = AUBIO_ARRAY(char_t, strnlen(uri, PATH_MAX) + 1);
277    strncpy(o->uri, uri, strnlen(uri, PATH_MAX) + 1);
[88042ef]278    o->finished = 0;
279    o->eof = 0;
[f253b03]280    o->eof_remaining = 0;
[88042ef]281    o->opened = 1;
282    ret = AUBIO_OK;
[1686fcf]283    o->duration = duration;
[82ad1ed]284    AUBIO_MSG("sampler: loaded %s\n", uri);
[f8bdcb2]285#ifdef HAVE_THREADS
[88a774c]286    if (o->waited) {
[584bfd0]287      AUBIO_WRN("sampler: %.2fms (%d samples) taken to load %s\n", 1000. *
288          o->waited / (smpl_t)o->samplerate, o->waited, o->uri);
[88a774c]289    }
[f8bdcb2]290#endif
[88042ef]291  } else {
292    o->source = NULL;
293    if (oldsource) del_aubio_source(oldsource);
294    o->playing = 0;
295    o->uri = NULL;
296    o->finished = 1;
297    o->eof = 0;
[f253b03]298    o->eof_remaining = 0;
[88042ef]299    o->opened = 0;
300    AUBIO_WRN("sampler: failed loading %s\n", uri);
301  }
[88a774c]302  if (o->ring) {
[f253b03]303    //AUBIO_WRN("sampler: resetting ringbuffer\n");
[88a774c]304    aubio_ringbuffer_reset(o->ring);
305  }
[88042ef]306  return ret;
307}
308
309#ifdef HAVE_THREADS
310static void *aubio_sampler_openfn(void *z) {
311  aubio_sampler_t *p = z;
312  uint_t err;
313  int oldtype;
314  void *ret;
315  pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
316  pthread_mutex_lock(&p->open_mutex);
317  p->open_thread_running = 1;
318  err = aubio_sampler_load(p, p->next_uri);
319  p->open_thread_running = 0;
320  pthread_mutex_unlock(&p->open_mutex);
321  ret = &err;
322  pthread_exit(ret);
323}
324#endif
[eaee767]325
[88042ef]326uint_t
327aubio_sampler_queue(aubio_sampler_t *o, const char_t *uri)
328{
329#ifdef HAVE_THREADS
330  uint_t ret = AUBIO_OK;
[2ca4b59]331
332  if (o->reading_from == aubio_sampler_reading_from_table) {
333    o->reading_from = aubio_sampler_reading_from_source;
334    o->opened = 0;
335    o->finished = 1;
336  }
[88042ef]337  /* open uri in open_thread */
338  if (o->open_thread_running) {
339    // cancel previous open_thread
340    if (pthread_cancel(o->open_thread)) {
[88a774c]341      AUBIO_WRN("sampler: failed queuing %s (cancelling existing open thread failed)\n", uri);
[88042ef]342      return AUBIO_FAIL;
343    } else {
[88a774c]344      AUBIO_WRN("sampler: cancelled queuing %s (queuing %s now)\n",
[88042ef]345          o->next_uri, uri);
346    }
347    o->open_thread_running = 0;
348  }
349  void *threadret;
350  if (o->open_thread && pthread_join(o->open_thread, &threadret)) {
351    AUBIO_WRN("sampler: joining thread failed\n");
352  }
353  if (pthread_mutex_trylock(&o->open_mutex)) {
[88a774c]354    AUBIO_WRN("sampler: failed queuing %s (locking failed)\n", uri);
[88042ef]355    ret = AUBIO_FAIL;
356    goto lock_failed;
357  }
358  o->opened = 0; // while opening
359  o->started = 0;
360  o->available = 0;
[ebed7e6]361  if (o->next_uri) AUBIO_FREE(o->next_uri);
362  o->next_uri = AUBIO_ARRAY(char_t, strnlen(uri, PATH_MAX) + 1);
363  strncpy(o->next_uri, uri, strnlen(uri, PATH_MAX) + 1);
[0a756ea]364  o->waited = 0;
[88042ef]365  if (pthread_create(&o->open_thread, 0, aubio_sampler_openfn, o) != 0) {
366    AUBIO_ERR("sampler: failed creating opening thread\n");
367    ret = AUBIO_FAIL;
368    goto thread_create_failed;
369  }
370
371thread_create_failed:
372  pthread_mutex_unlock(&o->open_mutex);
373lock_failed:
374  if (ret == AUBIO_OK) {
375    //AUBIO_WRN("sampler: queued %s\n", uri);
376  } else {
377    AUBIO_ERR("sampler: queueing %s failed\n", uri);
378  }
379  return ret;
380#else
381  AUBIO_WRN("sampler: opening %s, not queueing (not compiled with threading)\n", uri);
382  return aubio_sampler_load(o, uri);
383#endif
384}
[eaee767]385
[0a756ea]386#ifdef HAVE_THREADS
[88a774c]387
388uint_t aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s);
[fefbbd8]389
[0a756ea]390void *aubio_sampler_readfn(void *z) {
391  aubio_sampler_t *p = z;
392  while(1) {
393    pthread_mutex_lock(&p->read_mutex);
[88a774c]394    if (p->open_thread_running) {
395      //AUBIO_WRN("sampler: readfn(): file is being opened\n");
396      pthread_cond_signal(&p->read_avail);
397      //pthread_cond_wait(&p->read_request, &p->read_mutex);
398    } else if (p->opened && !p->started && !p->finished) {
399      //AUBIO_WRN("sampler: readfn(): file started\n");
400      if (p->ring) {
[fefbbd8]401        p->available = aubio_sampler_reading_from_source_ring_fetch(p);
[88a774c]402      } else {
403        p->available = aubio_sampler_pull_from_source(p);
404        if (p->available < (sint_t)p->source_blocksize)
405          aubio_sampler_do_eof(p);
406      }
407      pthread_cond_signal(&p->read_avail);
408      if (!p->finished) {
409        pthread_cond_wait(&p->read_request, &p->read_mutex);
410      }
411    } else {
412      //AUBIO_WRN("sampler: readfn(): idle?\n");
[d02d8f0]413      pthread_cond_signal(&p->read_avail);
[88a774c]414      pthread_cond_wait(&p->read_request, &p->read_mutex);
415      if (p->read_thread_finish) {
416        goto done;
417      }
418    }
419    pthread_mutex_unlock(&p->read_mutex);
420  }
421done:
422  //AUBIO_WRN("sampler: exiting reading thread\n");
423  pthread_mutex_unlock(&p->read_mutex);
424  pthread_exit(NULL);
425}
[0a756ea]426#endif
427
[88042ef]428void
[88a774c]429aubio_sampler_read(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
430  if (s->reading_from == aubio_sampler_reading_from_source) {
431    aubio_sampler_read_from_source(s, output, read);
432  } else if (s->reading_from == aubio_sampler_reading_from_table) {
433    aubio_sampler_read_from_table(s, output, read);
434  }
435}
436
437static void
438aubio_sampler_reading_from_source_naive(aubio_sampler_t *s, fvec_t * output,
439    uint_t *read)
440{
441  // directly read from disk
442  //aubio_source_do(s->source, output, read);
443  s->source_output = output;
444  *read = aubio_sampler_pull_from_source(s);
445  if (*read < s->source_blocksize) {
446    //AUBIO_WRN("sampler: calling go_eof in _read_from_source()\n");
447    aubio_sampler_do_eof(s);
448  }
[a682dbe]449}
450
[88a774c]451uint_t
452aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s) {
453  // read source_blocksize (> blocksize) at once
454  int ring_avail = aubio_ringbuffer_get_available(s->ring);
455  //if (ring_avail < s->blocksize) {
456  uint_t available = 0;
457  if (ring_avail < (sint_t)s->blocksize) {
458    available = aubio_sampler_pull_from_source(s);
459    if (available > 0) {
460      aubio_ringbuffer_push(s->ring, s->source_output, available);
[f253b03]461    }
[82ad1ed]462    if (available < s->blocksize) {
463      //AUBIO_WRN("sampler: short read %d\n", available);
[f253b03]464      if (ring_avail + available <= s->blocksize) {
465        s->eof_remaining = available + ring_avail;
466        if (s->eof_remaining == 0) s->eof_remaining = s->blocksize;
[82ad1ed]467        ring_avail = aubio_ringbuffer_get_available(s->ring);
468        //AUBIO_ERR("sampler: eof in: %d, last fetch: %d, in ring: %d\n",
469        //    s->eof_remaining, available, ring_avail);
[f253b03]470        if (s->loop) {
471          aubio_sampler_seek(s,0);
472          // read some frames from beginning of source for perfect looping
473          if (s->perfectloop) {
474            available = aubio_sampler_pull_from_source(s);
475            if (available <= 0) {
476              AUBIO_ERR("sampler: perfectloop but s->available = 0 !\n");
477            } else {
478              aubio_ringbuffer_push(s->ring, s->source_output, available);
479            }
480          }
481        }
482      }
[88a774c]483    }
484  }
485  return available;
486}
487
488static void
489aubio_sampler_reading_from_source_ring_pull(aubio_sampler_t *s, fvec_t *output,
490    uint_t *read)
491{
492  // write into output
493  int ring_avail = aubio_ringbuffer_get_available(s->ring);
494  if (ring_avail >= (sint_t)s->blocksize) {
495    //AUBIO_MSG("sampler: pulling %d / %d from ringbuffer\n", s->blocksize, ring_avail);
496    aubio_ringbuffer_pull(s->ring, output, s->blocksize);
497    *read = s->blocksize;
[f253b03]498    if (s->eof_remaining > 0) {
499      if (s->eof_remaining <= s->blocksize) {
[816932e]500        //AUBIO_WRN("sampler: signaling eof\n");
501        s->eof = 1; // signal eof
[f253b03]502        s->eof_remaining = 0;
503      } else if (s->eof_remaining <= s->source_blocksize) {
504        s->eof_remaining -= s->blocksize;
505      }
506    }
[88a774c]507  } else {
[a006c5f]508    //AUBIO_MSG("sampler: last frame, pulling remaining %d left\n", ring_avail);
[88a774c]509    *read = 0;
510    if (ring_avail > 0) {
[fefbbd8]511      // pull remaining frames in ring buffer
[88a774c]512      aubio_ringbuffer_pull(s->ring, output, ring_avail);
513      *read += ring_avail;
514    }
[f253b03]515    // signal eof
[88a774c]516    aubio_sampler_do_eof(s);
[f253b03]517    // finished playing, reset ringbuffer for next read
518    if (!s->playing)
519      aubio_ringbuffer_reset(s->ring);
[88a774c]520  }
521}
522
523static void
524aubio_sampler_reading_from_source_ring(aubio_sampler_t *s, fvec_t *output,
525    uint_t *read)
526{
[82ad1ed]527#if 0
[88a774c]528  aubio_sampler_reading_from_source_ring_fetch(s);
529  aubio_sampler_reading_from_source_ring_pull(s, output, read);
[82ad1ed]530#else // raw version
531  uint_t source_read;
532  while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
533      && s->eof_remaining == 0) {
534    aubio_source_do(s->source, s->source_output, &source_read);
535    aubio_timestretch_push(s->ts, s->source_output, source_read);
536    if (source_read < s->source_output->length) s->eof_remaining = source_read;
537    //AUBIO_WRN("sampler: pushed %d, now %d available\n",
538    //    source_read, aubio_timestretch_get_available(s->ts));
539  }
540  aubio_timestretch_do(s->ts, output, read);
541  if (s->eof_remaining > s->blocksize) {
542    s->eof_remaining -= s->blocksize;
543  }
544  if (*read < output->length) {
545    //AUBIO_WRN("sampler: short read %d, eof at %d\n", *read, s->eof_remaining);
546    s->eof_remaining = 0;
547    aubio_timestretch_reset(s->ts);
548    aubio_sampler_do_eof(s);
549    if (s->loop && s->perfectloop) {
[95af88b]550      uint_t partialread;
[82ad1ed]551      fvec_t tmpout; tmpout.data = output->data + *read;
552      tmpout.length = output->length - *read;
553      while (aubio_timestretch_get_available(s->ts) < (sint_t)tmpout.length
554          && s->eof_remaining == 0) {
555        aubio_source_do(s->source, s->source_output, &source_read);
556        aubio_timestretch_push(s->ts, s->source_output, source_read);
557        if (source_read < s->source_output->length) s->eof_remaining = source_read;
558      }
559      aubio_timestretch_do(s->ts, &tmpout, &partialread);
560      //AUBIO_WRN("sampler: partial read %d + %d\n", *read, partialread);
561      *read += partialread;
562    }
563  }
564#endif
[88a774c]565}
566
567#ifdef HAVE_THREADS
568static void
569aubio_sampler_read_from_source_threaded(aubio_sampler_t *s, fvec_t *output,
570    uint_t *read) {
571  // request at least output->length
572  // make sure we have enough samples read from source
573  int available;
574  pthread_mutex_lock(&s->read_mutex);
575  if (!s->opened || s->open_thread_running) {
576    //AUBIO_ERR("sampler: _read_from_source: not opened, signaling read_request\n");
577    pthread_cond_signal(&s->read_request);
578    available = 0;
579  } else if (!s->finished) {
580    pthread_cond_signal(&s->read_request);
581    pthread_cond_wait(&s->read_avail, &s->read_mutex);
582    //AUBIO_ERR("sampler: _read_from_source: %d\n", s->available);
583    available = s->available;
584  } else {
585    //AUBIO_WRN("sampler: _read_from_source: eof\n");
586    pthread_cond_signal(&s->read_request);
587    available = 0;
588  }
589  pthread_mutex_unlock(&s->read_mutex);
590  //AUBIO_WRN("sampler: got %d available in _read_from_source\n", available);
591  // read -> number of samples read
[fefbbd8]592  if (!s->perfectloop && s->source_blocksize == s->blocksize) {
593    if (available >= (sint_t)s->blocksize) {
594      fvec_copy(s->source_output, output);
595      *read = s->blocksize;
596    } else if (available > 0) {
597      fvec_copy(s->source_output, output);
598      *read = available;
599    } else {
600      fvec_zeros(output);
601      *read = 0;
602    }
[88a774c]603  } else {
[fefbbd8]604    aubio_sampler_reading_from_source_ring_pull(s, output, read);
[88a774c]605  }
606}
607#endif
608
[88042ef]609void
[88a774c]610aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
611#ifdef HAVE_THREADS
612  if (s->threaded_read) { // if threaded
[fefbbd8]613    aubio_sampler_read_from_source_threaded(s, output, read);
[88a774c]614  } else
615#endif
616  {
617    if (s->finished) {
618      *read = 0;
619    }
620    else if (s->source_blocksize == s->blocksize && !s->perfectloop) {
621      aubio_sampler_reading_from_source_naive(s, output, read);
622    } else {
623      aubio_sampler_reading_from_source_ring(s, output, read);
624    }
625#if 1
626    if (s->loop && s->perfectloop && *read != s->blocksize) { // && s->started && !s->finished) {
627      AUBIO_ERR("sampler: perfectloop but read only %d\n", *read);
628    }
629#endif
630  }
[88042ef]631}
632
633void
[2ca4b59]634aubio_sampler_read_from_table(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
[88a774c]635  *read = 0;
[2ca4b59]636  if (s->table == NULL) {
637    AUBIO_WRN("sampler: _pull_from_table but table not set %d, %d\n",
638        output->length, *read);
639  } else if (s->playing) {
[82ad1ed]640#if 0
[2ca4b59]641    uint_t available = s->table->length - s->table_index;
642    fvec_t tmp;
643    tmp.data = s->table->data + s->table_index;
644    if (available < s->blocksize) {
645      //AUBIO_WRN("sampler: _pull_from_table: table length %d, index: %d, read %d\n",
646      //    s->table->length, s->table_index, *read);
647      tmp.length = available;
648      fvec_t tmpout; tmpout.data = output->data; tmpout.length = available;
649      fvec_copy(&tmp, &tmpout);
650      if (s->loop && s->perfectloop) {
651        uint_t remaining = s->blocksize - available;
652        tmpout.data = output->data + available; tmpout.length = remaining;
653        tmp.data = s->table->data; tmp.length = remaining;
654        fvec_copy(&tmp, &tmpout);
655        s->table_index = remaining;
656        *read = s->blocksize;
657      } else {
658        s->table_index = 0;
659        *read = available;
660      }
661      aubio_sampler_do_eof(s);
662    } else {
663      tmp.length = s->blocksize;
664      fvec_copy(&tmp, output);
665      s->table_index += output->length;
666      *read = s->blocksize;
667    }
[82ad1ed]668#else
669    fvec_t tmp, tmpout;
670    uint_t source_read = 0;
671    while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
672        && s->eof_remaining == 0) {
673      uint_t available = s->table->length - s->table_index;
674      if (available < s->source_blocksize) {
675        source_read = available;
676      } else {
677        source_read = s->source_blocksize;
678      }
679      tmp.length = source_read; tmp.data = s->table->data + s->table_index;
680      tmpout.data = s->source_output->data; tmpout.length = source_read;
681      fvec_copy(&tmp, &tmpout);
682      aubio_timestretch_push(s->ts, &tmpout, source_read);
683      if (source_read < s->source_blocksize) {
684        s->eof_remaining = source_read;
685        s->table_index = s->source_blocksize - *read;
686      } else {
687        s->table_index += source_read;
688      }
689      if (s->table_index == s->table->length) s->table_index = 0;
690      //AUBIO_WRN("sampler: pushed %d, now %d available, table_index %d, eof %d\n",
691      //    source_read, aubio_timestretch_get_available(s->ts),
692      //    s->table_index, s->eof_remaining);
693    }
694    aubio_timestretch_do(s->ts, output, read);
695    if (*read == 0) {
696      //AUBIO_WRN("sampler: pushed %d, now %d available, table_index %d\n",
697      //    *read, aubio_timestretch_get_available(s->ts), s->table_index);
698    }
699    if (s->eof_remaining > s->blocksize) {
700      s->eof_remaining -= s->blocksize;
701    }
702    if (*read < output->length) {
703      s->eof_remaining = 0;
704      aubio_sampler_do_eof(s);
705    }
706#if 0
707    if (*read < output->length) {
708      //uint_t available = aubio_timestretch_get_available(s->ts);
709      s->eof_remaining = 0;
710      aubio_timestretch_reset(s->ts);
711      aubio_sampler_do_eof(s);
712    }
713#endif
714#if 0
715    if (*read < output->length) {
716      //uint_t available = aubio_timestretch_get_available(s->ts);
717      s->eof_remaining = 0;
718      aubio_timestretch_reset(s->ts);
719      aubio_sampler_do_eof(s);
720      if (s->loop && s->perfectloop) {
721        tmpout.data = output->data + *read;
722        tmpout.length = output->length - *read;
723        while (aubio_timestretch_get_available(s->ts) < (sint_t)tmpout.length
724            && s->eof_remaining == 0) {
725          uint_t available = s->table->length - s->table_index;
726          if (available < s->source_blocksize) {
727            source_read = available;
728          } else {
729            source_read = s->source_blocksize;
730          }
731          //AUBIO_WRN("sampler: short read %d, remaining %d\n", *read, remaining);
732          tmp.length = source_read; tmp.data = s->table->data + s->table_index;
733          fvec_t tmpout2; tmpout2.data = s->source_output->data; tmpout2.length = source_read;
734          fvec_copy(&tmp, &tmpout2);
735          aubio_timestretch_push(s->ts, &tmpout2, source_read);
736          if (source_read < s->source_blocksize) {
737            s->eof_remaining = source_read;
738            s->table_index = 0;
739          } else {
740            s->table_index += source_read;
741          }
742          if (s->table_index == s->table->length) s->table_index = 0;
743          //AUBIO_WRN("sampler: second push, pushed %d, now %d available\n",
744          //    source_read, aubio_timestretch_get_available(s->ts));
745        }
746        uint_t partialread;
747        aubio_timestretch_do(s->ts, &tmpout, &partialread);
748        AUBIO_WRN("sampler: partial read %d + %d\n", *read, partialread);
749        *read += partialread;
750        //s->eof = 1;
751      }
752    }
753#endif
754
755#endif
[2ca4b59]756  }
757}
758
759uint_t
760aubio_sampler_set_table(aubio_sampler_t *s, fvec_t *samples) {
761  if (!samples || !s) return AUBIO_FAIL;
762  if (s->reading_from == aubio_sampler_reading_from_source) {
763    //aubio_sampler_close_reading_thread(s);
764  }
765  s->table = samples;
766  //AUBIO_INF("sampler: setting table (%d long)\n", s->table->length);
767  s->table_index = 0;
768  s->reading_from = aubio_sampler_reading_from_table;
769  //s->threaded_read = 0;
770  s->opened = 1;
771  s->finished = 1;
772  return AUBIO_OK;
[88042ef]773}
[88a774c]774
775sint_t
776aubio_sampler_pull_from_source(aubio_sampler_t *s)
777{
778  // pull source_blocksize samples from source, return available frames
779  uint_t source_read = s->source_blocksize;
780  if (s->source == NULL) {
781    AUBIO_ERR("sampler: trying to fetch on NULL source\n");
782    return -1;
783  }
[82ad1ed]784#if 1
[88a774c]785  aubio_source_do(s->source, s->source_output, &source_read);
786  return source_read;
[82ad1ed]787#else
788  uint_t source_read_tmp;
789  while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
790      && s->last_read == 0) {
791    aubio_source_do(s->source, s->source_output_tmp, &source_read_tmp);
792    aubio_timestretch_push(s->ts, s->source_output_tmp, source_read_tmp);
793    if (source_read_tmp < s->source_output_tmp->length) s->last_read = source_read;
794  }
795  aubio_timestretch_do(s->ts, s->source_output, &source_read);
796  if (s->last_read > s->blocksize) {
797    s->last_read -= s->blocksize;
798  }
799  if (source_read < s->source_blocksize) {
800    s->last_read = 0;
801    //AUBIO_ERR("sampler: calling timestretch reset %d %d\n", source_read, s->source_blocksize);
802    aubio_timestretch_reset(s->ts);
803  }
804  return source_read;
805#endif
[88a774c]806}
807
[88042ef]808
809uint_t
810aubio_sampler_get_samplerate (aubio_sampler_t *o)
811{
812  return o->samplerate;
813}
814
815uint_t
[1686fcf]816aubio_sampler_get_duration (aubio_sampler_t *o)
817{
818  if (o->duration !=0) {
819    return o->duration;
820  } else {
821    AUBIO_WRN("sampler: failed getting duration for %s\n", o->uri);
822    return 0;
823  }
824}
825
826uint_t
[88042ef]827aubio_sampler_get_opened (aubio_sampler_t *o)
828{
829  return o->opened; //== 1 ? AUBIO_OK : AUBIO_FAIL;
830}
831
832uint_t
833aubio_sampler_get_finished(aubio_sampler_t *o)
834{
835  return o->finished;
836}
837
838uint_t
839aubio_sampler_get_eof (aubio_sampler_t *o)
[a682dbe]840{
[88042ef]841  return o->eof;
842}
843
844uint_t
845#ifdef HAVE_THREADS
[f8bdcb2]846aubio_sampler_get_waited_opening (aubio_sampler_t *o, uint_t waited) {
[a682dbe]847  if (o->playing) {
[88042ef]848    if (!o->opened) {
849      o->waited += waited;
850    } else if (o->waited) {
851      //AUBIO_WRN("sampler: waited %d frames (%.2fms) while opening %s\n",
852      //    o->waited, 1000.*o->waited/(smpl_t)o->samplerate, o->uri);
853      uint_t waited = o->waited;
854      o->waited = 0;
855      return waited;
[a682dbe]856    }
857  }
[f8bdcb2]858#else
859aubio_sampler_get_waited_opening (aubio_sampler_t *o UNUSED, uint_t waited UNUSED) {
[88042ef]860#endif
861  return 0;
862}
863
864uint_t
865aubio_sampler_seek(aubio_sampler_t * o, uint_t pos)
866{
[88a774c]867  //AUBIO_WRN("sampler: seeking to 0\n");
[88042ef]868  uint_t ret = AUBIO_FAIL;
869  o->finished = 0;
870  if (!o->opened) return AUBIO_OK;
871  if (o->source) {
872    ret = aubio_source_seek(o->source, pos);
[886a7d8]873  } else if (o->table && (sint_t)pos >= 0 && pos < o->table->length) {
874    o->table_index = pos < o->table->length ? pos : o->table->length - 1;
875    ret = AUBIO_OK;
[88042ef]876  }
[f8bdcb2]877  //o->last_read = 0;
[88042ef]878  return ret;
[a682dbe]879}
880
[88042ef]881void
882aubio_sampler_do_eof (aubio_sampler_t * o)
[a682dbe]883{
[88a774c]884  //AUBIO_MSG("sampler: calling  _do_eof()\n");
[88042ef]885  o->finished = 1;
886  o->eof = 1;
887  if (!o->loop) {
888    o->playing = 0;
889  } else {
[2ca4b59]890    if (o->reading_from == aubio_sampler_reading_from_source)
891      aubio_sampler_seek(o, 0);
[88a774c]892    //o->finished = 0;
[88042ef]893  }
894}
895
896void aubio_sampler_do ( aubio_sampler_t * o, fvec_t * output, uint_t *read)
897{
898  o->eof = 0;
899  if (o->opened == 1 && o->playing) {
[88a774c]900    aubio_sampler_read(o, output, read);
[88042ef]901  } else {
902    fvec_zeros(output);
[88a774c]903    *read = 0;
[a682dbe]904  }
[88042ef]905}
906
907void aubio_sampler_do_multi ( aubio_sampler_t * o, fmat_t * output, uint_t *read)
908{
909  o->eof = 0;
[88a774c]910  if (o->opened == 1 && o->playing) {
911    //aubio_sampler_read_multi(o, output, read);
[88042ef]912  } else {
913    fmat_zeros(output);
914    *read = 0;
[a682dbe]915  }
916}
917
[eaee767]918uint_t aubio_sampler_get_playing ( const aubio_sampler_t * o )
[a682dbe]919{
920  return o->playing;
921}
922
923uint_t aubio_sampler_set_playing ( aubio_sampler_t * o, uint_t playing )
924{
925  o->playing = (playing == 1) ? 1 : 0;
926  return 0;
927}
928
[88042ef]929uint_t aubio_sampler_get_loop ( aubio_sampler_t * o )
930{
931  return o->loop;
932}
933
934uint_t aubio_sampler_set_loop ( aubio_sampler_t * o, uint_t loop )
935{
936  o->loop = (loop == 1) ? 1 : 0;
937  return 0;
938}
939
[a682dbe]940uint_t aubio_sampler_play ( aubio_sampler_t * o )
941{
942  return aubio_sampler_set_playing (o, 1);
943}
944
945uint_t aubio_sampler_stop ( aubio_sampler_t * o )
946{
947  return aubio_sampler_set_playing (o, 0);
948}
949
[88042ef]950uint_t aubio_sampler_loop ( aubio_sampler_t * o )
951{
952  aubio_sampler_set_loop(o, 1);
953  aubio_sampler_seek(o, 0);
954  return aubio_sampler_set_playing (o, 1);
955}
956
957uint_t aubio_sampler_trigger ( aubio_sampler_t * o )
958{
[0840440]959  if (o->ring) aubio_ringbuffer_reset(o->ring);
[88042ef]960  aubio_sampler_set_loop(o, 0);
961  aubio_sampler_seek(o, 0);
962  return aubio_sampler_set_playing (o, 1);
963}
964
[943ef49]965uint_t aubio_sampler_set_perfectloop (aubio_sampler_t *s, uint_t perfectloop) {
966  if (!s) return AUBIO_FAIL;
967  s->perfectloop = perfectloop;
968  return AUBIO_OK;
969}
970
971uint_t aubio_sampler_get_perfectloop (aubio_sampler_t *s) {
972  if (!s) return AUBIO_FAIL;
973  return s->perfectloop;
974}
975
[82ad1ed]976
977uint_t aubio_sampler_set_stretch(aubio_sampler_t *s, smpl_t stretch)
978{
979  if (!s->ts) return AUBIO_FAIL;
980  return aubio_timestretch_set_stretch(s->ts, stretch);
981}
982
983smpl_t aubio_sampler_get_stretch(aubio_sampler_t *s)
984{
985  if (!s->ts) return 1.;
986  return aubio_timestretch_get_stretch(s->ts);
987}
988
989uint_t aubio_sampler_set_transpose(aubio_sampler_t *s, smpl_t transpose)
990{
991  if (!s->ts) return AUBIO_FAIL;
992  return aubio_timestretch_set_transpose(s->ts, transpose);
993}
994
995smpl_t aubio_sampler_get_transpose(aubio_sampler_t *s)
996{
997  if (!s->ts) return 0.;
998  return aubio_timestretch_get_transpose(s->ts);
999}
1000
1001
[a682dbe]1002void del_aubio_sampler( aubio_sampler_t * o )
1003{
[88042ef]1004#ifdef HAVE_THREADS
[b959a8f]1005  // close opening thread
1006  aubio_sampler_close_opening_thread(o);
[0a756ea]1007  // close reading thread
[b959a8f]1008  aubio_sampler_close_reading_thread(o);
[88042ef]1009#endif
[88a774c]1010  //if (o->source_output) {
[f253b03]1011  if (o->source_output && (o->threaded_read || o->perfectloop)) {
[88a774c]1012    del_fvec(o->source_output);
1013  }
1014  if (o->source_moutput) {
1015    del_fmat(o->source_moutput);
1016  }
1017  if (o->ring) {
1018    del_aubio_ringbuffer(o->ring);
1019  }
[82ad1ed]1020  if (o->ts) {
1021    del_aubio_timestretch(o->ts);
1022  }
[a682dbe]1023  if (o->source) {
1024    del_aubio_source(o->source);
1025  }
1026  AUBIO_FREE(o);
1027}
Note: See TracBrowser for help on using the repository browser.