source: src/synth/sampler.c @ fefbbd8

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

src/synth/sampler.c: clean up and add threaded ring buffer

  • Property mode set to 100644
File size: 21.9 KB
Line 
1/*
2  Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
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
21#include <assert.h>
22
23#include "config.h"
24#include "aubio_priv.h"
25#include "fvec.h"
26#include "fmat.h"
27#include "io/source.h"
28#include "utils/ringbuffer.h"
29#include "synth/sampler.h"
30
31#define HAVE_THREADS 1
32#define READER_THREAD_ON 1
33#if 0
34#undef HAVE_THREADS
35#endif
36
37#ifdef HAVE_THREADS
38#include <pthread.h>
39#endif
40
41typedef enum {
42  aubio_sampler_reading_from_source,
43  aubio_sampler_reading_from_table,
44  aubio_sampler_n_reading_methods
45} aubio_sampler_reading_method;
46
47
48int check_wrote = 0;
49
50typedef enum {
51  aubio_sampler_interp_pitchtime,
52  aubio_sampler_interp_quad,
53  aubio_sampler_interp_lin,
54  aubio_sampler_n_interp_methods
55} aubio_sampler_interp_method;
56
57struct _aubio_sampler_t {
58  uint_t samplerate;
59  uint_t blocksize;
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  // reading from a table
65  aubio_ringbuffer_t *ring;
66  uint_t perfectloop;
67  fvec_t *samples;
68  fmat_t *msamples;
69  // reading from a source
70  aubio_source_t *source;
71  const char_t *uri;
72  uint_t playing;
73  uint_t opened;
74  uint_t loop;
75  uint_t finished;              // end of file was reached
76  uint_t eof;                   // end of file is now
77#ifdef HAVE_THREADS
78  // file reading thread
79  pthread_t read_thread;
80  uint_t threaded_read;         // use reading thread?
81  pthread_mutex_t read_mutex;
82  pthread_cond_t read_avail;
83  pthread_cond_t read_request;
84  uint_t source_blocksize;
85  fvec_t *source_output;
86  fmat_t *source_moutput;
87  uint_t channels;
88  // file opening thread
89  pthread_t open_thread;
90  pthread_mutex_t open_mutex;
91  uint_t waited;                // number of frames skipped while opening
92  const char_t *next_uri;
93  uint_t open_thread_running;
94  sint_t available;             // number of samples currently available
95  uint_t started;               // source warmed up
96  uint_t read_thread_finish;    // flag to tell reading thread to exit
97#endif
98};
99
100static sint_t aubio_sampler_pull_from_source(aubio_sampler_t *s);
101
102static void aubio_sampler_do_eof(aubio_sampler_t *s);
103
104static void aubio_sampler_read(aubio_sampler_t *s, fvec_t *output, uint_t *read);
105static void aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read);
106static void aubio_sampler_read_from_table(aubio_sampler_t *s, fvec_t *output, uint_t *read);
107
108#ifdef HAVE_THREADS
109static void *aubio_sampler_openfn(void *p);
110static void *aubio_sampler_readfn(void *p);
111static void aubio_sampler_open_opening_thread(aubio_sampler_t *o);
112static void aubio_sampler_open_reading_thread(aubio_sampler_t *o);
113static void aubio_sampler_close_opening_thread(aubio_sampler_t *o);
114static void aubio_sampler_close_reading_thread(aubio_sampler_t *o);
115#endif
116
117aubio_sampler_t *new_aubio_sampler(uint_t blocksize, uint_t samplerate)
118{
119  aubio_sampler_t *s = AUBIO_NEW(aubio_sampler_t);
120  if ((sint_t)blocksize < 1) {
121    AUBIO_ERR("sampler: got blocksize %d, but can not be < 1\n", blocksize);
122    goto beach;
123  }
124  s->samplerate = samplerate;
125  s->blocksize = blocksize;
126  s->source = NULL;
127  s->playing = 0;
128  s->loop = 0;
129  s->uri = NULL;
130  s->finished = 1;
131  s->eof = 0;
132  s->opened = 0;
133  s->available = 0;
134
135  s->threaded_read = 0;
136  s->perfectloop = 0;
137#if 0 // naive mode
138  s->source_blocksize = s->blocksize;
139#elif 0 // threaded mode, no ringbuffer
140  s->source_blocksize = s->blocksize;
141  s->threaded_read = 1;
142#elif 0 // unthreaded, with ringbuffer
143  s->source_blocksize = 2048; //32 * s->blocksize;
144  s->perfectloop = 1;
145#elif 1 // threaded with ringhbuffer
146  s->source_blocksize = 2048; //32 * s->blocksize;
147  s->perfectloop = 1;
148  s->threaded_read = 1;
149#endif
150  // FIXME: perfectloop fails if source_blocksize > 2048 with source_avcodec
151  //s->source_blocksize = 8192;
152
153  if (s->perfectloop || s->source_blocksize != s->blocksize) {
154    s->source_output = new_fvec(s->source_blocksize);
155    s->ring = new_aubio_ringbuffer(s->source_blocksize, s->blocksize);
156  }
157  //s->channels = 1;
158  //s->source_moutput = new_fmat(s->source_blocksize, s->channels);
159
160#ifdef HAVE_THREADS
161  aubio_sampler_open_opening_thread(s);
162
163  if (s->threaded_read) {
164    //AUBIO_WRN("sampler: starting reading thread\n");
165    aubio_sampler_open_reading_thread(s);
166  }
167#endif
168
169  return s;
170beach:
171  AUBIO_FREE(s);
172  return NULL;
173}
174
175#ifdef HAVE_THREADS
176void aubio_sampler_open_opening_thread(aubio_sampler_t *s) {
177  pthread_mutex_init(&s->open_mutex, 0);
178  s->waited = 0;
179  s->open_thread = 0;
180  s->open_thread_running = 0;
181}
182
183void aubio_sampler_open_reading_thread(aubio_sampler_t *s) {
184  s->read_thread_finish = 0;
185  pthread_mutex_init(&s->read_mutex, 0);
186  pthread_cond_init (&s->read_avail, 0);
187  pthread_cond_init (&s->read_request, 0);
188  pthread_create(&s->read_thread, 0, aubio_sampler_readfn, s);
189}
190
191void aubio_sampler_close_opening_thread(aubio_sampler_t *o) {
192  // clean up opening thread
193  void *threadret;
194  pthread_mutex_destroy(&o->open_mutex);
195  if (o->open_thread_running) {
196    if (pthread_cancel(o->open_thread)) {
197      AUBIO_WRN("sampler: cancelling file opening thread failed\n");
198    }
199  }
200  if (o->open_thread && pthread_join(o->open_thread, &threadret)) {
201    AUBIO_WRN("sampler: joining file opening thread failed\n");
202  }
203  pthread_mutex_destroy(&o->open_mutex);
204}
205
206void aubio_sampler_close_reading_thread(aubio_sampler_t *o) {
207  // clean up reading thread
208  void *threadret;
209  if (!o->read_thread) return;
210  o->read_thread_finish = 1;
211  pthread_cond_signal(&o->read_request);
212  if (pthread_cancel(o->read_thread)) {
213    AUBIO_WRN("sampler: cancelling file reading thread failed\n");
214  }
215  if (pthread_join(o->read_thread, &threadret)) {
216    AUBIO_WRN("sampler: joining file reading thread failed\n");
217  }
218  pthread_mutex_destroy(&o->read_mutex);
219  pthread_cond_destroy(&o->read_avail);
220  pthread_cond_destroy(&o->read_request);
221}
222#endif
223
224uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri )
225{
226  uint_t ret = AUBIO_FAIL;
227  aubio_source_t *oldsource = o->source, *newsource = NULL;
228  newsource = new_aubio_source(uri, o->samplerate, o->source_blocksize);
229  if (newsource) {
230    o->source = newsource;
231    if (oldsource) del_aubio_source(oldsource);
232    if (o->samplerate == 0) {
233      o->samplerate = aubio_source_get_samplerate(o->source);
234    }
235    o->uri = uri;
236    o->finished = 0;
237    o->eof = 0;
238    o->opened = 1;
239    ret = AUBIO_OK;
240    AUBIO_MSG("sampler: loaded %s\n", uri);
241    if (o->waited) {
242      AUBIO_WRN("sampler: loading took %.2fms (%d samples)\n", 1000. *
243          o->waited / (smpl_t)o->samplerate, o->waited);
244    }
245  } else {
246    o->source = NULL;
247    if (oldsource) del_aubio_source(oldsource);
248    o->playing = 0;
249    o->uri = NULL;
250    o->finished = 1;
251    o->eof = 0;
252    o->opened = 0;
253    AUBIO_WRN("sampler: failed loading %s\n", uri);
254  }
255  if (o->ring) {
256    AUBIO_WRN("sampler: resetting ringbuffer\n");
257    aubio_ringbuffer_reset(o->ring);
258  }
259  return ret;
260}
261
262#ifdef HAVE_THREADS
263static void *aubio_sampler_openfn(void *z) {
264  aubio_sampler_t *p = z;
265  uint_t err;
266  int oldtype;
267  void *ret;
268  pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
269  pthread_mutex_lock(&p->open_mutex);
270  p->open_thread_running = 1;
271  err = aubio_sampler_load(p, p->next_uri);
272  p->open_thread_running = 0;
273  pthread_mutex_unlock(&p->open_mutex);
274  ret = &err;
275  pthread_exit(ret);
276}
277#endif
278
279uint_t
280aubio_sampler_queue(aubio_sampler_t *o, const char_t *uri)
281{
282#ifdef HAVE_THREADS
283  uint_t ret = AUBIO_OK;
284  /* open uri in open_thread */
285  if (o->open_thread_running) {
286    // cancel previous open_thread
287    if (pthread_cancel(o->open_thread)) {
288      AUBIO_WRN("sampler: failed queuing %s (cancelling existing open thread failed)\n", uri);
289      return AUBIO_FAIL;
290    } else {
291      AUBIO_WRN("sampler: cancelled queuing %s (queuing %s now)\n",
292          o->next_uri, uri);
293    }
294    o->open_thread_running = 0;
295  }
296  void *threadret;
297  if (o->open_thread && pthread_join(o->open_thread, &threadret)) {
298    AUBIO_WRN("sampler: joining thread failed\n");
299  }
300  if (pthread_mutex_trylock(&o->open_mutex)) {
301    AUBIO_WRN("sampler: failed queuing %s (locking failed)\n", uri);
302    ret = AUBIO_FAIL;
303    goto lock_failed;
304  }
305  o->opened = 0; // while opening
306  o->started = 0;
307  o->available = 0;
308  o->next_uri = uri;
309  o->waited = 0;
310  if (pthread_create(&o->open_thread, 0, aubio_sampler_openfn, o) != 0) {
311    AUBIO_ERR("sampler: failed creating opening thread\n");
312    ret = AUBIO_FAIL;
313    goto thread_create_failed;
314  }
315
316thread_create_failed:
317  pthread_mutex_unlock(&o->open_mutex);
318lock_failed:
319  if (ret == AUBIO_OK) {
320    //AUBIO_WRN("sampler: queued %s\n", uri);
321  } else {
322    AUBIO_ERR("sampler: queueing %s failed\n", uri);
323  }
324  return ret;
325#else
326  AUBIO_WRN("sampler: opening %s, not queueing (not compiled with threading)\n", uri);
327  return aubio_sampler_load(o, uri);
328#endif
329}
330
331#ifdef HAVE_THREADS
332
333uint_t aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s);
334
335void *aubio_sampler_readfn(void *z) {
336  aubio_sampler_t *p = z;
337  while(1) {
338    pthread_mutex_lock(&p->read_mutex);
339    if (p->open_thread_running) {
340      //AUBIO_WRN("sampler: readfn(): file is being opened\n");
341      pthread_cond_signal(&p->read_avail);
342      //pthread_cond_wait(&p->read_request, &p->read_mutex);
343    } else if (p->opened && !p->started && !p->finished) {
344      //AUBIO_WRN("sampler: readfn(): file started\n");
345      if (p->ring) {
346        p->available = aubio_sampler_reading_from_source_ring_fetch(p);
347      } else {
348        p->available = aubio_sampler_pull_from_source(p);
349        if (p->available < (sint_t)p->source_blocksize)
350          aubio_sampler_do_eof(p);
351      }
352      pthread_cond_signal(&p->read_avail);
353      if (!p->finished) {
354        pthread_cond_wait(&p->read_request, &p->read_mutex);
355      }
356    } else {
357      //AUBIO_WRN("sampler: readfn(): idle?\n");
358      //pthread_cond_signal(&p->read_avail);
359      pthread_cond_wait(&p->read_request, &p->read_mutex);
360      if (p->read_thread_finish) {
361        goto done;
362      }
363    }
364    pthread_mutex_unlock(&p->read_mutex);
365  }
366done:
367  //AUBIO_WRN("sampler: exiting reading thread\n");
368  pthread_mutex_unlock(&p->read_mutex);
369  pthread_exit(NULL);
370}
371
372void *aubio_sampler_readfn_ring(void *z) {
373  aubio_sampler_t *p = z;
374  while(1) {
375    pthread_mutex_lock(&p->read_mutex);
376    if (p->open_thread_running) {
377      //AUBIO_WRN("sampler: readfn(): file is being opened\n");
378      pthread_cond_signal(&p->read_avail);
379      //pthread_cond_wait(&p->read_request, &p->read_mutex);
380    } else if (p->opened && !p->started && !p->finished) {
381      //AUBIO_WRN("sampler: readfn(): file started\n");
382      p->available = aubio_sampler_pull_from_source(p);
383      if (p->available < (sint_t)p->source_blocksize)
384        aubio_sampler_do_eof(p);
385      pthread_cond_signal(&p->read_avail);
386      if (!p->finished) {
387        pthread_cond_wait(&p->read_request, &p->read_mutex);
388      }
389    } else {
390      //AUBIO_WRN("sampler: readfn(): idle?\n");
391      //pthread_cond_signal(&p->read_avail);
392      pthread_cond_wait(&p->read_request, &p->read_mutex);
393      if (p->read_thread_finish) {
394        goto done;
395      }
396    }
397    pthread_mutex_unlock(&p->read_mutex);
398  }
399done:
400  //AUBIO_WRN("sampler: exiting reading thread\n");
401  pthread_mutex_unlock(&p->read_mutex);
402  pthread_exit(NULL);
403}
404#endif
405
406void
407aubio_sampler_read(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
408  if (s->reading_from == aubio_sampler_reading_from_source) {
409    aubio_sampler_read_from_source(s, output, read);
410  } else if (s->reading_from == aubio_sampler_reading_from_table) {
411    aubio_sampler_read_from_table(s, output, read);
412  }
413}
414
415static void aubio_sampler_do_perfectloop(aubio_sampler_t *s);
416
417static void
418aubio_sampler_reading_from_source_naive(aubio_sampler_t *s, fvec_t * output,
419    uint_t *read)
420{
421  // directly read from disk
422  //aubio_source_do(s->source, output, read);
423  s->source_output = output;
424  *read = aubio_sampler_pull_from_source(s);
425  check_wrote += s->source_blocksize;
426  if (*read < s->source_blocksize) {
427    //AUBIO_WRN("sampler: calling go_eof in _read_from_source()\n");
428    aubio_sampler_do_eof(s);
429  }
430}
431
432uint_t
433aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s) {
434  // read source_blocksize (> blocksize) at once
435  int ring_avail = aubio_ringbuffer_get_available(s->ring);
436  //if (ring_avail < s->blocksize) {
437  uint_t available = 0;
438  if (ring_avail < (sint_t)s->blocksize) {
439    available = aubio_sampler_pull_from_source(s);
440#if 0
441    //AUBIO_MSG("sampler: got %d / %d fetching from source\n", s->available,
442    //    s->source_blocksize);
443    if (s->available == 0) {
444      //aubio_sampler_do_eof(s);
445      //aubio_sampler_do_perfectloop(s, output);
446    }
447    if (s->available < s->source_blocksize) {
448      AUBIO_ERR("sampler: short read from source"
449          " s->available %d, ring_avail %d \n", s->available, ring_avail);
450      //s->eof = 0;
451      //abort();
452    }
453#endif
454    if (available > 0) {
455      aubio_ringbuffer_push(s->ring, s->source_output, available);
456    } else {
457      //if (s->playing && !s->finished)
458      //AUBIO_WRN("sampler: not reading anymore should do eof now %d\n", check_wrote);
459      // TODO: move eof fetch now
460    }
461  }
462  return available;
463}
464
465uint_t
466aubio_sampler_write_remaining_ring(aubio_sampler_t *s, fvec_t *output, uint_t wrote);
467
468static void
469aubio_sampler_reading_from_source_ring_pull(aubio_sampler_t *s, fvec_t *output,
470    uint_t *read)
471{
472  // write into output
473  int ring_avail = aubio_ringbuffer_get_available(s->ring);
474  if (ring_avail >= (sint_t)s->blocksize) {
475    //AUBIO_MSG("sampler: pulling %d / %d from ringbuffer\n", s->blocksize, ring_avail);
476    aubio_ringbuffer_pull(s->ring, output, s->blocksize);
477    check_wrote += s->blocksize;
478    *read = s->blocksize;
479  } else {
480    //AUBIO_MSG("sampler: last frame, pulling remaining %d left\n", ring_avail);
481    *read = 0;
482    if (ring_avail > 0) {
483      // pull remaining frames in ring buffer
484      aubio_ringbuffer_pull(s->ring, output, ring_avail);
485      check_wrote += ring_avail;
486      *read += ring_avail;
487    }
488    // signal eof, seek to 0 if looping
489    aubio_sampler_do_eof(s);
490    // read new frames from source early if needed
491    aubio_sampler_do_perfectloop(s);
492    // write the remaining frames
493    *read += aubio_sampler_write_remaining_ring(s, output, ring_avail);
494  }
495}
496
497static void
498aubio_sampler_reading_from_source_ring(aubio_sampler_t *s, fvec_t *output,
499    uint_t *read)
500{
501  aubio_sampler_reading_from_source_ring_fetch(s);
502  aubio_sampler_reading_from_source_ring_pull(s, output, read);
503}
504
505#ifdef HAVE_THREADS
506static void
507aubio_sampler_read_from_source_threaded(aubio_sampler_t *s, fvec_t *output,
508    uint_t *read) {
509  // request at least output->length
510  // make sure we have enough samples read from source
511  int available;
512  pthread_mutex_lock(&s->read_mutex);
513  if (!s->opened || s->open_thread_running) {
514    //AUBIO_ERR("sampler: _read_from_source: not opened, signaling read_request\n");
515    pthread_cond_signal(&s->read_request);
516    available = 0;
517  } else if (!s->finished) {
518    //AUBIO_ERR("sampler: _read_from_source: waiting for read avail %d\n", s->started);
519    pthread_cond_signal(&s->read_request);
520    pthread_cond_wait(&s->read_avail, &s->read_mutex);
521    //AUBIO_ERR("sampler: _read_from_source: %d\n", s->available);
522    available = s->available;
523  } else {
524    //AUBIO_WRN("sampler: _read_from_source: eof\n");
525    pthread_cond_signal(&s->read_request);
526    available = 0;
527  }
528  pthread_mutex_unlock(&s->read_mutex);
529  //AUBIO_WRN("sampler: got %d available in _read_from_source\n", available);
530  // read -> number of samples read
531  if (!s->perfectloop && s->source_blocksize == s->blocksize) {
532    if (available >= (sint_t)s->blocksize) {
533      fvec_copy(s->source_output, output);
534      *read = s->blocksize;
535    } else if (available > 0) {
536      fvec_copy(s->source_output, output);
537      *read = available;
538    } else {
539      fvec_zeros(output);
540      *read = 0;
541    }
542  } else {
543    aubio_sampler_reading_from_source_ring_pull(s, output, read);
544  }
545  //*read = s->available;
546}
547#endif
548
549void
550aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
551#ifdef HAVE_THREADS
552  if (s->threaded_read) { // if threaded
553    aubio_sampler_read_from_source_threaded(s, output, read);
554  } else
555#endif
556  {
557    if (s->finished) {
558      *read = 0;
559    }
560    else if (s->source_blocksize == s->blocksize && !s->perfectloop) {
561      aubio_sampler_reading_from_source_naive(s, output, read);
562    } else {
563      aubio_sampler_reading_from_source_ring(s, output, read);
564    }
565#if 1
566    if (s->loop && s->perfectloop && *read != s->blocksize) { // && s->started && !s->finished) {
567      AUBIO_ERR("sampler: perfectloop but read only %d\n", *read);
568    }
569#endif
570  }
571}
572
573uint_t
574aubio_sampler_write_remaining_ring(aubio_sampler_t *s, fvec_t *output, uint_t wrote){
575  if (s->perfectloop && s->loop) {
576    fvec_t tmpout;
577    tmpout.data = output->data + wrote;
578    tmpout.length = s->blocksize - wrote;
579    aubio_ringbuffer_pull(s->ring, &tmpout, tmpout.length);
580    check_wrote += tmpout.length;
581    return tmpout.length;
582  }
583  return 0;
584}
585
586void
587aubio_sampler_do_perfectloop(aubio_sampler_t *s) {
588  // perfectloop fetched new samples from start of source to ringbuffer
589  if (s->perfectloop && s->loop) {
590    s->available = aubio_sampler_pull_from_source(s);
591    if (s->available <= 0) {
592      AUBIO_ERR("sampler: perfectloop but s->available = 0 !\n");
593    } else {
594      aubio_ringbuffer_push(s->ring, s->source_output, s->available);
595    }
596  }
597}
598
599void
600aubio_sampler_read_from_table(aubio_sampler_t *o, fvec_t *output, uint_t *read) {
601  *read = 0;
602  AUBIO_WRN("sampler: _pull_from_table not implemented for %d, %d, %d",
603      o, output->length, *read);
604}
605
606sint_t
607aubio_sampler_pull_from_source(aubio_sampler_t *s)
608{
609  // pull source_blocksize samples from source, return available frames
610  uint_t source_read = s->source_blocksize;
611  if (s->source == NULL) {
612    AUBIO_ERR("sampler: trying to fetch on NULL source\n");
613    return -1;
614  }
615  aubio_source_do(s->source, s->source_output, &source_read);
616  return source_read;
617}
618
619
620uint_t
621aubio_sampler_get_samplerate (aubio_sampler_t *o)
622{
623  return o->samplerate;
624}
625
626uint_t
627aubio_sampler_get_opened (aubio_sampler_t *o)
628{
629  return o->opened; //== 1 ? AUBIO_OK : AUBIO_FAIL;
630}
631
632uint_t
633aubio_sampler_get_finished(aubio_sampler_t *o)
634{
635  return o->finished;
636}
637
638uint_t
639aubio_sampler_get_eof (aubio_sampler_t *o)
640{
641  return o->eof;
642}
643
644uint_t
645aubio_sampler_get_waited_opening (aubio_sampler_t *o, uint_t waited) {
646#ifdef HAVE_THREADS
647  if (o->playing) {
648    if (!o->opened) {
649      o->waited += waited;
650    } else if (o->waited) {
651      //AUBIO_WRN("sampler: waited %d frames (%.2fms) while opening %s\n",
652      //    o->waited, 1000.*o->waited/(smpl_t)o->samplerate, o->uri);
653      uint_t waited = o->waited;
654      o->waited = 0;
655      return waited;
656    }
657  }
658#endif
659  return 0;
660}
661
662uint_t
663aubio_sampler_seek(aubio_sampler_t * o, uint_t pos)
664{
665  //AUBIO_WRN("sampler: seeking to 0\n");
666  uint_t ret = AUBIO_FAIL;
667  o->finished = 0;
668  if (!o->opened) return AUBIO_OK;
669  if (o->source) {
670    ret = aubio_source_seek(o->source, pos);
671  }
672  return ret;
673}
674
675void
676aubio_sampler_do_eof (aubio_sampler_t * o)
677{
678  //AUBIO_MSG("sampler: calling  _do_eof()\n");
679  o->finished = 1;
680  o->eof = 1;
681  if (!o->loop) {
682    o->playing = 0;
683  } else {
684    aubio_sampler_seek(o, 0);
685    //o->finished = 0;
686  }
687}
688
689void aubio_sampler_do ( aubio_sampler_t * o, fvec_t * output, uint_t *read)
690{
691  o->eof = 0;
692  if (o->opened == 1 && o->playing) {
693    aubio_sampler_read(o, output, read);
694    //AUBIO_WRN("sampler: _read got %d\n", *read);
695    if (*read < o->blocksize) {
696      if (*read > 0 && o->loop) {
697        // TODO pull (hopsize - read) frames
698      }
699    }
700  } else {
701    fvec_zeros(output);
702    *read = 0;
703  }
704}
705
706void aubio_sampler_do_multi ( aubio_sampler_t * o, fmat_t * output, uint_t *read)
707{
708  o->eof = 0;
709  if (o->opened == 1 && o->playing) {
710    //aubio_sampler_read_multi(o, output, read);
711    if (*read < o->blocksize) {
712      if (*read > 0) {
713        // TODO pull (hopsize - read) frames
714        //memset(...  tail , 0)
715      }
716    }
717  } else {
718    fmat_zeros(output);
719    *read = 0;
720  }
721}
722
723uint_t aubio_sampler_get_playing ( const aubio_sampler_t * o )
724{
725  return o->playing;
726}
727
728uint_t aubio_sampler_set_playing ( aubio_sampler_t * o, uint_t playing )
729{
730  o->playing = (playing == 1) ? 1 : 0;
731  return 0;
732}
733
734uint_t aubio_sampler_get_loop ( aubio_sampler_t * o )
735{
736  return o->loop;
737}
738
739uint_t aubio_sampler_set_loop ( aubio_sampler_t * o, uint_t loop )
740{
741  o->loop = (loop == 1) ? 1 : 0;
742  return 0;
743}
744
745uint_t aubio_sampler_play ( aubio_sampler_t * o )
746{
747  //aubio_source_seek (o->source, 0);
748  return aubio_sampler_set_playing (o, 1);
749}
750
751uint_t aubio_sampler_stop ( aubio_sampler_t * o )
752{
753  return aubio_sampler_set_playing (o, 0);
754}
755
756uint_t aubio_sampler_loop ( aubio_sampler_t * o )
757{
758  aubio_sampler_set_loop(o, 1);
759  aubio_sampler_seek(o, 0);
760  return aubio_sampler_set_playing (o, 1);
761}
762
763uint_t aubio_sampler_trigger ( aubio_sampler_t * o )
764{
765  aubio_sampler_set_loop(o, 0);
766  aubio_sampler_seek(o, 0);
767  return aubio_sampler_set_playing (o, 1);
768}
769
770void del_aubio_sampler( aubio_sampler_t * o )
771{
772  AUBIO_MSG("sampler: check_wrote: %d\n", check_wrote);
773#ifdef HAVE_THREADS
774  // close opening thread
775  aubio_sampler_close_opening_thread(o);
776  // close reading thread
777  aubio_sampler_close_reading_thread(o);
778#endif
779  //if (o->source_output) {
780  if (o->perfectloop || o->ring) {
781    del_fvec(o->source_output);
782  }
783  if (o->source_moutput) {
784    del_fmat(o->source_moutput);
785  }
786  if (o->ring) {
787    del_aubio_ringbuffer(o->ring);
788  }
789  if (o->source) {
790    del_aubio_source(o->source);
791  }
792  AUBIO_FREE(o);
793}
Note: See TracBrowser for help on using the repository browser.