Changes in / [c7d444a:bad88364]


Ignore:
Files:
14 added
11 edited

Legend:

Unmodified
Added
Removed
  • .travis.yml

    rc7d444a rbad88364  
    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
     
    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

    rc7d444a rbad88364  
    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
     
    184191    def gen_code(self):
    185192        out = ""
    186         out += self.gen_struct()
    187         out += self.gen_doc()
    188         out += self.gen_new()
    189         out += self.gen_init()
    190         out += self.gen_del()
    191         out += self.gen_do()
    192         out += self.gen_memberdef()
    193         out += self.gen_set()
    194         out += self.gen_get()
    195         out += self.gen_methodef()
    196         out += self.gen_typeobject()
     193        try:
     194            out += self.gen_struct()
     195            out += self.gen_doc()
     196            out += self.gen_new()
     197            out += self.gen_init()
     198            out += self.gen_del()
     199            out += self.gen_do()
     200            out += self.gen_memberdef()
     201            out += self.gen_set()
     202            out += self.gen_get()
     203            out += self.gen_methodef()
     204            out += self.gen_typeobject()
     205        except Exception as e:
     206            print ("Failed generating code for", self.shortname)
     207            raise
    197208        return out
    198209
     
    266277        if p['type'] == 'char_t*':
    267278            return self.check_valid_char(p)
     279        if p['type'] == 'smpl_t':
     280            return self.check_valid_smpl(p)
    268281        else:
    269282            print ("ERROR, no idea how to check %s for validity" % p['type'])
     
    286299    self->{name} = {defval};
    287300    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.) {{
    288310        self->{name} = {name};
    289311    }}
  • python/lib/gen_external.py

    rc7d444a rbad88364  
    4040  #'sampler',
    4141  'audio_unit',
     42  'timestretch', # TODO fix parsing of uint_t *read in _do
     43  'sampler', # TODO fix parsing of uint_t *read in _do
     44  'ringbuffer',
    4245  ]
    4346
  • python/lib/moresetuptools.py

    rc7d444a rbad88364  
    113113    # loof for additional packages
    114114    print("Info: looking for *optional* additional packages")
    115     packages = ['libavcodec', 'libavformat', 'libavutil',
    116                 'libswresample', 'libavresample',
     115    packages = ['libavcodec', 'libavformat', 'libavutil', 'libavresample',
    117116                'sndfile',
     117                'rubberband',
    118118                #'fftw3f',
    119119               ]
     
    137137    if 'samplerate' in ext.libraries:
    138138        ext.define_macros += [('HAVE_SAMPLERATE', 1)]
     139    if 'rubberband' in ext.libraries:
     140        ext.define_macros += [('HAVE_RUBBERBAND', 1)]
    139141    if 'fftw3f' in ext.libraries:
    140142        ext.define_macros += [('HAVE_FFTW3F', 1)]
  • src/aubio.h

    rc7d444a rbad88364  
    218218#include "pitch/pitchspecacf.h"
    219219#include "tempo/beattracking.h"
     220#include "effects/pitchshift.h"
     221#include "effects/timestretch.h"
    220222#include "utils/scale.h"
    221223#include "utils/hist.h"
     224#include "utils/ringbuffer.h"
    222225#endif
    223226
  • src/io/source_avcodec.c

    rc7d444a rbad88364  
    5858#define AUBIO_AVCODEC_MAX_BUFFER_SIZE FF_MIN_BUFFER_SIZE
    5959
     60#ifdef HAVE_PTHREAD_H
     61// Global mutex to make sure avcodec_open2 is not called simultaneously in a
     62// multithreaded environment. Comment the following define if no lock required.
     63#define HAVE_AUBIO_AVCODEC_MUTEX
     64#include <pthread.h>
     65pthread_mutex_t aubio_avcodec_mutex = PTHREAD_MUTEX_INITIALIZER;
     66#endif /* HAVE_PTHREAD_H */
     67
    6068struct _aubio_source_avcodec_t {
    6169  uint_t hop_size;
     
    8492  uint_t eof;
    8593  uint_t multi;
     94  uint_t has_network_url;
    8695};
    8796
     
    98107  av_url_split(proto, proto_size, authorization, authorization_size, hostname,
    99108      hostname_size, port_ptr, uripath, path_size, s->path);
     109  s->has_network_url = 0;
    100110  if (strlen(proto)) {
    101     return 1;
    102   }
    103   return 0;
     111    s->has_network_url = 1;
     112  }
     113  return s->has_network_url;
    104114}
    105115
     
    128138  strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
    129139
     140#ifdef HAVE_AUBIO_AVCODEC_MUTEX
     141  pthread_mutex_lock(&aubio_avcodec_mutex);
     142#endif /* HAVE_AUBIO_AVCODEC_MUTEX */
     143
    130144  // register all formats and codecs
    131145  av_register_all();
     
    137151  // try opening the file and get some info about it
    138152  AVFormatContext *avFormatCtx = s->avFormatCtx;
     153  AVDictionary *streamopts = 0;
     154  if (s->has_network_url) {
     155    if (av_dict_set(&streamopts, "timeout", "1000000", 0)) { // in microseconds
     156      AUBIO_WRN("source_avcodec: Failed setting timeout to 1000000 for %s\n", s->path);
     157    } else {
     158      AUBIO_WRN("source_avcodec: Setting timeout to 1000000 for %s\n", s->path);
     159    }
     160  }
    139161  avFormatCtx = NULL;
    140   if ( (err = avformat_open_input(&avFormatCtx, s->path, NULL, NULL) ) < 0 ) {
     162  if ( (err = avformat_open_input(&avFormatCtx, s->path, NULL, &streamopts) ) < 0 ) {
    141163    char errorstr[256];
    142164    av_strerror (err, errorstr, sizeof(errorstr));
    143165    AUBIO_ERR("source_avcodec: Failed opening %s (%s)\n", s->path, errorstr);
    144     goto beach;
     166    goto beach_streamopts;
    145167  }
    146168
     
    229251  }
    230252
     253#ifdef HAVE_AUBIO_AVCODEC_MUTEX
     254  pthread_mutex_unlock(&aubio_avcodec_mutex);
     255#endif /* HAVE_AUBIO_AVCODEC_MUTEX */
     256
    231257  /* get input specs */
    232258  s->input_samplerate = avCodecCtx->sample_rate;
     
    270296  //av_log_set_level(AV_LOG_QUIET);
    271297
     298  av_dict_free(&streamopts);
    272299  return s;
    273300
     301beach_streamopts:
     302  av_dict_free(&streamopts);
    274303beach:
    275304  //AUBIO_ERR("can not read %s at samplerate %dHz with a hop_size of %d\n",
    276305  //    s->path, s->samplerate, s->hop_size);
     306#ifdef HAVE_AUBIO_AVCODEC_MUTEX
     307  pthread_mutex_unlock(&aubio_avcodec_mutex);
     308#endif /* HAVE_AUBIO_AVCODEC_MUTEX */
    277309  del_aubio_source_avcodec(s);
    278310  return NULL;
  • src/synth/sampler.c

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

    rc7d444a rbad88364  
    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  - add _set_stretch
     36  - add _set_pitch
    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
     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
    111157/** play sample from start
    112158
     
    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 the eof is being 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

    rc7d444a rbad88364  
    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

    rc7d444a rbad88364  
    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

    rc7d444a rbad88364  
    7575            help_str = 'compile with samplerate (auto)',
    7676            help_disable_str = 'disable samplerate')
     77    add_option_enable_disable(ctx, 'rubberband', default = None,
     78            help_str = 'compile with rubberband (auto)',
     79            help_disable_str = 'disable rubberband')
    7780    add_option_enable_disable(ctx, 'memcpy', default = True,
    7881            help_str = 'use memcpy hacks (default)',
     
    127130    ctx.check(header_name='unistd.h', mandatory = False)
    128131
     132    ctx.check(header_name='pthread.h', mandatory = False)
     133    needs_pthread = ctx.get_define("HAVE_PTHREAD_H") is not None
     134    if needs_pthread:
     135        ctx.check_cc(lib="pthread", uselib_store="PTHREAD", mandatory=needs_pthread)
     136
    129137    target_platform = sys.platform
    130138    if ctx.options.target_platform:
     
    307315                args = '--cflags --libs',
    308316                mandatory = ctx.options.enable_samplerate)
     317
     318    # check for librubberband
     319    if (ctx.options.enable_rubberband != False):
     320        ctx.check_cfg(package = 'rubberband', atleast_version = '1.3',
     321                args = '--cflags --libs',
     322                mandatory = ctx.options.enable_rubberband)
    309323
    310324    # check for jack
Note: See TracChangeset for help on using the changeset viewer.