source: src/synth/sampler.c @ 943ef49

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

src/synth/sampler.h: add _{get,set}_perfectloop

  • 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
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->threaded_read || s->perfectloop)
157    s->source_output = new_fvec(s->source_blocksize);
158  if (s->perfectloop || s->source_blocksize != s->blocksize) {
159    s->ring = new_aubio_ringbuffer(s->source_blocksize * 2, s->blocksize);
160  }
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_MSG("sampler: loaded %s\n", uri);
263    if (o->waited) {
264      AUBIO_WRN("sampler: loading took %.2fms (%d samples)\n", 1000. *
265          o->waited / (smpl_t)o->samplerate, o->waited);
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        s->eof = 1;
473        s->eof_remaining = 0;
474      } else if (s->eof_remaining <= s->source_blocksize) {
475        s->eof_remaining -= s->blocksize;
476      }
477    }
478  } else {
479    //AUBIO_MSG("sampler: last frame, pulling remaining %d left\n", ring_avail);
480    *read = 0;
481    if (ring_avail > 0) {
482      // pull remaining frames in ring buffer
483      aubio_ringbuffer_pull(s->ring, output, ring_avail);
484      *read += ring_avail;
485    }
486    // signal eof
487    aubio_sampler_do_eof(s);
488    // finished playing, reset ringbuffer for next read
489    if (!s->playing)
490      aubio_ringbuffer_reset(s->ring);
491  }
492}
493
494static void
495aubio_sampler_reading_from_source_ring(aubio_sampler_t *s, fvec_t *output,
496    uint_t *read)
497{
498  aubio_sampler_reading_from_source_ring_fetch(s);
499  aubio_sampler_reading_from_source_ring_pull(s, output, read);
500}
501
502#ifdef HAVE_THREADS
503static void
504aubio_sampler_read_from_source_threaded(aubio_sampler_t *s, fvec_t *output,
505    uint_t *read) {
506  // request at least output->length
507  // make sure we have enough samples read from source
508  int available;
509  pthread_mutex_lock(&s->read_mutex);
510  if (!s->opened || s->open_thread_running) {
511    //AUBIO_ERR("sampler: _read_from_source: not opened, signaling read_request\n");
512    pthread_cond_signal(&s->read_request);
513    available = 0;
514  } else if (!s->finished) {
515    pthread_cond_signal(&s->read_request);
516    pthread_cond_wait(&s->read_avail, &s->read_mutex);
517    //AUBIO_ERR("sampler: _read_from_source: %d\n", s->available);
518    available = s->available;
519  } else {
520    //AUBIO_WRN("sampler: _read_from_source: eof\n");
521    pthread_cond_signal(&s->read_request);
522    available = 0;
523  }
524  pthread_mutex_unlock(&s->read_mutex);
525  //AUBIO_WRN("sampler: got %d available in _read_from_source\n", available);
526  // read -> number of samples read
527  if (!s->perfectloop && s->source_blocksize == s->blocksize) {
528    if (available >= (sint_t)s->blocksize) {
529      fvec_copy(s->source_output, output);
530      *read = s->blocksize;
531    } else if (available > 0) {
532      fvec_copy(s->source_output, output);
533      *read = available;
534    } else {
535      fvec_zeros(output);
536      *read = 0;
537    }
538  } else {
539    aubio_sampler_reading_from_source_ring_pull(s, output, read);
540  }
541}
542#endif
543
544void
545aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
546#ifdef HAVE_THREADS
547  if (s->threaded_read) { // if threaded
548    aubio_sampler_read_from_source_threaded(s, output, read);
549  } else
550#endif
551  {
552    if (s->finished) {
553      *read = 0;
554    }
555    else if (s->source_blocksize == s->blocksize && !s->perfectloop) {
556      aubio_sampler_reading_from_source_naive(s, output, read);
557    } else {
558      aubio_sampler_reading_from_source_ring(s, output, read);
559    }
560#if 1
561    if (s->loop && s->perfectloop && *read != s->blocksize) { // && s->started && !s->finished) {
562      AUBIO_ERR("sampler: perfectloop but read only %d\n", *read);
563    }
564#endif
565  }
566}
567
568void
569aubio_sampler_read_from_table(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
570  *read = 0;
571  if (s->table == NULL) {
572    AUBIO_WRN("sampler: _pull_from_table but table not set %d, %d\n",
573        output->length, *read);
574  } else if (s->playing) {
575    uint_t available = s->table->length - s->table_index;
576    fvec_t tmp;
577    tmp.data = s->table->data + s->table_index;
578    if (available < s->blocksize) {
579      //AUBIO_WRN("sampler: _pull_from_table: table length %d, index: %d, read %d\n",
580      //    s->table->length, s->table_index, *read);
581      tmp.length = available;
582      fvec_t tmpout; tmpout.data = output->data; tmpout.length = available;
583      fvec_copy(&tmp, &tmpout);
584      if (s->loop && s->perfectloop) {
585        uint_t remaining = s->blocksize - available;
586        tmpout.data = output->data + available; tmpout.length = remaining;
587        tmp.data = s->table->data; tmp.length = remaining;
588        fvec_copy(&tmp, &tmpout);
589        s->table_index = remaining;
590        *read = s->blocksize;
591      } else {
592        s->table_index = 0;
593        *read = available;
594      }
595      aubio_sampler_do_eof(s);
596    } else {
597      tmp.length = s->blocksize;
598      fvec_copy(&tmp, output);
599      s->table_index += output->length;
600      *read = s->blocksize;
601    }
602  }
603}
604
605uint_t
606aubio_sampler_set_table(aubio_sampler_t *s, fvec_t *samples) {
607  if (!samples || !s) return AUBIO_FAIL;
608  if (s->reading_from == aubio_sampler_reading_from_source) {
609    //aubio_sampler_close_reading_thread(s);
610  }
611  s->table = samples;
612  //AUBIO_INF("sampler: setting table (%d long)\n", s->table->length);
613  s->table_index = 0;
614  s->reading_from = aubio_sampler_reading_from_table;
615  //s->threaded_read = 0;
616  s->opened = 1;
617  s->finished = 1;
618  return AUBIO_OK;
619}
620
621sint_t
622aubio_sampler_pull_from_source(aubio_sampler_t *s)
623{
624  // pull source_blocksize samples from source, return available frames
625  uint_t source_read = s->source_blocksize;
626  if (s->source == NULL) {
627    AUBIO_ERR("sampler: trying to fetch on NULL source\n");
628    return -1;
629  }
630  aubio_source_do(s->source, s->source_output, &source_read);
631  return source_read;
632}
633
634
635uint_t
636aubio_sampler_get_samplerate (aubio_sampler_t *o)
637{
638  return o->samplerate;
639}
640
641uint_t
642aubio_sampler_get_opened (aubio_sampler_t *o)
643{
644  return o->opened; //== 1 ? AUBIO_OK : AUBIO_FAIL;
645}
646
647uint_t
648aubio_sampler_get_finished(aubio_sampler_t *o)
649{
650  return o->finished;
651}
652
653uint_t
654aubio_sampler_get_eof (aubio_sampler_t *o)
655{
656  return o->eof;
657}
658
659uint_t
660aubio_sampler_get_waited_opening (aubio_sampler_t *o, uint_t waited) {
661#ifdef HAVE_THREADS
662  if (o->playing) {
663    if (!o->opened) {
664      o->waited += waited;
665    } else if (o->waited) {
666      //AUBIO_WRN("sampler: waited %d frames (%.2fms) while opening %s\n",
667      //    o->waited, 1000.*o->waited/(smpl_t)o->samplerate, o->uri);
668      uint_t waited = o->waited;
669      o->waited = 0;
670      return waited;
671    }
672  }
673#endif
674  return 0;
675}
676
677uint_t
678aubio_sampler_seek(aubio_sampler_t * o, uint_t pos)
679{
680  //AUBIO_WRN("sampler: seeking to 0\n");
681  uint_t ret = AUBIO_FAIL;
682  o->finished = 0;
683  if (!o->opened) return AUBIO_OK;
684  if (o->source) {
685    ret = aubio_source_seek(o->source, pos);
686  } else {
687    o->table_index = pos;
688  }
689  return ret;
690}
691
692void
693aubio_sampler_do_eof (aubio_sampler_t * o)
694{
695  //AUBIO_MSG("sampler: calling  _do_eof()\n");
696  o->finished = 1;
697  o->eof = 1;
698  if (!o->loop) {
699    o->playing = 0;
700  } else {
701    if (o->reading_from == aubio_sampler_reading_from_source)
702      aubio_sampler_seek(o, 0);
703    //o->finished = 0;
704  }
705}
706
707void aubio_sampler_do ( aubio_sampler_t * o, fvec_t * output, uint_t *read)
708{
709  o->eof = 0;
710  if (o->opened == 1 && o->playing) {
711    aubio_sampler_read(o, output, read);
712    //AUBIO_WRN("sampler: _read got %d\n", *read);
713    if (*read < o->blocksize) {
714      if (*read > 0 && o->loop) {
715        // TODO pull (hopsize - read) frames
716      }
717    }
718  } else {
719    fvec_zeros(output);
720    *read = 0;
721  }
722}
723
724void aubio_sampler_do_multi ( aubio_sampler_t * o, fmat_t * output, uint_t *read)
725{
726  o->eof = 0;
727  if (o->opened == 1 && o->playing) {
728    //aubio_sampler_read_multi(o, output, read);
729    if (*read < o->blocksize) {
730      if (*read > 0) {
731        // TODO pull (hopsize - read) frames
732        //memset(...  tail , 0)
733      }
734    }
735  } else {
736    fmat_zeros(output);
737    *read = 0;
738  }
739}
740
741uint_t aubio_sampler_get_playing ( const aubio_sampler_t * o )
742{
743  return o->playing;
744}
745
746uint_t aubio_sampler_set_playing ( aubio_sampler_t * o, uint_t playing )
747{
748  o->playing = (playing == 1) ? 1 : 0;
749  return 0;
750}
751
752uint_t aubio_sampler_get_loop ( aubio_sampler_t * o )
753{
754  return o->loop;
755}
756
757uint_t aubio_sampler_set_loop ( aubio_sampler_t * o, uint_t loop )
758{
759  o->loop = (loop == 1) ? 1 : 0;
760  return 0;
761}
762
763uint_t aubio_sampler_play ( aubio_sampler_t * o )
764{
765  //aubio_source_seek (o->source, 0);
766  return aubio_sampler_set_playing (o, 1);
767}
768
769uint_t aubio_sampler_stop ( aubio_sampler_t * o )
770{
771  return aubio_sampler_set_playing (o, 0);
772}
773
774uint_t aubio_sampler_loop ( aubio_sampler_t * o )
775{
776  aubio_sampler_set_loop(o, 1);
777  aubio_sampler_seek(o, 0);
778  return aubio_sampler_set_playing (o, 1);
779}
780
781uint_t aubio_sampler_trigger ( aubio_sampler_t * o )
782{
783  aubio_sampler_set_loop(o, 0);
784  aubio_sampler_seek(o, 0);
785  return aubio_sampler_set_playing (o, 1);
786}
787
788uint_t aubio_sampler_set_perfectloop (aubio_sampler_t *s, uint_t perfectloop) {
789  if (!s) return AUBIO_FAIL;
790  s->perfectloop = perfectloop;
791  return AUBIO_OK;
792}
793
794uint_t aubio_sampler_get_perfectloop (aubio_sampler_t *s) {
795  if (!s) return AUBIO_FAIL;
796  return s->perfectloop;
797}
798
799void del_aubio_sampler( aubio_sampler_t * o )
800{
801#ifdef HAVE_THREADS
802  // close opening thread
803  aubio_sampler_close_opening_thread(o);
804  // close reading thread
805  aubio_sampler_close_reading_thread(o);
806#endif
807  //if (o->source_output) {
808  if (o->source_output && (o->threaded_read || o->perfectloop)) {
809    del_fvec(o->source_output);
810  }
811  if (o->source_moutput) {
812    del_fmat(o->source_moutput);
813  }
814  if (o->ring) {
815    del_aubio_ringbuffer(o->ring);
816  }
817  if (o->source) {
818    del_aubio_source(o->source);
819  }
820  AUBIO_FREE(o);
821}
Note: See TracBrowser for help on using the repository browser.