Index: src/synth/sampler.c
===================================================================
--- src/synth/sampler.c	(revision 8b07fa98b9cae496fc72051dde84311a66a57b00)
+++ src/synth/sampler.c	(revision 82ad1edd0ccc569d36c1091431262e688ecaeb90)
@@ -26,4 +26,5 @@
 #include "io/source.h"
 #include "utils/ringbuffer.h"
+#include "effects/timestretch.h"
 #include "synth/sampler.h"
 
@@ -73,4 +74,6 @@
   uint_t finished;              // end of file was reached
   uint_t eof;                   // end of file is now
+  // time stretching
+  aubio_timestretch_t *ts;
 #ifdef HAVE_THREADS
   // file reading thread
@@ -179,4 +182,8 @@
 #endif
 
+  s->ts = new_aubio_timestretch("default", 1., s->blocksize, s->samplerate);
+  s->source_output_tmp = new_fvec(s->source_blocksize);
+  s->last_read = 0;
+
   return s;
 beach:
@@ -259,5 +266,5 @@
     o->opened = 1;
     ret = AUBIO_OK;
-    AUBIO_WRN("sampler: loaded %s\n", uri);
+    AUBIO_MSG("sampler: loaded %s\n", uri);
     if (o->waited) {
       AUBIO_WRN("sampler: %.2fms (%d samples) taken to load %s\n", 1000. *
@@ -433,10 +440,12 @@
       aubio_ringbuffer_push(s->ring, s->source_output, available);
     }
-    if (available < s->source_blocksize) {
+    if (available < s->blocksize) {
+      //AUBIO_WRN("sampler: short read %d\n", available);
       if (ring_avail + available <= s->blocksize) {
         s->eof_remaining = available + ring_avail;
         if (s->eof_remaining == 0) s->eof_remaining = s->blocksize;
-        //AUBIO_ERR("sampler: marking special eof got: %d, in ring: %d, %d, eof remaining %d\n",
-        //    available, ring_avail, s->blocksize, s->eof_remaining);
+        ring_avail = aubio_ringbuffer_get_available(s->ring);
+        //AUBIO_ERR("sampler: eof in: %d, last fetch: %d, in ring: %d\n",
+        //    s->eof_remaining, available, ring_avail);
         if (s->loop) {
           aubio_sampler_seek(s,0);
@@ -496,6 +505,42 @@
     uint_t *read)
 {
+#if 0
   aubio_sampler_reading_from_source_ring_fetch(s);
   aubio_sampler_reading_from_source_ring_pull(s, output, read);
+#else // raw version
+  uint_t source_read;
+  while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
+      && s->eof_remaining == 0) {
+    aubio_source_do(s->source, s->source_output, &source_read);
+    aubio_timestretch_push(s->ts, s->source_output, source_read);
+    if (source_read < s->source_output->length) s->eof_remaining = source_read;
+    //AUBIO_WRN("sampler: pushed %d, now %d available\n",
+    //    source_read, aubio_timestretch_get_available(s->ts));
+  }
+  aubio_timestretch_do(s->ts, output, read);
+  if (s->eof_remaining > s->blocksize) {
+    s->eof_remaining -= s->blocksize;
+  }
+  if (*read < output->length) {
+    //AUBIO_WRN("sampler: short read %d, eof at %d\n", *read, s->eof_remaining);
+    s->eof_remaining = 0;
+    aubio_timestretch_reset(s->ts);
+    aubio_sampler_do_eof(s);
+    if (s->loop && s->perfectloop) {
+      fvec_t tmpout; tmpout.data = output->data + *read;
+      tmpout.length = output->length - *read;
+      uint_t partialread;
+      while (aubio_timestretch_get_available(s->ts) < (sint_t)tmpout.length
+          && s->eof_remaining == 0) {
+        aubio_source_do(s->source, s->source_output, &source_read);
+        aubio_timestretch_push(s->ts, s->source_output, source_read);
+        if (source_read < s->source_output->length) s->eof_remaining = source_read;
+      }
+      aubio_timestretch_do(s->ts, &tmpout, &partialread);
+      //AUBIO_WRN("sampler: partial read %d + %d\n", *read, partialread);
+      *read += partialread;
+    }
+  }
+#endif
 }
 
@@ -573,4 +618,5 @@
         output->length, *read);
   } else if (s->playing) {
+#if 0
     uint_t available = s->table->length - s->table_index;
     fvec_t tmp;
@@ -600,4 +646,92 @@
       *read = s->blocksize;
     }
+#else
+    fvec_t tmp, tmpout;
+    uint_t source_read = 0;
+    while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
+        && s->eof_remaining == 0) {
+      uint_t available = s->table->length - s->table_index;
+      if (available < s->source_blocksize) {
+        source_read = available;
+      } else {
+        source_read = s->source_blocksize;
+      }
+      tmp.length = source_read; tmp.data = s->table->data + s->table_index;
+      tmpout.data = s->source_output->data; tmpout.length = source_read;
+      fvec_copy(&tmp, &tmpout);
+      aubio_timestretch_push(s->ts, &tmpout, source_read);
+      if (source_read < s->source_blocksize) {
+        s->eof_remaining = source_read;
+        s->table_index = s->source_blocksize - *read;
+      } else {
+        s->table_index += source_read;
+      }
+      if (s->table_index == s->table->length) s->table_index = 0;
+      //AUBIO_WRN("sampler: pushed %d, now %d available, table_index %d, eof %d\n",
+      //    source_read, aubio_timestretch_get_available(s->ts),
+      //    s->table_index, s->eof_remaining);
+    }
+    aubio_timestretch_do(s->ts, output, read);
+    if (*read == 0) {
+      //AUBIO_WRN("sampler: pushed %d, now %d available, table_index %d\n",
+      //    *read, aubio_timestretch_get_available(s->ts), s->table_index);
+    }
+    if (s->eof_remaining > s->blocksize) {
+      s->eof_remaining -= s->blocksize;
+    }
+    if (*read < output->length) {
+      s->eof_remaining = 0;
+      aubio_sampler_do_eof(s);
+    }
+#if 0
+    if (*read < output->length) {
+      //uint_t available = aubio_timestretch_get_available(s->ts);
+      s->eof_remaining = 0;
+      aubio_timestretch_reset(s->ts);
+      aubio_sampler_do_eof(s);
+    }
+#endif
+#if 0
+    if (*read < output->length) {
+      //uint_t available = aubio_timestretch_get_available(s->ts);
+      s->eof_remaining = 0;
+      aubio_timestretch_reset(s->ts);
+      aubio_sampler_do_eof(s);
+      if (s->loop && s->perfectloop) {
+        tmpout.data = output->data + *read;
+        tmpout.length = output->length - *read;
+        while (aubio_timestretch_get_available(s->ts) < (sint_t)tmpout.length
+            && s->eof_remaining == 0) {
+          uint_t available = s->table->length - s->table_index;
+          if (available < s->source_blocksize) {
+            source_read = available;
+          } else {
+            source_read = s->source_blocksize;
+          }
+          //AUBIO_WRN("sampler: short read %d, remaining %d\n", *read, remaining);
+          tmp.length = source_read; tmp.data = s->table->data + s->table_index;
+          fvec_t tmpout2; tmpout2.data = s->source_output->data; tmpout2.length = source_read;
+          fvec_copy(&tmp, &tmpout2);
+          aubio_timestretch_push(s->ts, &tmpout2, source_read);
+          if (source_read < s->source_blocksize) {
+            s->eof_remaining = source_read;
+            s->table_index = 0;
+          } else {
+            s->table_index += source_read;
+          }
+          if (s->table_index == s->table->length) s->table_index = 0;
+          //AUBIO_WRN("sampler: second push, pushed %d, now %d available\n",
+          //    source_read, aubio_timestretch_get_available(s->ts));
+        }
+        uint_t partialread;
+        aubio_timestretch_do(s->ts, &tmpout, &partialread);
+        AUBIO_WRN("sampler: partial read %d + %d\n", *read, partialread);
+        *read += partialread;
+        //s->eof = 1;
+      }
+    }
+#endif
+
+#endif
   }
 }
@@ -628,6 +762,26 @@
     return -1;
   }
+#if 1
   aubio_source_do(s->source, s->source_output, &source_read);
   return source_read;
+#else
+  uint_t source_read_tmp;
+  while (aubio_timestretch_get_available(s->ts) < (sint_t)s->blocksize
+      && s->last_read == 0) {
+    aubio_source_do(s->source, s->source_output_tmp, &source_read_tmp);
+    aubio_timestretch_push(s->ts, s->source_output_tmp, source_read_tmp);
+    if (source_read_tmp < s->source_output_tmp->length) s->last_read = source_read;
+  }
+  aubio_timestretch_do(s->ts, s->source_output, &source_read);
+  if (s->last_read > s->blocksize) {
+    s->last_read -= s->blocksize;
+  }
+  if (source_read < s->source_blocksize) {
+    s->last_read = 0;
+    //AUBIO_ERR("sampler: calling timestretch reset %d %d\n", source_read, s->source_blocksize);
+    aubio_timestretch_reset(s->ts);
+  }
+  return source_read;
+#endif
 }
 
@@ -688,4 +842,5 @@
     ret = AUBIO_OK;
   }
+  o->last_read = 0;
   return ret;
 }
@@ -786,4 +941,30 @@
 }
 
+
+uint_t aubio_sampler_set_stretch(aubio_sampler_t *s, smpl_t stretch)
+{
+  if (!s->ts) return AUBIO_FAIL;
+  return aubio_timestretch_set_stretch(s->ts, stretch);
+}
+
+smpl_t aubio_sampler_get_stretch(aubio_sampler_t *s)
+{
+  if (!s->ts) return 1.;
+  return aubio_timestretch_get_stretch(s->ts);
+}
+
+uint_t aubio_sampler_set_transpose(aubio_sampler_t *s, smpl_t transpose)
+{
+  if (!s->ts) return AUBIO_FAIL;
+  return aubio_timestretch_set_transpose(s->ts, transpose);
+}
+
+smpl_t aubio_sampler_get_transpose(aubio_sampler_t *s)
+{
+  if (!s->ts) return 0.;
+  return aubio_timestretch_get_transpose(s->ts);
+}
+
+
 void del_aubio_sampler( aubio_sampler_t * o )
 {
@@ -804,4 +985,7 @@
     del_aubio_ringbuffer(o->ring);
   }
+  if (o->ts) {
+    del_aubio_timestretch(o->ts);
+  }
   if (o->source) {
     del_aubio_source(o->source);
Index: src/synth/sampler.h
===================================================================
--- src/synth/sampler.h	(revision 8b07fa98b9cae496fc72051dde84311a66a57b00)
+++ src/synth/sampler.h	(revision 82ad1edd0ccc569d36c1091431262e688ecaeb90)
@@ -221,4 +221,42 @@
 uint_t aubio_sampler_get_waited_opening(aubio_sampler_t * o, uint_t waited);
 
+/** get current time stretching factor
+
+  \param o sampler, created by new_aubio_sampler()
+
+  \return the current time stretch factor
+
+ */
+smpl_t aubio_sampler_get_stretch (aubio_sampler_t *o);
+
+/** set current time stretching factor
+
+  \param o sampler, created by new_aubio_sampler()
+  \param stretch new time stretching factor
+
+  \return AUBIO_OK on success, AUBIO_FAIL otherwise
+
+ */
+uint_t aubio_sampler_set_stretch (aubio_sampler_t *o, smpl_t stretch);
+
+/** get current pitch shifting factor
+
+  \param o sampler, created by new_aubio_sampler()
+
+  \return the current pitch transposition factor
+
+ */
+smpl_t aubio_sampler_get_transpose (aubio_sampler_t *o);
+
+/** set current pitch shifting factor
+
+  \param o sampler, created by new_aubio_sampler()
+  \param transpose new pitch shifting (transposition) factor
+
+  \return AUBIO_OK on success, AUBIO_FAIL otherwise
+
+ */
+uint_t aubio_sampler_set_transpose (aubio_sampler_t *o, smpl_t transpose);
+
 /** get the current perfect loop mode
 
