source: src/synth/sampler.c @ 1686fcf

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

src/synth/sampler.h: add aubio_sampler_get_duration

  • Property mode set to 100644
File size: 30.0 KB
Line 
1/*
2  Copyright (C) 2003-2017 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 "aubio_priv.h"
24#include "fvec.h"
25#include "fmat.h"
26#include "io/source.h"
27#include "utils/ringbuffer.h"
28#include "effects/timestretch.h"
29#include "synth/sampler.h"
30
31#ifdef HAVE_PTHREAD_H
32#define HAVE_THREADS 1
33#include <pthread.h>
34#else
35#ifdef _MSC_VER
36#pragma message ("WARNING: compiling sampler without threading")
37#else
38#warning "compiling sampler without threading"
39#endif
40#endif
41
42typedef enum {
43  aubio_sampler_reading_from_source,
44  aubio_sampler_reading_from_table,
45  aubio_sampler_n_reading_methods
46} aubio_sampler_reading_method;
47
48
49typedef enum {
50  aubio_sampler_interp_pitchtime,
51  aubio_sampler_interp_quad,
52  aubio_sampler_interp_lin,
53  aubio_sampler_n_interp_methods
54} aubio_sampler_interp_method;
55
56struct _aubio_sampler_t {
57  uint_t samplerate;
58  uint_t blocksize;
59  uint_t duration;
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  aubio_ringbuffer_t *ring;
65  uint_t perfectloop;
66  uint_t eof_remaining;
67  // reading from a table
68  fvec_t *table;
69  uint_t table_index;
70  // reading from a source
71  aubio_source_t *source;
72  char_t *uri;
73  uint_t playing;
74  uint_t opened;
75  uint_t loop;
76  uint_t finished;              // end of file was reached
77  uint_t eof;                   // end of file is now
78  // time stretching
79  aubio_timestretch_t *ts;
80  sint_t available;             // number of samples currently available
81  uint_t started;               // source warmed up
82  // source
83  uint_t source_blocksize;
84  uint_t channels;
85  fvec_t *source_output;
86  fmat_t *source_moutput;
87  //fvec_t *source_output_tmp;
88  //uint_t last_read;
89  uint_t threaded_read;         // use reading thread?
90#ifdef HAVE_THREADS
91  // file reading thread
92  pthread_t read_thread;
93  pthread_mutex_t read_mutex;
94  pthread_cond_t read_avail;
95  pthread_cond_t read_request;
96  // file opening thread
97  pthread_t open_thread;
98  pthread_mutex_t open_mutex;
99  uint_t waited;                // number of frames skipped while opening
100  char_t *next_uri;
101  uint_t open_thread_running;
102  uint_t read_thread_finish;    // flag to tell reading thread to exit
103#endif
104};
105
106static sint_t aubio_sampler_pull_from_source(aubio_sampler_t *s);
107
108static void aubio_sampler_do_eof(aubio_sampler_t *s);
109
110static void aubio_sampler_read(aubio_sampler_t *s, fvec_t *output, uint_t *read);
111static void aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read);
112static void aubio_sampler_read_from_table(aubio_sampler_t *s, fvec_t *output, uint_t *read);
113
114#ifdef HAVE_THREADS
115static void *aubio_sampler_openfn(void *p);
116static void *aubio_sampler_readfn(void *p);
117static void aubio_sampler_open_opening_thread(aubio_sampler_t *o);
118static void aubio_sampler_open_reading_thread(aubio_sampler_t *o);
119static void aubio_sampler_close_opening_thread(aubio_sampler_t *o);
120static void aubio_sampler_close_reading_thread(aubio_sampler_t *o);
121#endif
122
123aubio_sampler_t *new_aubio_sampler(uint_t blocksize, uint_t samplerate)
124{
125  aubio_sampler_t *s = AUBIO_NEW(aubio_sampler_t);
126  if ((sint_t)blocksize < 1) {
127    AUBIO_ERR("sampler: got blocksize %d, but can not be < 1\n", blocksize);
128    goto beach;
129  }
130  s->samplerate = samplerate;
131  s->blocksize = blocksize;
132  s->duration = 0;
133  s->source = NULL;
134  s->playing = 0;
135  s->loop = 0;
136  s->uri = NULL;
137  s->finished = 1;
138  s->eof = 0;
139  s->opened = 0;
140  s->available = 0;
141
142  s->perfectloop = 0;
143#if 0 // naive mode
144  s->source_blocksize = s->blocksize;
145#elif 0 // threaded mode, no ringbuffer
146  s->source_blocksize = s->blocksize;
147  s->threaded_read = 1;
148#elif 0 // unthreaded, with ringbuffer
149  s->source_blocksize = 2048; //32 * s->blocksize;
150  s->perfectloop = 1;
151#elif 1 // threaded with ringhbuffer
152  s->source_blocksize = 2048; //32 * s->blocksize;
153  s->perfectloop = 1;
154#endif
155
156#ifdef HAVE_THREADS
157  // disabled for now
158  s->threaded_read = 0;
159#else
160  s->threaded_read = 0;
161#endif
162
163  s->perfectloop = 1;
164
165  if (s->source_blocksize < s->blocksize) {
166    s->source_blocksize = s->blocksize;
167  }
168  // FIXME: perfectloop fails if source_blocksize > 2048 with source_avcodec
169  //s->source_blocksize = 8192;
170
171  if (s->perfectloop || s->source_blocksize != s->blocksize) {
172    s->ring = new_aubio_ringbuffer(s->source_blocksize * 2, s->blocksize);
173  }
174  if (s->threaded_read || s->perfectloop || s->ring)
175    s->source_output = new_fvec(s->source_blocksize);
176  //s->channels = 1;
177  //s->source_moutput = new_fmat(s->source_blocksize, s->channels);
178
179#ifdef HAVE_THREADS
180  aubio_sampler_open_opening_thread(s);
181
182  if (s->threaded_read) {
183    //AUBIO_WRN("sampler: starting reading thread\n");
184    aubio_sampler_open_reading_thread(s);
185  }
186#endif
187
188#if 0
189  s->reading_from = aubio_sampler_reading_from_table;
190  s->perfectloop = 1;
191  s->threaded_read = 0;
192  s->opened = 1;
193  s->finished = 1;
194  s->table_index = 0;
195#endif
196
197  s->ts = new_aubio_timestretch("default", 1., s->blocksize, s->samplerate);
198  //s->source_output_tmp = new_fvec(s->source_blocksize);
199  //s->last_read = 0;
200
201  return s;
202beach:
203  AUBIO_FREE(s);
204  return NULL;
205}
206
207#ifdef HAVE_THREADS
208void aubio_sampler_open_opening_thread(aubio_sampler_t *s) {
209  pthread_mutex_init(&s->open_mutex, 0);
210  s->waited = 0;
211  s->open_thread = 0;
212  s->open_thread_running = 0;
213}
214
215void aubio_sampler_open_reading_thread(aubio_sampler_t *s) {
216  s->read_thread_finish = 0;
217  pthread_mutex_init(&s->read_mutex, 0);
218  pthread_cond_init (&s->read_avail, 0);
219  pthread_cond_init (&s->read_request, 0);
220  pthread_create(&s->read_thread, 0, aubio_sampler_readfn, s);
221}
222
223void aubio_sampler_close_opening_thread(aubio_sampler_t *o) {
224  // clean up opening thread
225  void *threadret;
226  if (!o->open_thread) return;
227  pthread_mutex_destroy(&o->open_mutex);
228  if (o->open_thread_running) {
229    if (pthread_cancel(o->open_thread)) {
230      AUBIO_WRN("sampler: cancelling file opening thread failed\n");
231    }
232  }
233  if (o->open_thread && pthread_join(o->open_thread, &threadret)) {
234    AUBIO_WRN("sampler: joining file opening thread failed\n");
235  }
236  pthread_mutex_destroy(&o->open_mutex);
237  o->open_thread = 0;
238}
239
240void aubio_sampler_close_reading_thread(aubio_sampler_t *o) {
241  // clean up reading thread
242  void *threadret;
243  if (!o->read_thread) return;
244  o->read_thread_finish = 1;
245  pthread_cond_signal(&o->read_request);
246  if (pthread_cancel(o->read_thread)) {
247    AUBIO_WRN("sampler: cancelling file reading thread failed\n");
248  }
249  if (pthread_join(o->read_thread, &threadret)) {
250    AUBIO_WRN("sampler: joining file reading thread failed\n");
251  }
252  pthread_mutex_destroy(&o->read_mutex);
253  pthread_cond_destroy(&o->read_avail);
254  pthread_cond_destroy(&o->read_request);
255  o->read_thread = 0;
256}
257#endif
258
259uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri )
260{
261  uint_t ret = AUBIO_FAIL;
262  aubio_source_t *oldsource = o->source, *newsource = NULL;
263  newsource = new_aubio_source(uri, o->samplerate, o->source_blocksize);
264  if (newsource) {
265    uint_t duration = aubio_source_get_duration(newsource);
266    if (duration < o->blocksize) {
267      AUBIO_WRN("sampler: %s is %d frames long, but blocksize is %d\n",
268          uri, duration, o->blocksize);
269    }
270    o->source = newsource;
271    if (oldsource) del_aubio_source(oldsource);
272    if (o->samplerate == 0) {
273      o->samplerate = aubio_source_get_samplerate(o->source);
274    }
275    if (o->uri) AUBIO_FREE(o->uri);
276    o->uri = AUBIO_ARRAY(char_t, strnlen(uri, PATH_MAX) + 1);
277    strncpy(o->uri, uri, strnlen(uri, PATH_MAX) + 1);
278    o->finished = 0;
279    o->eof = 0;
280    o->eof_remaining = 0;
281    o->opened = 1;
282    ret = AUBIO_OK;
283    o->duration = duration;
284    AUBIO_MSG("sampler: loaded %s\n", uri);
285#ifdef HAVE_THREADS
286    if (o->waited) {
287      AUBIO_WRN("sampler: %.2fms (%d samples) taken to load %s\n", 1000. *
288          o->waited / (smpl_t)o->samplerate, o->waited, o->uri);
289    }
290#endif
291  } else {
292    o->source = NULL;
293    if (oldsource) del_aubio_source(oldsource);
294    o->playing = 0;
295    o->uri = NULL;
296    o->finished = 1;
297    o->eof = 0;
298    o->eof_remaining = 0;
299    o->opened = 0;
300    AUBIO_WRN("sampler: failed loading %s\n", uri);
301  }
302  if (o->ring) {
303    //AUBIO_WRN("sampler: resetting ringbuffer\n");
304    aubio_ringbuffer_reset(o->ring);
305  }
306  return ret;
307}
308
309#ifdef HAVE_THREADS
310static void *aubio_sampler_openfn(void *z) {
311  aubio_sampler_t *p = z;
312  uint_t err;
313  int oldtype;
314  void *ret;
315  pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
316  pthread_mutex_lock(&p->open_mutex);
317  p->open_thread_running = 1;
318  err = aubio_sampler_load(p, p->next_uri);
319  p->open_thread_running = 0;
320  pthread_mutex_unlock(&p->open_mutex);
321  ret = &err;
322  pthread_exit(ret);
323}
324#endif
325
326uint_t
327aubio_sampler_queue(aubio_sampler_t *o, const char_t *uri)
328{
329#ifdef HAVE_THREADS
330  uint_t ret = AUBIO_OK;
331
332  if (o->reading_from == aubio_sampler_reading_from_table) {
333    o->reading_from = aubio_sampler_reading_from_source;
334    o->opened = 0;
335    o->finished = 1;
336  }
337  /* open uri in open_thread */
338  if (o->open_thread_running) {
339    // cancel previous open_thread
340    if (pthread_cancel(o->open_thread)) {
341      AUBIO_WRN("sampler: failed queuing %s (cancelling existing open thread failed)\n", uri);
342      return AUBIO_FAIL;
343    } else {
344      AUBIO_WRN("sampler: cancelled queuing %s (queuing %s now)\n",
345          o->next_uri, uri);
346    }
347    o->open_thread_running = 0;
348  }
349  void *threadret;
350  if (o->open_thread && pthread_join(o->open_thread, &threadret)) {
351    AUBIO_WRN("sampler: joining thread failed\n");
352  }
353  if (pthread_mutex_trylock(&o->open_mutex)) {
354    AUBIO_WRN("sampler: failed queuing %s (locking failed)\n", uri);
355    ret = AUBIO_FAIL;
356    goto lock_failed;
357  }
358  o->opened = 0; // while opening
359  o->started = 0;
360  o->available = 0;
361  if (o->next_uri) AUBIO_FREE(o->next_uri);
362  o->next_uri = AUBIO_ARRAY(char_t, strnlen(uri, PATH_MAX) + 1);
363  strncpy(o->next_uri, uri, strnlen(uri, PATH_MAX) + 1);
364  o->waited = 0;
365  if (pthread_create(&o->open_thread, 0, aubio_sampler_openfn, o) != 0) {
366    AUBIO_ERR("sampler: failed creating opening thread\n");
367    ret = AUBIO_FAIL;
368    goto thread_create_failed;
369  }
370
371thread_create_failed:
372  pthread_mutex_unlock(&o->open_mutex);
373lock_failed:
374  if (ret == AUBIO_OK) {
375    //AUBIO_WRN("sampler: queued %s\n", uri);
376  } else {
377    AUBIO_ERR("sampler: queueing %s failed\n", uri);
378  }
379  return ret;
380#else
381  AUBIO_WRN("sampler: opening %s, not queueing (not compiled with threading)\n", uri);
382  return aubio_sampler_load(o, uri);
383#endif
384}
385
386#ifdef HAVE_THREADS
387
388uint_t aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s);
389
390void *aubio_sampler_readfn(void *z) {
391  aubio_sampler_t *p = z;
392  while(1) {
393    pthread_mutex_lock(&p->read_mutex);
394    if (p->open_thread_running) {
395      //AUBIO_WRN("sampler: readfn(): file is being opened\n");
396      pthread_cond_signal(&p->read_avail);
397      //pthread_cond_wait(&p->read_request, &p->read_mutex);
398    } else if (p->opened && !p->started && !p->finished) {
399      //AUBIO_WRN("sampler: readfn(): file started\n");
400      if (p->ring) {
401        p->available = aubio_sampler_reading_from_source_ring_fetch(p);
402      } else {
403        p->available = aubio_sampler_pull_from_source(p);
404        if (p->available < (sint_t)p->source_blocksize)
405          aubio_sampler_do_eof(p);
406      }
407      pthread_cond_signal(&p->read_avail);
408      if (!p->finished) {
409        pthread_cond_wait(&p->read_request, &p->read_mutex);
410      }
411    } else {
412      //AUBIO_WRN("sampler: readfn(): idle?\n");
413      pthread_cond_signal(&p->read_avail);
414      pthread_cond_wait(&p->read_request, &p->read_mutex);
415      if (p->read_thread_finish) {
416        goto done;
417      }
418    }
419    pthread_mutex_unlock(&p->read_mutex);
420  }
421done:
422  //AUBIO_WRN("sampler: exiting reading thread\n");
423  pthread_mutex_unlock(&p->read_mutex);
424  pthread_exit(NULL);
425}
426#endif
427
428void
429aubio_sampler_read(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
430  if (s->reading_from == aubio_sampler_reading_from_source) {
431    aubio_sampler_read_from_source(s, output, read);
432  } else if (s->reading_from == aubio_sampler_reading_from_table) {
433    aubio_sampler_read_from_table(s, output, read);
434  }
435}
436
437static void
438aubio_sampler_reading_from_source_naive(aubio_sampler_t *s, fvec_t * output,
439    uint_t *read)
440{
441  // directly read from disk
442  //aubio_source_do(s->source, output, read);
443  s->source_output = output;
444  *read = aubio_sampler_pull_from_source(s);
445  if (*read < s->source_blocksize) {
446    //AUBIO_WRN("sampler: calling go_eof in _read_from_source()\n");
447    aubio_sampler_do_eof(s);
448  }
449}
450
451uint_t
452aubio_sampler_reading_from_source_ring_fetch(aubio_sampler_t*s) {
453  // read source_blocksize (> blocksize) at once
454  int ring_avail = aubio_ringbuffer_get_available(s->ring);
455  //if (ring_avail < s->blocksize) {
456  uint_t available = 0;
457  if (ring_avail < (sint_t)s->blocksize) {
458    available = aubio_sampler_pull_from_source(s);
459    if (available > 0) {
460      aubio_ringbuffer_push(s->ring, s->source_output, available);
461    }
462    if (available < s->blocksize) {
463      //AUBIO_WRN("sampler: short read %d\n", available);
464      if (ring_avail + available <= s->blocksize) {
465        s->eof_remaining = available + ring_avail;
466        if (s->eof_remaining == 0) s->eof_remaining = s->blocksize;
467        ring_avail = aubio_ringbuffer_get_available(s->ring);
468        //AUBIO_ERR("sampler: eof in: %d, last fetch: %d, in ring: %d\n",
469        //    s->eof_remaining, available, ring_avail);
470        if (s->loop) {
471          aubio_sampler_seek(s,0);
472          // read some frames from beginning of source for perfect looping
473          if (s->perfectloop) {
474            available = aubio_sampler_pull_from_source(s);
475            if (available <= 0) {
476              AUBIO_ERR("sampler: perfectloop but s->available = 0 !\n");
477            } else {
478              aubio_ringbuffer_push(s->ring, s->source_output, available);
479            }
480          }
481        }
482      }
483    }
484  }
485  return available;
486}
487
488static void
489aubio_sampler_reading_from_source_ring_pull(aubio_sampler_t *s, fvec_t *output,
490    uint_t *read)
491{
492  // write into output
493  int ring_avail = aubio_ringbuffer_get_available(s->ring);
494  if (ring_avail >= (sint_t)s->blocksize) {
495    //AUBIO_MSG("sampler: pulling %d / %d from ringbuffer\n", s->blocksize, ring_avail);
496    aubio_ringbuffer_pull(s->ring, output, s->blocksize);
497    *read = s->blocksize;
498    if (s->eof_remaining > 0) {
499      if (s->eof_remaining <= s->blocksize) {
500        //AUBIO_WRN("sampler: signaling eof\n");
501        s->eof = 1; // signal eof
502        s->eof_remaining = 0;
503      } else if (s->eof_remaining <= s->source_blocksize) {
504        s->eof_remaining -= s->blocksize;
505      }
506    }
507  } else {
508    //AUBIO_MSG("sampler: last frame, pulling remaining %d left\n", ring_avail);
509    *read = 0;
510    if (ring_avail > 0) {
511      // pull remaining frames in ring buffer
512      aubio_ringbuffer_pull(s->ring, output, ring_avail);
513      *read += ring_avail;
514    }
515    // signal eof
516    aubio_sampler_do_eof(s);
517    // finished playing, reset ringbuffer for next read
518    if (!s->playing)
519      aubio_ringbuffer_reset(s->ring);
520  }
521}
522
523static void
524aubio_sampler_reading_from_source_ring(aubio_sampler_t *s, fvec_t *output,
525    uint_t *read)
526{
527#if 0
528  aubio_sampler_reading_from_source_ring_fetch(s);
529  aubio_sampler_reading_from_source_ring_pull(s, output, read);
530#else // raw version
531  uint_t source_read;
532  while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
533      && s->eof_remaining == 0) {
534    aubio_source_do(s->source, s->source_output, &source_read);
535    aubio_timestretch_push(s->ts, s->source_output, source_read);
536    if (source_read < s->source_output->length) s->eof_remaining = source_read;
537    //AUBIO_WRN("sampler: pushed %d, now %d available\n",
538    //    source_read, aubio_timestretch_get_available(s->ts));
539  }
540  aubio_timestretch_do(s->ts, output, read);
541  if (s->eof_remaining > s->blocksize) {
542    s->eof_remaining -= s->blocksize;
543  }
544  if (*read < output->length) {
545    //AUBIO_WRN("sampler: short read %d, eof at %d\n", *read, s->eof_remaining);
546    s->eof_remaining = 0;
547    aubio_timestretch_reset(s->ts);
548    aubio_sampler_do_eof(s);
549    if (s->loop && s->perfectloop) {
550      uint_t partialread;
551      fvec_t tmpout; tmpout.data = output->data + *read;
552      tmpout.length = output->length - *read;
553      while (aubio_timestretch_get_available(s->ts) < (sint_t)tmpout.length
554          && s->eof_remaining == 0) {
555        aubio_source_do(s->source, s->source_output, &source_read);
556        aubio_timestretch_push(s->ts, s->source_output, source_read);
557        if (source_read < s->source_output->length) s->eof_remaining = source_read;
558      }
559      aubio_timestretch_do(s->ts, &tmpout, &partialread);
560      //AUBIO_WRN("sampler: partial read %d + %d\n", *read, partialread);
561      *read += partialread;
562    }
563  }
564#endif
565}
566
567#ifdef HAVE_THREADS
568static void
569aubio_sampler_read_from_source_threaded(aubio_sampler_t *s, fvec_t *output,
570    uint_t *read) {
571  // request at least output->length
572  // make sure we have enough samples read from source
573  int available;
574  pthread_mutex_lock(&s->read_mutex);
575  if (!s->opened || s->open_thread_running) {
576    //AUBIO_ERR("sampler: _read_from_source: not opened, signaling read_request\n");
577    pthread_cond_signal(&s->read_request);
578    available = 0;
579  } else if (!s->finished) {
580    pthread_cond_signal(&s->read_request);
581    pthread_cond_wait(&s->read_avail, &s->read_mutex);
582    //AUBIO_ERR("sampler: _read_from_source: %d\n", s->available);
583    available = s->available;
584  } else {
585    //AUBIO_WRN("sampler: _read_from_source: eof\n");
586    pthread_cond_signal(&s->read_request);
587    available = 0;
588  }
589  pthread_mutex_unlock(&s->read_mutex);
590  //AUBIO_WRN("sampler: got %d available in _read_from_source\n", available);
591  // read -> number of samples read
592  if (!s->perfectloop && s->source_blocksize == s->blocksize) {
593    if (available >= (sint_t)s->blocksize) {
594      fvec_copy(s->source_output, output);
595      *read = s->blocksize;
596    } else if (available > 0) {
597      fvec_copy(s->source_output, output);
598      *read = available;
599    } else {
600      fvec_zeros(output);
601      *read = 0;
602    }
603  } else {
604    aubio_sampler_reading_from_source_ring_pull(s, output, read);
605  }
606}
607#endif
608
609void
610aubio_sampler_read_from_source(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
611#ifdef HAVE_THREADS
612  if (s->threaded_read) { // if threaded
613    aubio_sampler_read_from_source_threaded(s, output, read);
614  } else
615#endif
616  {
617    if (s->finished) {
618      *read = 0;
619    }
620    else if (s->source_blocksize == s->blocksize && !s->perfectloop) {
621      aubio_sampler_reading_from_source_naive(s, output, read);
622    } else {
623      aubio_sampler_reading_from_source_ring(s, output, read);
624    }
625#if 1
626    if (s->loop && s->perfectloop && *read != s->blocksize) { // && s->started && !s->finished) {
627      AUBIO_ERR("sampler: perfectloop but read only %d\n", *read);
628    }
629#endif
630  }
631}
632
633void
634aubio_sampler_read_from_table(aubio_sampler_t *s, fvec_t *output, uint_t *read) {
635  *read = 0;
636  if (s->table == NULL) {
637    AUBIO_WRN("sampler: _pull_from_table but table not set %d, %d\n",
638        output->length, *read);
639  } else if (s->playing) {
640#if 0
641    uint_t available = s->table->length - s->table_index;
642    fvec_t tmp;
643    tmp.data = s->table->data + s->table_index;
644    if (available < s->blocksize) {
645      //AUBIO_WRN("sampler: _pull_from_table: table length %d, index: %d, read %d\n",
646      //    s->table->length, s->table_index, *read);
647      tmp.length = available;
648      fvec_t tmpout; tmpout.data = output->data; tmpout.length = available;
649      fvec_copy(&tmp, &tmpout);
650      if (s->loop && s->perfectloop) {
651        uint_t remaining = s->blocksize - available;
652        tmpout.data = output->data + available; tmpout.length = remaining;
653        tmp.data = s->table->data; tmp.length = remaining;
654        fvec_copy(&tmp, &tmpout);
655        s->table_index = remaining;
656        *read = s->blocksize;
657      } else {
658        s->table_index = 0;
659        *read = available;
660      }
661      aubio_sampler_do_eof(s);
662    } else {
663      tmp.length = s->blocksize;
664      fvec_copy(&tmp, output);
665      s->table_index += output->length;
666      *read = s->blocksize;
667    }
668#else
669    fvec_t tmp, tmpout;
670    uint_t source_read = 0;
671    while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
672        && s->eof_remaining == 0) {
673      uint_t available = s->table->length - s->table_index;
674      if (available < s->source_blocksize) {
675        source_read = available;
676      } else {
677        source_read = s->source_blocksize;
678      }
679      tmp.length = source_read; tmp.data = s->table->data + s->table_index;
680      tmpout.data = s->source_output->data; tmpout.length = source_read;
681      fvec_copy(&tmp, &tmpout);
682      aubio_timestretch_push(s->ts, &tmpout, source_read);
683      if (source_read < s->source_blocksize) {
684        s->eof_remaining = source_read;
685        s->table_index = s->source_blocksize - *read;
686      } else {
687        s->table_index += source_read;
688      }
689      if (s->table_index == s->table->length) s->table_index = 0;
690      //AUBIO_WRN("sampler: pushed %d, now %d available, table_index %d, eof %d\n",
691      //    source_read, aubio_timestretch_get_available(s->ts),
692      //    s->table_index, s->eof_remaining);
693    }
694    aubio_timestretch_do(s->ts, output, read);
695    if (*read == 0) {
696      //AUBIO_WRN("sampler: pushed %d, now %d available, table_index %d\n",
697      //    *read, aubio_timestretch_get_available(s->ts), s->table_index);
698    }
699    if (s->eof_remaining > s->blocksize) {
700      s->eof_remaining -= s->blocksize;
701    }
702    if (*read < output->length) {
703      s->eof_remaining = 0;
704      aubio_sampler_do_eof(s);
705    }
706#if 0
707    if (*read < output->length) {
708      //uint_t available = aubio_timestretch_get_available(s->ts);
709      s->eof_remaining = 0;
710      aubio_timestretch_reset(s->ts);
711      aubio_sampler_do_eof(s);
712    }
713#endif
714#if 0
715    if (*read < output->length) {
716      //uint_t available = aubio_timestretch_get_available(s->ts);
717      s->eof_remaining = 0;
718      aubio_timestretch_reset(s->ts);
719      aubio_sampler_do_eof(s);
720      if (s->loop && s->perfectloop) {
721        tmpout.data = output->data + *read;
722        tmpout.length = output->length - *read;
723        while (aubio_timestretch_get_available(s->ts) < (sint_t)tmpout.length
724            && s->eof_remaining == 0) {
725          uint_t available = s->table->length - s->table_index;
726          if (available < s->source_blocksize) {
727            source_read = available;
728          } else {
729            source_read = s->source_blocksize;
730          }
731          //AUBIO_WRN("sampler: short read %d, remaining %d\n", *read, remaining);
732          tmp.length = source_read; tmp.data = s->table->data + s->table_index;
733          fvec_t tmpout2; tmpout2.data = s->source_output->data; tmpout2.length = source_read;
734          fvec_copy(&tmp, &tmpout2);
735          aubio_timestretch_push(s->ts, &tmpout2, source_read);
736          if (source_read < s->source_blocksize) {
737            s->eof_remaining = source_read;
738            s->table_index = 0;
739          } else {
740            s->table_index += source_read;
741          }
742          if (s->table_index == s->table->length) s->table_index = 0;
743          //AUBIO_WRN("sampler: second push, pushed %d, now %d available\n",
744          //    source_read, aubio_timestretch_get_available(s->ts));
745        }
746        uint_t partialread;
747        aubio_timestretch_do(s->ts, &tmpout, &partialread);
748        AUBIO_WRN("sampler: partial read %d + %d\n", *read, partialread);
749        *read += partialread;
750        //s->eof = 1;
751      }
752    }
753#endif
754
755#endif
756  }
757}
758
759uint_t
760aubio_sampler_set_table(aubio_sampler_t *s, fvec_t *samples) {
761  if (!samples || !s) return AUBIO_FAIL;
762  if (s->reading_from == aubio_sampler_reading_from_source) {
763    //aubio_sampler_close_reading_thread(s);
764  }
765  s->table = samples;
766  //AUBIO_INF("sampler: setting table (%d long)\n", s->table->length);
767  s->table_index = 0;
768  s->reading_from = aubio_sampler_reading_from_table;
769  //s->threaded_read = 0;
770  s->opened = 1;
771  s->finished = 1;
772  return AUBIO_OK;
773}
774
775sint_t
776aubio_sampler_pull_from_source(aubio_sampler_t *s)
777{
778  // pull source_blocksize samples from source, return available frames
779  uint_t source_read = s->source_blocksize;
780  if (s->source == NULL) {
781    AUBIO_ERR("sampler: trying to fetch on NULL source\n");
782    return -1;
783  }
784#if 1
785  aubio_source_do(s->source, s->source_output, &source_read);
786  return source_read;
787#else
788  uint_t source_read_tmp;
789  while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
790      && s->last_read == 0) {
791    aubio_source_do(s->source, s->source_output_tmp, &source_read_tmp);
792    aubio_timestretch_push(s->ts, s->source_output_tmp, source_read_tmp);
793    if (source_read_tmp < s->source_output_tmp->length) s->last_read = source_read;
794  }
795  aubio_timestretch_do(s->ts, s->source_output, &source_read);
796  if (s->last_read > s->blocksize) {
797    s->last_read -= s->blocksize;
798  }
799  if (source_read < s->source_blocksize) {
800    s->last_read = 0;
801    //AUBIO_ERR("sampler: calling timestretch reset %d %d\n", source_read, s->source_blocksize);
802    aubio_timestretch_reset(s->ts);
803  }
804  return source_read;
805#endif
806}
807
808
809uint_t
810aubio_sampler_get_samplerate (aubio_sampler_t *o)
811{
812  return o->samplerate;
813}
814
815uint_t
816aubio_sampler_get_duration (aubio_sampler_t *o)
817{
818  if (o->duration !=0) {
819    return o->duration;
820  } else {
821    AUBIO_WRN("sampler: failed getting duration for %s\n", o->uri);
822    return 0;
823  }
824}
825
826uint_t
827aubio_sampler_get_opened (aubio_sampler_t *o)
828{
829  return o->opened; //== 1 ? AUBIO_OK : AUBIO_FAIL;
830}
831
832uint_t
833aubio_sampler_get_finished(aubio_sampler_t *o)
834{
835  return o->finished;
836}
837
838uint_t
839aubio_sampler_get_eof (aubio_sampler_t *o)
840{
841  return o->eof;
842}
843
844uint_t
845#ifdef HAVE_THREADS
846aubio_sampler_get_waited_opening (aubio_sampler_t *o, uint_t waited) {
847  if (o->playing) {
848    if (!o->opened) {
849      o->waited += waited;
850    } else if (o->waited) {
851      //AUBIO_WRN("sampler: waited %d frames (%.2fms) while opening %s\n",
852      //    o->waited, 1000.*o->waited/(smpl_t)o->samplerate, o->uri);
853      uint_t waited = o->waited;
854      o->waited = 0;
855      return waited;
856    }
857  }
858#else
859aubio_sampler_get_waited_opening (aubio_sampler_t *o UNUSED, uint_t waited UNUSED) {
860#endif
861  return 0;
862}
863
864uint_t
865aubio_sampler_seek(aubio_sampler_t * o, uint_t pos)
866{
867  //AUBIO_WRN("sampler: seeking to 0\n");
868  uint_t ret = AUBIO_FAIL;
869  o->finished = 0;
870  if (!o->opened) return AUBIO_OK;
871  if (o->source) {
872    ret = aubio_source_seek(o->source, pos);
873  } else if (o->table && (sint_t)pos >= 0 && pos < o->table->length) {
874    o->table_index = pos < o->table->length ? pos : o->table->length - 1;
875    ret = AUBIO_OK;
876  }
877  //o->last_read = 0;
878  return ret;
879}
880
881void
882aubio_sampler_do_eof (aubio_sampler_t * o)
883{
884  //AUBIO_MSG("sampler: calling  _do_eof()\n");
885  o->finished = 1;
886  o->eof = 1;
887  if (!o->loop) {
888    o->playing = 0;
889  } else {
890    if (o->reading_from == aubio_sampler_reading_from_source)
891      aubio_sampler_seek(o, 0);
892    //o->finished = 0;
893  }
894}
895
896void aubio_sampler_do ( aubio_sampler_t * o, fvec_t * output, uint_t *read)
897{
898  o->eof = 0;
899  if (o->opened == 1 && o->playing) {
900    aubio_sampler_read(o, output, read);
901  } else {
902    fvec_zeros(output);
903    *read = 0;
904  }
905}
906
907void aubio_sampler_do_multi ( aubio_sampler_t * o, fmat_t * output, uint_t *read)
908{
909  o->eof = 0;
910  if (o->opened == 1 && o->playing) {
911    //aubio_sampler_read_multi(o, output, read);
912  } else {
913    fmat_zeros(output);
914    *read = 0;
915  }
916}
917
918uint_t aubio_sampler_get_playing ( const aubio_sampler_t * o )
919{
920  return o->playing;
921}
922
923uint_t aubio_sampler_set_playing ( aubio_sampler_t * o, uint_t playing )
924{
925  o->playing = (playing == 1) ? 1 : 0;
926  return 0;
927}
928
929uint_t aubio_sampler_get_loop ( aubio_sampler_t * o )
930{
931  return o->loop;
932}
933
934uint_t aubio_sampler_set_loop ( aubio_sampler_t * o, uint_t loop )
935{
936  o->loop = (loop == 1) ? 1 : 0;
937  return 0;
938}
939
940uint_t aubio_sampler_play ( aubio_sampler_t * o )
941{
942  return aubio_sampler_set_playing (o, 1);
943}
944
945uint_t aubio_sampler_stop ( aubio_sampler_t * o )
946{
947  return aubio_sampler_set_playing (o, 0);
948}
949
950uint_t aubio_sampler_loop ( aubio_sampler_t * o )
951{
952  aubio_sampler_set_loop(o, 1);
953  aubio_sampler_seek(o, 0);
954  return aubio_sampler_set_playing (o, 1);
955}
956
957uint_t aubio_sampler_trigger ( aubio_sampler_t * o )
958{
959  if (o->ring) aubio_ringbuffer_reset(o->ring);
960  aubio_sampler_set_loop(o, 0);
961  aubio_sampler_seek(o, 0);
962  return aubio_sampler_set_playing (o, 1);
963}
964
965uint_t aubio_sampler_set_perfectloop (aubio_sampler_t *s, uint_t perfectloop) {
966  if (!s) return AUBIO_FAIL;
967  s->perfectloop = perfectloop;
968  return AUBIO_OK;
969}
970
971uint_t aubio_sampler_get_perfectloop (aubio_sampler_t *s) {
972  if (!s) return AUBIO_FAIL;
973  return s->perfectloop;
974}
975
976
977uint_t aubio_sampler_set_stretch(aubio_sampler_t *s, smpl_t stretch)
978{
979  if (!s->ts) return AUBIO_FAIL;
980  return aubio_timestretch_set_stretch(s->ts, stretch);
981}
982
983smpl_t aubio_sampler_get_stretch(aubio_sampler_t *s)
984{
985  if (!s->ts) return 1.;
986  return aubio_timestretch_get_stretch(s->ts);
987}
988
989uint_t aubio_sampler_set_transpose(aubio_sampler_t *s, smpl_t transpose)
990{
991  if (!s->ts) return AUBIO_FAIL;
992  return aubio_timestretch_set_transpose(s->ts, transpose);
993}
994
995smpl_t aubio_sampler_get_transpose(aubio_sampler_t *s)
996{
997  if (!s->ts) return 0.;
998  return aubio_timestretch_get_transpose(s->ts);
999}
1000
1001
1002void del_aubio_sampler( aubio_sampler_t * o )
1003{
1004#ifdef HAVE_THREADS
1005  // close opening thread
1006  aubio_sampler_close_opening_thread(o);
1007  // close reading thread
1008  aubio_sampler_close_reading_thread(o);
1009#endif
1010  //if (o->source_output) {
1011  if (o->source_output && (o->threaded_read || o->perfectloop)) {
1012    del_fvec(o->source_output);
1013  }
1014  if (o->source_moutput) {
1015    del_fmat(o->source_moutput);
1016  }
1017  if (o->ring) {
1018    del_aubio_ringbuffer(o->ring);
1019  }
1020  if (o->ts) {
1021    del_aubio_timestretch(o->ts);
1022  }
1023  if (o->source) {
1024    del_aubio_source(o->source);
1025  }
1026  AUBIO_FREE(o);
1027}
Note: See TracBrowser for help on using the repository browser.