source: src/synth/sampler.c @ 7dfd972

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

src/synth/sampler.c: unthreaded read for now

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