source: src/synth/sampler.c @ bad88364

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

src/synth/sampler.c: update copyright

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