source: src/synth/sampler.c @ 95af88b

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

src/synth/sampler.c: avoid declaration after statement, use () for pragma

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