source: src/synth/sampler.c @ 388c2e7

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

src/synth/sampler.c: no #warning for msvc

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