source: src/synth/sampler.c @ 82ad1ed

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

src/synth/sampler.h: add timestretch (first draft)

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