From: Paul Brossier Date: Wed, 5 Oct 2016 12:30:57 +0000 (+0200) Subject: src/synth/sampler.{c,h}: prepare reading thread, reset waited in _queue, only join... X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=0a756ea260eaf016f1075a6639c3640586625f95;p=aubio.git src/synth/sampler.{c,h}: prepare reading thread, reset waited in _queue, only join open thread if still open, improve documentation --- diff --git a/src/synth/sampler.c b/src/synth/sampler.c index 079087b9..5c9c0add 100644 --- a/src/synth/sampler.c +++ b/src/synth/sampler.c @@ -43,9 +43,13 @@ struct _aubio_sampler_t { uint_t playing; uint_t opened; uint_t loop; - uint_t finished; - uint_t eof; + uint_t finished; // end of file was reached + uint_t eof; // end of file is now #ifdef HAVE_THREADS + pthread_t read_thread; // file reading thread + pthread_mutex_t read_mutex; + pthread_cond_t read_avail; + pthread_cond_t read_request; pthread_t open_thread; // file opening thread pthread_mutex_t open_mutex; uint_t waited; // number of frames skipped while opening @@ -53,10 +57,14 @@ struct _aubio_sampler_t { uint_t open_thread_running; sint_t available; // number of samples currently available uint_t started; // source warmed up - uint_t finish; // flag to tell reading thread to exit + uint_t read_thread_finish; // flag to tell reading thread to exit #endif }; +#ifdef HAVE_THREADS +static void *aubio_sampler_readfn(void *p); +#endif + aubio_sampler_t *new_aubio_sampler(uint_t blocksize, uint_t samplerate) { aubio_sampler_t *s = AUBIO_NEW(aubio_sampler_t); @@ -79,6 +87,12 @@ aubio_sampler_t *new_aubio_sampler(uint_t blocksize, uint_t samplerate) s->waited = 0; s->open_thread = 0; s->open_thread_running = 0; + + s->read_thread_finish = 0; + pthread_mutex_init(&s->read_mutex, 0); + pthread_cond_init (&s->read_avail, 0); + pthread_cond_init (&s->read_request, 0); + pthread_create(&s->read_thread, 0, aubio_sampler_readfn, s); #endif return s; beach: @@ -163,6 +177,7 @@ aubio_sampler_queue(aubio_sampler_t *o, const char_t *uri) o->started = 0; o->available = 0; o->next_uri = uri; + o->waited = 0; if (pthread_create(&o->open_thread, 0, aubio_sampler_openfn, o) != 0) { AUBIO_ERR("sampler: failed creating opening thread\n"); ret = AUBIO_FAIL; @@ -184,6 +199,27 @@ lock_failed: #endif } +#ifdef HAVE_THREADS +void *aubio_sampler_readfn(void *z) { + aubio_sampler_t *p = z; + while(1) { + pthread_mutex_lock(&p->read_mutex); + if (1) { + // idle + 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 aubio_sampler_fetch_from_source(aubio_sampler_t *o, fvec_t *output, uint_t *read) { if (o->opened == 1 && o->source && !o->finished) @@ -250,18 +286,9 @@ aubio_sampler_seek(aubio_sampler_t * o, uint_t pos) uint_t ret = AUBIO_FAIL; o->finished = 0; if (!o->opened) return AUBIO_OK; -#ifdef HAVE_THREADS - if (pthread_mutex_trylock(&o->open_mutex)) { - AUBIO_WRN("sampler: failed locking in seek\n"); - return ret; - } -#endif if (o->source) { ret = aubio_source_seek(o->source, pos); } -#ifdef HAVE_THREADS - pthread_mutex_unlock(&o->open_mutex); -#endif return ret; } @@ -363,18 +390,32 @@ uint_t aubio_sampler_trigger ( aubio_sampler_t * o ) void del_aubio_sampler( aubio_sampler_t * o ) { #ifdef HAVE_THREADS - AUBIO_WRN("sampler: cleaning up\n"); + void *threadret; + + // clean up opening thread pthread_mutex_destroy(&o->open_mutex); if (o->open_thread_running) { if (pthread_cancel(o->open_thread)) { - AUBIO_WRN("sampler: cancelling open thread failed\n"); + AUBIO_WRN("sampler: cancelling file opening thread failed\n"); } } - void *threadret; - if (pthread_join(o->open_thread, &threadret)) { - AUBIO_WRN("sampler: joining open thread failed\n"); + if (o->open_thread && pthread_join(o->open_thread, &threadret)) { + AUBIO_WRN("sampler: joining file opening thread failed\n"); } pthread_mutex_destroy(&o->open_mutex); + + // close reading thread + o->read_thread_finish = 1; + pthread_cond_signal(&o->read_request); + if (pthread_cancel(o->read_thread)) { + AUBIO_WRN("sampler: cancelling file reading thread failed\n"); + } + if (pthread_join(o->read_thread, &threadret)) { + AUBIO_WRN("sampler: joining file reading thread failed\n"); + } + pthread_mutex_destroy(&o->read_mutex); + pthread_cond_destroy(&o->read_avail); + pthread_cond_destroy(&o->read_request); #endif if (o->source) { del_aubio_source(o->source); diff --git a/src/synth/sampler.h b/src/synth/sampler.h index f326119b..7a9376e0 100644 --- a/src/synth/sampler.h +++ b/src/synth/sampler.h @@ -193,8 +193,10 @@ uint_t aubio_sampler_get_samplerate(aubio_sampler_t * o); /** get the number of samples that were set to zero while opening a file \param o sampler, created by new_aubio_sampler() + \param waited the number of frames processed during this block - \return samplerate of the sampler + \return the total delay in samples when the file was successfuly opened, 0 + otherwise */ uint_t aubio_sampler_get_waited_opening(aubio_sampler_t * o, uint_t waited);