Changes in / [b762f8d:b201912]


Ignore:
Files:
14 added
11 edited

Legend:

Unmodified
Added
Removed
  • .travis.yml

    rb762f8d rb201912  
    4242      osx_image: xcode8
    4343      compiler: clang
    44       env: WAFOPTS="--with-target-platform=ios --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
     44      env: WAFOPTS="--with-target-platform=ios --disable-avcodec --disable-sndfile --disable-samplerate --disable-rubberband" AUBIO_NOTESTS=1
    4545    - language: C
    4646      os: osx
    4747      osx_image: xcode8
    4848      compiler: clang
    49       env: WAFOPTS="--with-target-platform=iosimulator --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
     49      env: WAFOPTS="--enable-fat --disable-avcodec --disable-sndfile --disable-samplerate --disable-rubberband" AUBIO_NOTESTS=1
    5050    - language: C
    5151      os: osx
     
    5757      osx_image: xcode8.2
    5858      compiler: clang
    59       env: WAFOPTS="--with-target-platform=ios --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
     59      env: WAFOPTS="--with-target-platform=ios --disable-avcodec --disable-sndfile --disable-samplerate --disable-rubberband" AUBIO_NOTESTS=1
    6060    - language: C
    6161      os: osx
    6262      osx_image: xcode8.2
    6363      compiler: clang
    64       env: WAFOPTS="--with-target-platform=iosimulator --disable-avcodec --disable-sndfile" AUBIO_NOTESTS=1
     64      env: WAFOPTS="--with-target-platform=iosimulator --disable-avcodec --disable-sndfile --disable-samplerate --disable-rubberband" AUBIO_NOTESTS=1
    6565
    6666# use trusty
     
    8181    - libasound2-dev
    8282    - libfftw3-dev
     83    - librubberband-dev
    8384    - sox
    8485
     
    9091       brew install ffmpeg
    9192       brew install libsndfile
     93       brew install libsamplerate
     94       brew install rubberband
    9295       export PATH="$HOME/Library/Python/2.7/bin/:$PATH"
    9396     fi;
  • python/lib/gen_code.py

    rb762f8d rb201912  
    2020    'method': '"default"',
    2121    'uri': '"none"',
     22    'transpose': '0.',
     23    'maxwrite': 1024,
     24    'maxrequest': 1024,
    2225    }
    2326
     
    8386        'filterbank': 'self->n_filters',
    8487        'tss': 'self->buf_size',
     88        'pitchshift': 'self->hop_size',
     89        'ringbuffer': 'self->maxrequest',
    8590        }
    8691
     
    95100        'wavetable': 'self->hop_size',
    96101        'tss': 'self->buf_size / 2 + 1',
     102        'pitchshift': 'self->hop_size',
     103        'ringbuffer': 'self->maxwrite',
    97104        }
    98105
     
    270277        if p['type'] == 'char_t*':
    271278            return self.check_valid_char(p)
     279        if p['type'] == 'smpl_t':
     280            return self.check_valid_smpl(p)
    272281        else:
    273282            print ("ERROR, no idea how to check %s for validity" % p['type'])
     
    290299    self->{name} = {defval};
    291300    if ({name} != NULL) {{
     301        self->{name} = {name};
     302    }}
     303""".format(defval = aubiodefvalue[name], name = name)
     304
     305    def check_valid_smpl(self, p):
     306        name = p['name']
     307        return """
     308    self->{name} = {defval};
     309    if ({name} != 0.) {{
    292310        self->{name} = {name};
    293311    }}
  • python/lib/gen_external.py

    rb762f8d rb201912  
    3838  'source_avcodec',
    3939  'source_wavread',
    40   #'sampler',
    4140  'audio_unit',
    4241  'spectral_whitening',
     42  'timestretch', # TODO fix parsing of uint_t *read in _do
     43  'sampler', # TODO fix parsing of uint_t *read in _do
     44  'ringbuffer',
    4345  ]
    4446
  • python/lib/moresetuptools.py

    rb762f8d rb201912  
    8080                'libswresample', 'libavresample',
    8181                'sndfile',
     82                'rubberband',
    8283                #'fftw3f',
    8384               ]
     
    101102    if 'samplerate' in ext.libraries:
    102103        ext.define_macros += [('HAVE_SAMPLERATE', 1)]
     104    if 'rubberband' in ext.libraries:
     105        ext.define_macros += [('HAVE_RUBBERBAND', 1)]
    103106    if 'fftw3f' in ext.libraries:
    104107        ext.define_macros += [('HAVE_FFTW3F', 1)]
  • src/aubio.h

    rb762f8d rb201912  
    219219#include "pitch/pitchspecacf.h"
    220220#include "tempo/beattracking.h"
     221#include "effects/pitchshift.h"
     222#include "effects/timestretch.h"
    221223#include "utils/scale.h"
    222224#include "utils/hist.h"
     225#include "utils/ringbuffer.h"
    223226#endif
    224227
  • src/io/source_avcodec.c

    rb762f8d rb201912  
    6161#define AUBIO_AVCODEC_MAX_BUFFER_SIZE FF_MIN_BUFFER_SIZE
    6262
     63#ifdef HAVE_PTHREAD_H
     64// Global mutex to make sure avcodec_open2 is not called simultaneously in a
     65// multithreaded environment. Comment the following define if no lock required.
     66#define HAVE_AUBIO_AVCODEC_MUTEX
     67#include <pthread.h>
     68pthread_mutex_t aubio_avcodec_mutex = PTHREAD_MUTEX_INITIALIZER;
     69#endif /* HAVE_PTHREAD_H */
     70
    6371struct _aubio_source_avcodec_t {
    6472  uint_t hop_size;
     
    8795  uint_t eof;
    8896  uint_t multi;
     97  uint_t has_network_url;
    8998};
    9099
     
    101110  av_url_split(proto, proto_size, authorization, authorization_size, hostname,
    102111      hostname_size, port_ptr, uripath, path_size, s->path);
     112  s->has_network_url = 0;
    103113  if (strlen(proto)) {
    104     return 1;
    105   }
    106   return 0;
     114    s->has_network_url = 1;
     115  }
     116  return s->has_network_url;
    107117}
    108118
     
    113123  AVCodecContext *avCodecCtx = s->avCodecCtx;
    114124  AVFrame *avFrame = s->avFrame;
     125  AVDictionary *streamopts = 0;
    115126  sint_t selected_stream = -1;
    116127#if FF_API_LAVF_AVCTX
     
    140151  strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
    141152
     153#ifdef HAVE_AUBIO_AVCODEC_MUTEX
     154  pthread_mutex_lock(&aubio_avcodec_mutex);
     155#endif /* HAVE_AUBIO_AVCODEC_MUTEX */
     156
    142157  // register all formats and codecs
    143158  av_register_all();
     
    148163
    149164  // try opening the file and get some info about it
     165  if (s->has_network_url) {
     166    if (av_dict_set(&streamopts, "timeout", "1000000", 0)) { // in microseconds
     167      AUBIO_WRN("source_avcodec: Failed setting timeout to 1000000 for %s\n", s->path);
     168    } else {
     169      AUBIO_WRN("source_avcodec: Setting timeout to 1000000 for %s\n", s->path);
     170    }
     171  }
    150172  avFormatCtx = NULL;
    151   if ( (err = avformat_open_input(&avFormatCtx, s->path, NULL, NULL) ) < 0 ) {
     173  if ( (err = avformat_open_input(&avFormatCtx, s->path, NULL, &streamopts) ) < 0 ) {
    152174    char errorstr[256];
    153175    av_strerror (err, errorstr, sizeof(errorstr));
     
    237259  }
    238260
     261#ifdef HAVE_AUBIO_AVCODEC_MUTEX
     262  pthread_mutex_unlock(&aubio_avcodec_mutex);
     263#endif /* HAVE_AUBIO_AVCODEC_MUTEX */
     264
    239265  /* get input specs */
    240266  s->input_samplerate = avCodecCtx->sample_rate;
     
    277303  //av_log_set_level(AV_LOG_QUIET);
    278304
     305  av_dict_free(&streamopts);
    279306  return s;
    280307
    281308beach:
     309  if (streamopts != 0) av_dict_free(&streamopts);
    282310  //AUBIO_ERR("can not read %s at samplerate %dHz with a hop_size of %d\n",
    283311  //    s->path, s->samplerate, s->hop_size);
     312#ifdef HAVE_AUBIO_AVCODEC_MUTEX
     313  pthread_mutex_unlock(&aubio_avcodec_mutex);
     314#endif /* HAVE_AUBIO_AVCODEC_MUTEX */
    284315  del_aubio_source_avcodec(s);
    285316  return NULL;
  • src/synth/sampler.c

    rb762f8d rb201912  
    11/*
    2   Copyright (C) 2003-2013 Paul Brossier <piem@aubio.org>
     2  Copyright (C) 2003-2017 Paul Brossier <piem@aubio.org>
    33
    44  This file is part of aubio.
     
    1919*/
    2020
     21#include <assert.h>
    2122
    2223#include "aubio_priv.h"
     
    2425#include "fmat.h"
    2526#include "io/source.h"
     27#include "utils/ringbuffer.h"
     28#include "effects/timestretch.h"
    2629#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;
    2755
    2856struct _aubio_sampler_t {
    2957  uint_t samplerate;
    3058  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
    3170  aubio_source_t *source;
    32   fvec_t *source_output;
    33   fmat_t *source_output_multi;
    3471  char_t *uri;
    3572  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
    36103};
    37104
    38 aubio_sampler_t *new_aubio_sampler(uint_t samplerate, uint_t blocksize)
     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)
    39123{
    40124  aubio_sampler_t *s = AUBIO_NEW(aubio_sampler_t);
     
    45129  s->samplerate = samplerate;
    46130  s->blocksize = blocksize;
    47   s->source_output = new_fvec(blocksize);
    48   s->source_output_multi = new_fmat(4, blocksize);
    49131  s->source = NULL;
    50132  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
    51199  return s;
    52200beach:
     
    55203}
    56204
     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
    57257uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri )
    58258{
    59   if (o->source) del_aubio_source(o->source);
    60 
    61   if (o->uri) AUBIO_FREE(o->uri);
    62   o->uri = AUBIO_ARRAY(char_t, strnlen(uri, PATH_MAX));
    63   strncpy(o->uri, uri, strnlen(uri, PATH_MAX));
    64 
    65   o->source = new_aubio_source(uri, o->samplerate, o->blocksize);
    66   if (o->source) return 0;
    67   AUBIO_ERR("sampler: failed loading %s", uri);
    68   return 1;
    69 }
    70 
    71 void aubio_sampler_do ( aubio_sampler_t * o, const fvec_t * input, fvec_t * output)
    72 {
    73   uint_t read = 0, i;
     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) {
    74833  if (o->playing) {
    75     aubio_source_do (o->source, o->source_output, &read);
    76     for (i = 0; i < output->length; i++) {
    77       output->data[i] += o->source_output->data[i];
    78     }
    79     if (read < o->blocksize) o->playing = 0;
    80   }
    81   if (input && input != output) {
    82     for (i = 0; i < output->length; i++) {
    83       output->data[i] += input->data[i];
    84     }
    85   }
    86 }
    87 
    88 void aubio_sampler_do_multi ( aubio_sampler_t * o, const fmat_t * input, fmat_t * output)
    89 {
    90   uint_t read = 0, i, j;
    91   if (o->playing) {
    92     aubio_source_do_multi (o->source, o->source_output_multi, &read);
    93     for (i = 0; i < output->height; i++) {
    94       for (j = 0; j < output->length; j++) {
    95         output->data[i][j] += o->source_output_multi->data[i][j];
    96       }
    97     }
    98     if ( read < o->blocksize ) o->playing = 0;
    99   }
    100   if (input && input != output) {
    101     for (i = 0; i < output->height; i++) {
    102       for (j = 0; j < output->length; j++) {
    103         output->data[i][j] += input->data[i][j];
    104       }
    105     }
     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;
    106901  }
    107902}
     
    118913}
    119914
     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
    120926uint_t aubio_sampler_play ( aubio_sampler_t * o )
    121927{
    122   aubio_source_seek (o->source, 0);
    123928  return aubio_sampler_set_playing (o, 1);
    124929}
     
    129934}
    130935
     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
    131988void del_aubio_sampler( aubio_sampler_t * o )
    132989{
     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  }
    1331009  if (o->source) {
    1341010    del_aubio_source(o->source);
    1351011  }
    136   if (o->uri) AUBIO_FREE(o->uri);
    137   del_fvec(o->source_output);
    138   del_fmat(o->source_output_multi);
    1391012  AUBIO_FREE(o);
    1401013}
  • src/synth/sampler.h

    rb762f8d rb201912  
    2424/** \file
    2525
    26   Load and play sound files.
     26  Load and play a sound file.
    2727
    2828  This file loads a sample and gets ready to play it.
     
    3030  The `_do` function adds the new samples to the input, and write the result as
    3131  the output.
     32
     33TODO:
     34  - add _preset_threaded(level)
     35  - rename _set_loop/_get_loop to _set_looping/_get_looping
     36  - add option to pass a callback to signal eof
    3237
    3338  \example synth/test-sampler.c
     
    5055
    5156*/
    52 aubio_sampler_t * new_aubio_sampler(uint_t samplerate, uint_t hop_size);
     57aubio_sampler_t * new_aubio_sampler(uint_t hop_size, uint_t samplerate);
    5358
    5459/** load source in sampler
     
    5964  \return 0 if successful, non-zero otherwise
    6065
     66  This function attempts to load a new source, swaps the current one with the
     67  newly loaded one (or NULL if loading failed), then delete the old one.
     68
    6169*/
    6270uint_t aubio_sampler_load( aubio_sampler_t * o, const char_t * uri );
    6371
     72/** queue source in sampler
     73
     74  \param o sampler, created by new_aubio_sampler()
     75  \param uri the uri of the source to load
     76
     77  \return 0 if successfully queued, non-zero otherwise
     78
     79  This function is identical to aubio_sampler_load(), except it will be called
     80  in its own thread to avoid blocking calls to aubio_sampler_do().
     81
     82*/
     83uint_t aubio_sampler_queue(aubio_sampler_t * o, const char_t * uri );
     84
     85/** set array to read from
     86
     87  \param o sampler, created by new_aubio_sampler()
     88  \param samples the vector to set the table to
     89
     90  \return 0 if successfully set, non-zero otherwise
     91
     92*/
     93uint_t aubio_sampler_set_table(aubio_sampler_t *o, fvec_t *samples);
     94
    6495/** process sampler function
    6596
    6697  \param o sampler, created by new_aubio_sampler()
    67   \param input input of the sampler, to be added to the output
    6898  \param output output of the sampler
    69 
    70 This function adds the new samples from the playing source to the output.
    71 
    72 If `input` is not NULL and different from `output`, then the samples from `input`
    73 are added to the output.
    74 
    75 */
    76 void aubio_sampler_do ( aubio_sampler_t * o, const fvec_t * input, fvec_t * output);
     99  \param read will be set to then number of samples actually read
     100
     101  This function get new samples from the sampler and store them into output.
     102
     103  The output vector will be completed with 0 if too few samples are available.
     104
     105*/
     106void aubio_sampler_do ( aubio_sampler_t * o, fvec_t * output, uint_t *read);
    77107
    78108/** process sampler function, multiple channels
    79109
    80110  \param o sampler, created by new_aubio_sampler()
    81   \param input input of the sampler, to be added to the output
    82111  \param output output of the sampler
    83 
    84 This function adds the new samples from the playing source to the output.
    85 
    86 If `input` is not NULL and different from `output`, then the samples from `input`
    87 are added to the output.
    88 
    89 */
    90 void aubio_sampler_do_multi ( aubio_sampler_t * o, const fmat_t * input, fmat_t * output);
     112  \param read will be set to the number of samples actually read
     113
     114  This function is identical to aubio_sampler_do(), but for a multi-channel source.
     115
     116*/
     117void aubio_sampler_do_multi ( aubio_sampler_t * o, fmat_t * output, uint_t *read);
    91118
    92119/** get current playing state
     
    109136uint_t aubio_sampler_set_playing ( aubio_sampler_t * o, uint_t playing );
    110137
    111 /** play sample from start
     138/** get current looping state
     139
     140  \param o sampler, created by new_aubio_sampler()
     141
     142  \return 0 if not looping , 1 if looping
     143
     144*/
     145uint_t aubio_sampler_get_loop(aubio_sampler_t * o);
     146
     147/** set current looping state
     148
     149  \param o sampler, created by new_aubio_sampler()
     150  \param loop 0 for not looping, 1 for looping
     151
     152  \return 0 if successful, 1 otherwise
     153
     154*/
     155uint_t aubio_sampler_set_loop(aubio_sampler_t * o, uint_t loop);
     156
     157/** play sample
    112158
    113159  \param o sampler, created by new_aubio_sampler()
     
    118164uint_t aubio_sampler_play ( aubio_sampler_t * o );
    119165
     166/** play sample from start, looping it
     167
     168  \param o sampler, created by new_aubio_sampler()
     169
     170  \return 0 if successful, 1 otherwise
     171
     172*/
     173uint_t aubio_sampler_loop ( aubio_sampler_t * o );
     174
     175/** play sample from start, once
     176
     177  \param o sampler, created by new_aubio_sampler()
     178
     179  \return 0 if successful, 1 otherwise
     180
     181*/
     182uint_t aubio_sampler_trigger ( aubio_sampler_t * o );
     183
    120184/** stop sample
    121185
     
    126190*/
    127191uint_t aubio_sampler_stop ( aubio_sampler_t * o );
     192
     193/** get end-of-file status
     194
     195  \param o sampler, created by new_aubio_sampler()
     196
     197  \return 1 when the eof is being reached, 0 otherwise
     198
     199*/
     200uint_t aubio_sampler_get_eof(aubio_sampler_t * o);
     201
     202/** get end-of-file status
     203
     204  \param o sampler, created by new_aubio_sampler()
     205
     206  \return 1 when end of file has been reached, 0 otherwise
     207
     208*/
     209uint_t aubio_sampler_get_finished (aubio_sampler_t * o);
     210
     211/** get samplerate
     212
     213  \param o sampler, created by new_aubio_sampler()
     214
     215  \return samplerate of the sampler
     216
     217*/
     218uint_t aubio_sampler_get_samplerate(aubio_sampler_t * o);
     219
     220/** get the number of samples that were set to zero while opening a file
     221
     222  \param o sampler, created by new_aubio_sampler()
     223  \param waited the number of frames processed during this block
     224
     225  \return the total delay in samples when the file was successfuly opened, 0
     226  otherwise
     227
     228*/
     229uint_t aubio_sampler_get_waited_opening(aubio_sampler_t * o, uint_t waited);
     230
     231/** get current time stretching factor
     232
     233  \param o sampler, created by new_aubio_sampler()
     234
     235  \return the current time stretch factor
     236
     237 */
     238smpl_t aubio_sampler_get_stretch (aubio_sampler_t *o);
     239
     240/** set current time stretching factor
     241
     242  \param o sampler, created by new_aubio_sampler()
     243  \param stretch new time stretching factor
     244
     245  \return AUBIO_OK on success, AUBIO_FAIL otherwise
     246
     247 */
     248uint_t aubio_sampler_set_stretch (aubio_sampler_t *o, smpl_t stretch);
     249
     250/** get current pitch shifting factor
     251
     252  \param o sampler, created by new_aubio_sampler()
     253
     254  \return the current pitch transposition factor
     255
     256 */
     257smpl_t aubio_sampler_get_transpose (aubio_sampler_t *o);
     258
     259/** set current pitch shifting factor
     260
     261  \param o sampler, created by new_aubio_sampler()
     262  \param transpose new pitch shifting (transposition) factor
     263
     264  \return AUBIO_OK on success, AUBIO_FAIL otherwise
     265
     266 */
     267uint_t aubio_sampler_set_transpose (aubio_sampler_t *o, smpl_t transpose);
     268
     269/** get the current perfect loop mode
     270
     271  \param o sampler, created by new_aubio_sampler()
     272
     273  \return the total delay in samples when the file was successfuly opened, 0
     274  otherwise
     275
     276*/
     277uint_t aubio_sampler_get_perfectloop (aubio_sampler_t *o);
     278
     279/** set the perfect loop mode
     280
     281  \param o sampler, created by new_aubio_sampler()
     282  \param perfectloop 1 to set perfect loop mode, 0 to turn it of
     283
     284  \return AUBIO_OK on success, AUBIO_FAIL otherwise
     285
     286 */
     287uint_t aubio_sampler_set_perfectloop (aubio_sampler_t *o, uint_t perfectloop);
     288
     289/** seek to position
     290
     291  \param o sampler, created by new_aubio_sampler()
     292  \param pos position to seek to, in samples
     293
     294  \return 0 if successful, 1 otherwise
     295
     296*/
     297uint_t aubio_sampler_seek(aubio_sampler_t * o, uint_t pos);
    128298
    129299/** destroy ::aubio_sampler_t object
  • src/wscript_build

    rb762f8d rb201912  
    66uselib += ['SAMPLERATE']
    77uselib += ['SNDFILE']
     8uselib += ['RUBBERBAND']
    89uselib += ['AVCODEC']
    910uselib += ['AVFORMAT']
     
    1213uselib += ['AVUTIL']
    1314uselib += ['BLAS']
     15uselib += ['PTHREAD']
    1416
    1517source = ctx.path.ant_glob('*.c **/*.c')
  • tests/src/synth/test-sampler.c

    rb762f8d rb201912  
    11#include <aubio.h>
    22#include "utils_tests.h"
     3
     4int time_was_reached (smpl_t time_s, uint_t n_frames, uint_t hop_size, uint_t samplerate) {
     5    if ((n_frames / hop_size) == (uint_t)(time_s * samplerate) / hop_size) {
     6      PRINT_MSG("reached %.2f sec at %d samples\n", time_s, n_frames);
     7      return 1;
     8    } else {
     9      return 0;
     10    }
     11}
    312
    413int main (int argc, char **argv)
     
    615  sint_t err = 0;
    716
    8   if (argc < 4) {
     17  if (argc < 2) {
    918    err = 2;
    1019    PRINT_ERR("not enough arguments\n");
    11     PRINT_MSG("usage: %s <input_path> <output_path> <sample_path> [samplerate]\n", argv[0]);
     20    PRINT_MSG("usage: %s <sample_path> [samplerate] [blocksize] [output_path]\n", argv[0]);
    1221    return err;
    1322  }
    1423
    15   uint_t samplerate = 0; // default is the samplerate of input_path
    16   uint_t hop_size = 256;
    17   uint_t n_frames = 0, read = 0;
     24  uint_t samplerate = 44100; // default is 44100
     25  uint_t hop_size = 64; //256;
     26  uint_t n_frames = 0, frames_played = 0;
     27  uint_t read = 0;
     28  char_t *sink_path = NULL;
     29  aubio_sink_t *sink = NULL;
    1830
    19   char_t *source_path = argv[1];
    20   char_t *sink_path = argv[2];
    21   char_t *sample_path = argv[3];
    22   if ( argc == 5 ) samplerate = atoi(argv[4]);
     31  char_t *sample_path = argv[1];
     32  if ( argc > 2 ) samplerate = atoi(argv[2]);
     33  if ( argc > 3 ) hop_size = atoi(argv[3]);
     34  if ( argc > 4 ) sink_path = argv[4];
    2335
    2436  fvec_t *vec = new_fvec(hop_size);
    25   aubio_source_t *source = new_aubio_source(source_path, samplerate, hop_size);
    26   if (samplerate == 0 ) samplerate = aubio_source_get_samplerate(source);
    27   aubio_sink_t *sink = new_aubio_sink(sink_path, samplerate);
    2837
    29   aubio_sampler_t * sampler = new_aubio_sampler (samplerate, hop_size);
     38  aubio_sampler_t * sampler = new_aubio_sampler (hop_size, samplerate);
     39  if (!vec) goto beach;
     40  if (!sampler) goto beach_sampler;
     41  // load source file
     42  aubio_sampler_load (sampler, sample_path);
     43  // load source file (asynchronously)
     44  //aubio_sampler_queue (sampler, sample_path);
     45  samplerate = aubio_sampler_get_samplerate (sampler);
     46  if (samplerate == 0) {
     47    PRINT_ERR("starting with samplerate = 0\n");
     48    //goto beach_sink;
     49  }
    3050
    31   aubio_sampler_load (sampler, sample_path);
     51  if (sink_path) {
     52    sink = new_aubio_sink(sink_path, samplerate);
     53    if (!sink) goto beach_sink;
     54  }
     55
     56  smpl_t sample_duration = 2.953;
     57  uint_t sample_repeat = 10;
     58  smpl_t t1 = 1.,
     59         t2 = t1 + sample_duration * sample_repeat - .1,
     60         t3 = t2 - sample_duration + .1,
     61         t4 = t3 + sample_duration + .1,
     62         t5 = t4 + sample_duration + .1,
     63         total_duration = t5 + sample_duration + .1;
     64
     65  //aubio_sampler_set_transpose(sampler, 0.);
     66  //aubio_sampler_set_stretch(sampler, .8);
    3267
    3368  do {
    34     aubio_source_do(source, vec, &read);
    35     if (n_frames / hop_size == 10) {
     69    if (time_was_reached(t1, n_frames, hop_size, samplerate)) {
     70      PRINT_MSG("`-test one shot play of loaded sample\n");
     71      aubio_sampler_set_loop( sampler, 1);
    3672      aubio_sampler_play ( sampler );
     73    } else if (time_was_reached(t2, n_frames, hop_size, samplerate)) {
     74      PRINT_MSG("`-test queueing while playing after eof was reached\n");
     75      //aubio_sampler_queue (sampler, sample_path);
     76      //aubio_sampler_play (sampler);
     77      aubio_sampler_set_loop( sampler, 0);
     78#if 0
     79    } else if (time_was_reached(t3, n_frames, hop_size, samplerate)) {
     80      PRINT_MSG("`-test queueing twice cancels the first one\n");
     81      aubio_sampler_queue (sampler, sample_path);
     82      aubio_sampler_queue (sampler, sample_path);
     83      aubio_sampler_play (sampler);
     84    } else if (time_was_reached(t4, n_frames, hop_size, samplerate)) {
     85      PRINT_MSG("`-test queueing a corrupt file\n");
     86      aubio_sampler_queue (sampler, "/dev/null");
     87      aubio_sampler_play (sampler);
     88    } else if (time_was_reached(t5, n_frames, hop_size, samplerate)) {
     89      aubio_sampler_stop ( sampler );
     90      PRINT_MSG("`-test queueing a correct file after a corrupt one\n");
     91      uint_t i;
     92      for (i = 0; i < 4; i++)
     93        aubio_sampler_queue (sampler, "/dev/null");
     94      aubio_sampler_queue (sampler, "/dev/null1");
     95      aubio_sampler_queue (sampler, "/dev/null2");
     96      aubio_sampler_queue (sampler, sample_path);
     97      aubio_sampler_play (sampler);
     98#endif
    3799    }
     100    /*
    38101    if (n_frames / hop_size == 40) {
    39       aubio_sampler_play ( sampler );
     102      aubio_sampler_queue (sampler, sample_path);
     103      aubio_sampler_queue (sampler, sample_path);
     104      aubio_sampler_seek ( sampler, 0);
    40105    }
    41106    if (n_frames / hop_size == 70) {
    42       aubio_sampler_play ( sampler );
     107      aubio_sampler_seek ( sampler, 0);
    43108    }
    44     if (n_frames > 10.0 * samplerate) {
    45       aubio_sampler_stop ( sampler );
    46     }
    47     aubio_sampler_do (sampler, vec, vec);
    48     aubio_sink_do(sink, vec, read);
    49     n_frames += read;
    50   } while ( read == hop_size );
     109    */
     110    aubio_sampler_do (sampler, vec, &read);
     111    if (sink) aubio_sink_do(sink, vec, hop_size);
     112    n_frames += hop_size;
     113    frames_played += read;
     114  //} while ( read == hop_size );
     115    // last for 40 seconds
     116  } while ( n_frames <= total_duration * samplerate );
     117  PRINT_MSG("reached %.2f sec at %d samples, sampler played %d frames\n",
     118      total_duration, n_frames, frames_played);
    51119
     120  if (sink) del_aubio_sink(sink);
     121beach_sink:
    52122  del_aubio_sampler(sampler);
    53   del_aubio_source(source);
    54   del_aubio_sink(sink);
     123beach_sampler:
    55124  del_fvec(vec);
     125beach:
    56126  aubio_cleanup();
    57 
    58127  return 0;
    59128}
  • wscript

    rb762f8d rb201912  
    6666            help_str = 'compile with samplerate (auto)',
    6767            help_disable_str = 'disable samplerate')
     68    add_option_enable_disable(ctx, 'rubberband', default = None,
     69            help_str = 'compile with rubberband (auto)',
     70            help_disable_str = 'disable rubberband')
    6871    add_option_enable_disable(ctx, 'memcpy', default = True,
    6972            help_str = 'use memcpy hacks (default)',
     
    118121    ctx.check(header_name='unistd.h', mandatory = False)
    119122
     123    ctx.check(header_name='pthread.h', mandatory = False)
     124    needs_pthread = ctx.get_define("HAVE_PTHREAD_H") is not None
     125    if needs_pthread:
     126        ctx.check_cc(lib="pthread", uselib_store="PTHREAD", mandatory=needs_pthread)
     127
    120128    target_platform = sys.platform
    121129    if ctx.options.target_platform:
     
    298306                args = '--cflags --libs samplerate >= 0.0.15',
    299307                mandatory = ctx.options.enable_samplerate)
     308
     309    # check for librubberband
     310    if (ctx.options.enable_rubberband != False):
     311        ctx.check_cfg(package = 'rubberband', atleast_version = '1.3',
     312                args = '--cflags --libs',
     313                mandatory = ctx.options.enable_rubberband)
    300314
    301315    # check for jack
Note: See TracChangeset for help on using the changeset viewer.