source: src/synth/sampler.c @ 88a774c

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

src/synth/sampler.c: huge change adding a ringbuffer mode and preparing for the next steps

  • Property mode set to 100644
File size: 22.7 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#if 0 // naive mode
136  s->source_blocksize = s->blocksize;
137  s->perfectloop = 0;
138#elif 0 // threaded mode
139  s->source_blocksize = s->blocksize;
140  // FIXME: perfectloop fails if source_blocksize > 2048 ?!
141  //s->source_blocksize = 4096; //32 * s->blocksize;
142  s->perfectloop = 0;
143  s->threaded_read = 0;
144#elif 1 // unthreaded ringbuffer mode
145  s->source_blocksize = 2048; //32 * s->blocksize;
146  // FIXME: perfectloop fails if source_blocksize > 2048 ?!
147  //s->source_blocksize = 4096; //32 * s->blocksize;
148  s->perfectloop = 1;
149#endif
150
151  if (s->perfectloop || s->source_blocksize != s->blocksize) {
152    s->source_output = new_fvec(s->source_blocksize);
153    s->ring = new_aubio_ringbuffer(s->source_blocksize, s->blocksize);
154  }
155
156#ifdef HAVE_THREADS
157  aubio_sampler_open_opening_thread(s);
158
159  if (s->threaded_read) {
160    s->source_blocksize = s->blocksize;
161    //s->source_output = new_fvec(s->source_blocksize);
162    s->channels = 1;
163    s->source_moutput = new_fmat(s->source_blocksize, s->channels);
164    aubio_sampler_open_reading_thread(s);
165  } else if (0) {
166    s->source_blocksize = s->blocksize;
167  } else {
168    //s->source_blocksize = 16*s->blocksize;
169    //s->source_blocksize = 8192; //s->blocksize;
170    //s->ring = new_aubio_ringbuffer(s->source_blocksize, s->source_blocksize);
171  }
172#endif
173
174  return s;
175beach:
176  AUBIO_FREE(s);
177  return NULL;
178}
179
180#ifdef HAVE_THREADS
181void aubio_sampler_open_opening_thread(aubio_sampler_t *s) {
182  pthread_mutex_init(&s->open_mutex, 0);
183  s->waited = 0;
184  s->open_thread = 0;
185  s->open_thread_running = 0;
186}
187
188void aubio_sampler_open_reading_thread(aubio_sampler_t *s) {
189  s->read_thread_finish = 0;
190  pthread_mutex_init(&s->read_mutex, 0);
191  pthread_cond_init (&s->read_avail, 0);
192  pthread_cond_init (&s->read_request, 0);
193  pthread_create(&s->read_thread, 0, aubio_sampler_readfn, s);
194}
195
196void aubio_sampler_close_opening_thread(aubio_sampler_t *o) {
197  // clean up opening thread
198  void *threadret;
199  pthread_mutex_destroy(&o->open_mutex);
200  if (o->open_thread_running) {
201    if (pthread_cancel(o->open_thread)) {
202      AUBIO_WRN("sampler: cancelling file opening thread failed\n");
203    }
204  }
205  if (o->open_thread && pthread_join(o->open_thread, &threadret)) {
206    AUBIO_WRN("sampler: joining file opening thread failed\n");
207  }
208  pthread_mutex_destroy(&o->open_mutex);
209}
210
211void aubio_sampler_close_reading_thread(aubio_sampler_t *o) {
212  // clean up reading thread
213  void *threadret;
214  if (!o->read_thread) return;
215  o->read_thread_finish = 1;
216  pthread_cond_signal(&o->read_request);
217  if (pthread_cancel(o->read_thread)) {
218    AUBIO_WRN("sampler: cancelling file reading thread failed\n");
219  }
220  if (pthread_join(o->read_thread, &threadret)) {
221    AUBIO_WRN("sampler: joining file reading thread failed\n");
222  }
223  pthread_mutex_destroy(&o->read_mutex);
224  pthread_cond_destroy(&o->read_avail);
225  pthread_cond_destroy(&o->read_request);
226}
227#endif
228
229uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri )
230{
231  uint_t ret = AUBIO_FAIL;
232  aubio_source_t *oldsource = o->source, *newsource = NULL;
233  newsource = new_aubio_source(uri, o->samplerate, o->source_blocksize);
234  if (newsource) {
235    o->source = newsource;
236    if (oldsource) del_aubio_source(oldsource);
237    if (o->samplerate == 0) {
238      o->samplerate = aubio_source_get_samplerate(o->source);
239    }
240    o->uri = uri;
241    o->finished = 0;
242    o->eof = 0;
243    o->opened = 1;
244    ret = AUBIO_OK;
245    AUBIO_MSG("sampler: loaded %s\n", uri);
246    if (o->waited) {
247      AUBIO_WRN("sampler: loading took %.2fms (%d samples)\n", 1000. *
248          o->waited / (smpl_t)o->samplerate, o->waited);
249    }
250  } else {
251    o->source = NULL;
252    if (oldsource) del_aubio_source(oldsource);
253    o->playing = 0;
254    o->uri = NULL;
255    o->finished = 1;
256    o->eof = 0;
257    o->opened = 0;
258    AUBIO_WRN("sampler: failed loading %s\n", uri);
259  }
260  if (o->ring) {
261    AUBIO_WRN("sampler: resetting ringbuffer\n");
262    aubio_ringbuffer_reset(o->ring);
263  }
264  return ret;
265}
266
267#ifdef HAVE_THREADS
268static void *aubio_sampler_openfn(void *z) {
269  aubio_sampler_t *p = z;
270  uint_t err;
271  int oldtype;
272  void *ret;
273  pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
274  pthread_mutex_lock(&p->open_mutex);
275  p->open_thread_running = 1;
276  err = aubio_sampler_load(p, p->next_uri);
277  p->open_thread_running = 0;
278  pthread_mutex_unlock(&p->open_mutex);
279  ret = &err;
280  pthread_exit(ret);
281}
282#endif
283
284uint_t
285aubio_sampler_queue(aubio_sampler_t *o, const char_t *uri)
286{
287#ifdef HAVE_THREADS
288  uint_t ret = AUBIO_OK;
289  /* open uri in open_thread */
290  if (o->open_thread_running) {
291    // cancel previous open_thread
292    if (pthread_cancel(o->open_thread)) {
293      AUBIO_WRN("sampler: failed queuing %s (cancelling existing open thread failed)\n", uri);
294      return AUBIO_FAIL;
295    } else {
296      AUBIO_WRN("sampler: cancelled queuing %s (queuing %s now)\n",
297          o->next_uri, uri);
298    }
299    o->open_thread_running = 0;
300  }
301  void *threadret;
302  if (o->open_thread && pthread_join(o->open_thread, &threadret)) {
303    AUBIO_WRN("sampler: joining thread failed\n");
304  }
305  if (pthread_mutex_trylock(&o->open_mutex)) {
306    AUBIO_WRN("sampler: failed queuing %s (locking failed)\n", uri);
307    ret = AUBIO_FAIL;
308    goto lock_failed;
309  }
310  o->opened = 0; // while opening
311  o->started = 0;
312  o->available = 0;
313  o->next_uri = uri;
314  o->waited = 0;
315  if (pthread_create(&o->open_thread, 0, aubio_sampler_openfn, o) != 0) {
316    AUBIO_ERR("sampler: failed creating opening thread\n");
317    ret = AUBIO_FAIL;
318    goto thread_create_failed;
319  }
320
321thread_create_failed:
322  pthread_mutex_unlock(&o->open_mutex);
323lock_failed:
324  if (ret == AUBIO_OK) {
325    //AUBIO_WRN("sampler: queued %s\n", uri);
326  } else {
327    AUBIO_ERR("sampler: queueing %s failed\n", uri);
328  }
329  return ret;
330#else
331  AUBIO_WRN("sampler: opening %s, not queueing (not compiled with threading)\n", uri);
332  return aubio_sampler_load(o, uri);
333#endif
334}
335
336#ifdef HAVE_THREADS
337
338uint_t aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s);
339void *aubio_sampler_readfn(void *z) {
340  aubio_sampler_t *p = z;
341  while(1) {
342    pthread_mutex_lock(&p->read_mutex);
343    if (p->open_thread_running) {
344      //AUBIO_WRN("sampler: readfn(): file is being opened\n");
345      pthread_cond_signal(&p->read_avail);
346      //pthread_cond_wait(&p->read_request, &p->read_mutex);
347    } else if (p->opened && !p->started && !p->finished) {
348      //AUBIO_WRN("sampler: readfn(): file started\n");
349      if (p->ring) {
350        aubio_sampler_reading_from_source_ring_fetch(p);
351      } else {
352        p->available = aubio_sampler_pull_from_source(p);
353        if (p->available < (sint_t)p->source_blocksize)
354          aubio_sampler_do_eof(p);
355      }
356      pthread_cond_signal(&p->read_avail);
357      if (!p->finished) {
358        pthread_cond_wait(&p->read_request, &p->read_mutex);
359      }
360    } else {
361      //AUBIO_WRN("sampler: readfn(): idle?\n");
362      //pthread_cond_signal(&p->read_avail);
363      pthread_cond_wait(&p->read_request, &p->read_mutex);
364      if (p->read_thread_finish) {
365        goto done;
366      }
367    }
368    pthread_mutex_unlock(&p->read_mutex);
369  }
370done:
371  //AUBIO_WRN("sampler: exiting reading thread\n");
372  pthread_mutex_unlock(&p->read_mutex);
373  pthread_exit(NULL);
374}
375
376void *aubio_sampler_readfn_ring(void *z) {
377  aubio_sampler_t *p = z;
378  while(1) {
379    pthread_mutex_lock(&p->read_mutex);
380    if (p->open_thread_running) {
381      //AUBIO_WRN("sampler: readfn(): file is being opened\n");
382      pthread_cond_signal(&p->read_avail);
383      //pthread_cond_wait(&p->read_request, &p->read_mutex);
384    } else if (p->opened && !p->started && !p->finished) {
385      //AUBIO_WRN("sampler: readfn(): file started\n");
386      p->available = aubio_sampler_pull_from_source(p);
387      if (p->available < (sint_t)p->source_blocksize)
388        aubio_sampler_do_eof(p);
389      pthread_cond_signal(&p->read_avail);
390      if (!p->finished) {
391        pthread_cond_wait(&p->read_request, &p->read_mutex);
392      }
393    } else {
394      //AUBIO_WRN("sampler: readfn(): idle?\n");
395      //pthread_cond_signal(&p->read_avail);
396      pthread_cond_wait(&p->read_request, &p->read_mutex);
397      if (p->read_thread_finish) {
398        goto done;
399      }
400    }
401    pthread_mutex_unlock(&p->read_mutex);
402  }
403done:
404  //AUBIO_WRN("sampler: exiting reading thread\n");
405  pthread_mutex_unlock(&p->read_mutex);
406  pthread_exit(NULL);
407}
408#endif
409
410void
411aubio_sampler_read(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
412  if (s->reading_from == aubio_sampler_reading_from_source) {
413    aubio_sampler_read_from_source(s, output, read);
414  } else if (s->reading_from == aubio_sampler_reading_from_table) {
415    aubio_sampler_read_from_table(s, output, read);
416  }
417}
418
419static void aubio_sampler_do_perfectloop(aubio_sampler_t *s);
420
421static void
422aubio_sampler_reading_from_source_naive(aubio_sampler_t *s, fvec_t * output,
423    uint_t *read)
424{
425  // directly read from disk
426  //aubio_source_do(s->source, output, read);
427  s->source_output = output;
428  *read = aubio_sampler_pull_from_source(s);
429  check_wrote += s->source_blocksize;
430  if (*read < s->source_blocksize) {
431    //AUBIO_WRN("sampler: calling go_eof in _read_from_source()\n");
432    aubio_sampler_do_eof(s);
433  }
434}
435
436uint_t
437aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s) {
438  // read source_blocksize (> blocksize) at once
439  int ring_avail = aubio_ringbuffer_get_available(s->ring);
440  //if (ring_avail < s->blocksize) {
441  uint_t available = 0;
442  if (ring_avail < (sint_t)s->blocksize) {
443    available = aubio_sampler_pull_from_source(s);
444#if 0
445    //AUBIO_MSG("sampler: got %d / %d fetching from source\n", s->available,
446    //    s->source_blocksize);
447    if (s->available == 0) {
448      //aubio_sampler_do_eof(s);
449      //aubio_sampler_do_perfectloop(s, output);
450    }
451    if (s->available < s->source_blocksize) {
452      AUBIO_ERR("sampler: short read from source"
453          " s->available %d, ring_avail %d \n", s->available, ring_avail);
454      //s->eof = 0;
455      //abort();
456    }
457#endif
458    if (available > 0) {
459      aubio_ringbuffer_push(s->ring, s->source_output, available);
460    } else {
461      //if (s->playing && !s->finished)
462      //AUBIO_WRN("sampler: not reading anymore should do eof now %d\n", check_wrote);
463      // TODO: move eof fetch now
464    }
465  }
466  return available;
467}
468
469uint_t
470aubio_sampler_write_remaining_ring(aubio_sampler_t *s, fvec_t *output, uint_t wrote);
471
472static void
473aubio_sampler_reading_from_source_ring_pull(aubio_sampler_t *s, fvec_t *output,
474    uint_t *read)
475{
476  // write into output
477  int ring_avail = aubio_ringbuffer_get_available(s->ring);
478  if (ring_avail >= (sint_t)s->blocksize) {
479    //AUBIO_MSG("sampler: pulling %d / %d from ringbuffer\n", s->blocksize, ring_avail);
480    aubio_ringbuffer_pull(s->ring, output, s->blocksize);
481    check_wrote += s->blocksize;
482    *read = s->blocksize;
483  } else {
484    //AUBIO_MSG("sampler: last frame, pulling remaining %d left\n", ring_avail);
485    *read = 0;
486    if (ring_avail > 0) {
487      aubio_ringbuffer_pull(s->ring, output, ring_avail);
488      check_wrote += ring_avail;
489      *read += ring_avail;
490    }
491    aubio_sampler_do_eof(s);
492    aubio_sampler_do_perfectloop(s);
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 (available >= (sint_t)s->blocksize) {
532    fvec_copy(s->source_output, output);
533    *read = s->blocksize;
534  } else if (available > 0) {
535    fvec_copy(s->source_output, output);
536    *read = available;
537  } else {
538    fvec_zeros(output);
539    *read = 0;
540  }
541  //*read = s->available;
542}
543#endif
544
545void
546aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
547#ifdef HAVE_THREADS
548  if (s->threaded_read) { // if threaded
549    if (s->source_blocksize == s->blocksize) {
550      aubio_sampler_read_from_source_threaded(s, output, read);
551    } else {
552      //abort();
553    }
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    //*read += tmpout.length;
581#if 0
582    int ring_avail = aubio_ringbuffer_get_available(s->ring);
583    AUBIO_WRN("sampler: perfectloop, "
584        "%d left in ring, looping pulled %d more, wrote %d + %d\n",
585        ring_avail, s->available, wrote, tmpout.length);
586#endif
587    check_wrote += tmpout.length;
588    return tmpout.length;
589  }
590  return 0;
591}
592
593void
594aubio_sampler_do_perfectloop(aubio_sampler_t *s) {
595  // perfectloop fetched new samples from start of source to ringbuffer
596  if (s->perfectloop && s->loop) {
597    s->available = aubio_sampler_pull_from_source(s);
598    if (s->available <= 0) {
599      AUBIO_ERR("sampler: looping but s->available = 0 !\n");
600    } else {
601      //AUBIO_ERR("sampler: perfectloop fetch and push more\n");
602      aubio_ringbuffer_push(s->ring, s->source_output, s->available);
603    }
604  }
605}
606
607void
608aubio_sampler_read_from_table(aubio_sampler_t *o, fvec_t *output, uint_t *read) {
609  *read = 0;
610  AUBIO_WRN("sampler: _pull_from_table not implemented for %d, %d, %d",
611      o, output->length, *read);
612}
613
614sint_t
615aubio_sampler_pull_from_source(aubio_sampler_t *s)
616{
617  // pull source_blocksize samples from source, return available frames
618  uint_t source_read = s->source_blocksize;
619  if (s->source == NULL) {
620    AUBIO_ERR("sampler: trying to fetch on NULL source\n");
621    return -1;
622  }
623  // do actual reading
624  aubio_source_do(s->source, s->source_output, &source_read);
625#if 0
626  if (source_read < s->source_blocksize) {
627    //AUBIO_ERR("sampler: _pull_from_source: short read %d < %d\n", source_read,
628    //    s->source_blocksize);
629    //aubio_sampler_do_eof(s);
630    if (s->loop) {
631      AUBIO_ERR("sampler: _pull_from_source: loop, should seeking to 0? %d / %d\n",
632          source_read, s->source_blocksize);
633      //aubio_sampler_seek(s, 0);
634    }
635  }
636  //AUBIO_ERR("sampler: _pull_from_source: read %d / %d\n", source_read, length);
637#endif
638  return source_read;
639}
640
641
642uint_t
643aubio_sampler_get_samplerate (aubio_sampler_t *o)
644{
645  return o->samplerate;
646}
647
648uint_t
649aubio_sampler_get_opened (aubio_sampler_t *o)
650{
651  return o->opened; //== 1 ? AUBIO_OK : AUBIO_FAIL;
652}
653
654uint_t
655aubio_sampler_get_finished(aubio_sampler_t *o)
656{
657  return o->finished;
658}
659
660uint_t
661aubio_sampler_get_eof (aubio_sampler_t *o)
662{
663  return o->eof;
664}
665
666uint_t
667aubio_sampler_get_waited_opening (aubio_sampler_t *o, uint_t waited) {
668#ifdef HAVE_THREADS
669  if (o->playing) {
670    if (!o->opened) {
671      o->waited += waited;
672    } else if (o->waited) {
673      //AUBIO_WRN("sampler: waited %d frames (%.2fms) while opening %s\n",
674      //    o->waited, 1000.*o->waited/(smpl_t)o->samplerate, o->uri);
675      uint_t waited = o->waited;
676      o->waited = 0;
677      return waited;
678    }
679  }
680#endif
681  return 0;
682}
683
684uint_t
685aubio_sampler_seek(aubio_sampler_t * o, uint_t pos)
686{
687  //AUBIO_WRN("sampler: seeking to 0\n");
688  uint_t ret = AUBIO_FAIL;
689  o->finished = 0;
690  if (!o->opened) return AUBIO_OK;
691  if (o->source) {
692    ret = aubio_source_seek(o->source, pos);
693  }
694  return ret;
695}
696
697void
698aubio_sampler_do_eof (aubio_sampler_t * o)
699{
700  //AUBIO_MSG("sampler: calling  _do_eof()\n");
701  o->finished = 1;
702  o->eof = 1;
703  if (!o->loop) {
704    o->playing = 0;
705  } else {
706    aubio_sampler_seek(o, 0);
707    //o->finished = 0;
708  }
709}
710
711void aubio_sampler_do ( aubio_sampler_t * o, fvec_t * output, uint_t *read)
712{
713  o->eof = 0;
714  if (o->opened == 1 && o->playing) {
715    aubio_sampler_read(o, output, read);
716    //AUBIO_WRN("sampler: _read got %d\n", *read);
717    if (*read < o->blocksize) {
718      if (*read > 0 && o->loop) {
719        // TODO pull (hopsize - read) frames
720      }
721    }
722  } else {
723    fvec_zeros(output);
724    *read = 0;
725  }
726}
727
728void aubio_sampler_do_multi ( aubio_sampler_t * o, fmat_t * output, uint_t *read)
729{
730  o->eof = 0;
731  if (o->opened == 1 && o->playing) {
732    //aubio_sampler_read_multi(o, output, read);
733    if (*read < o->blocksize) {
734      if (*read > 0) {
735        // TODO pull (hopsize - read) frames
736        //memset(...  tail , 0)
737      }
738    }
739  } else {
740    fmat_zeros(output);
741    *read = 0;
742  }
743}
744
745uint_t aubio_sampler_get_playing ( const aubio_sampler_t * o )
746{
747  return o->playing;
748}
749
750uint_t aubio_sampler_set_playing ( aubio_sampler_t * o, uint_t playing )
751{
752  o->playing = (playing == 1) ? 1 : 0;
753  return 0;
754}
755
756uint_t aubio_sampler_get_loop ( aubio_sampler_t * o )
757{
758  return o->loop;
759}
760
761uint_t aubio_sampler_set_loop ( aubio_sampler_t * o, uint_t loop )
762{
763  o->loop = (loop == 1) ? 1 : 0;
764  return 0;
765}
766
767uint_t aubio_sampler_play ( aubio_sampler_t * o )
768{
769  //aubio_source_seek (o->source, 0);
770  return aubio_sampler_set_playing (o, 1);
771}
772
773uint_t aubio_sampler_stop ( aubio_sampler_t * o )
774{
775  return aubio_sampler_set_playing (o, 0);
776}
777
778uint_t aubio_sampler_loop ( aubio_sampler_t * o )
779{
780  aubio_sampler_set_loop(o, 1);
781  aubio_sampler_seek(o, 0);
782  return aubio_sampler_set_playing (o, 1);
783}
784
785uint_t aubio_sampler_trigger ( aubio_sampler_t * o )
786{
787  aubio_sampler_set_loop(o, 0);
788  aubio_sampler_seek(o, 0);
789  return aubio_sampler_set_playing (o, 1);
790}
791
792void del_aubio_sampler( aubio_sampler_t * o )
793{
794  AUBIO_MSG("sampler: check_wrote: %d\n", check_wrote);
795#ifdef HAVE_THREADS
796  // close opening thread
797  aubio_sampler_close_opening_thread(o);
798  // close reading thread
799  aubio_sampler_close_reading_thread(o);
800#endif
801  //if (o->source_output) {
802  if (o->perfectloop || o->ring) {
803    del_fvec(o->source_output);
804  }
805  if (o->source_moutput) {
806    del_fmat(o->source_moutput);
807  }
808  if (o->ring) {
809    del_aubio_ringbuffer(o->ring);
810  }
811  if (o->source) {
812    del_aubio_source(o->source);
813  }
814  AUBIO_FREE(o);
815}
Note: See TracBrowser for help on using the repository browser.