source: src/synth/sampler.c @ d02d8f0

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

src/synth/sampler.c: alwasy signal read_avail in idle

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