From: Paul Brossier Date: Fri, 30 Sep 2016 10:32:21 +0000 (+0200) Subject: src/aubiostretchsf~.c: a replacement of readsf~, with time-stretching X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=f5203f858abe837d83665a4d043e4baaa97a366d;p=pd-aubio.git src/aubiostretchsf~.c: a replacement of readsf~, with time-stretching --- diff --git a/src/aubiostretchsf~.c b/src/aubiostretchsf~.c new file mode 100644 index 0000000..a0e16bd --- /dev/null +++ b/src/aubiostretchsf~.c @@ -0,0 +1,175 @@ +/* + Copyright (C) 2016 Paul Brossier + + This file is part of pd-aubio. + + aubio is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + aubio is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with aubio. If not, see . + +*/ + +#include +#define AUBIO_UNSTABLE 1 +#include +#include + +char aubiostretchsf_version[] = "aubiostretchsf~ version " PACKAGE_VERSION; + +static t_class *aubiostretchsf_tilde_class; + +void aubiostretchsf_tilde_setup (void); + +typedef struct _aubiostretchsf_tilde +{ + t_object x_obj; + aubio_timestretch_t *o; + fvec_t *out; + t_inlet *inlet_s; + t_inlet *inlet_t; + t_outlet *outlet; + t_outlet *outlet_done; + t_clock *clock_done; + smpl_t stretch; + smpl_t transpose; + int playing; + int ended; +} t_aubiostretchsf_tilde; + +static t_int * +aubiostretchsf_tilde_perform (t_int * w) +{ + t_aubiostretchsf_tilde *x = (t_aubiostretchsf_tilde *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + int s_n = (int)w[3]; + int read = 0; + if (x->playing) { + aubio_timestretch_set_stretch(x->o, x->stretch); + aubio_timestretch_set_transpose(x->o, x->transpose); + aubio_timestretch_do(x->o, x->out, &read); + if (read > 0) { + memcpy(out, x->out->data, read * sizeof(smpl_t)); + } + if (read > 0 && s_n > read) { + //post("feel-in %d with zeros", sys_getblksize() - read); + memset(out + read, 0, (s_n - read) * sizeof(smpl_t)); + //post("sending clock"); + clock_delay(x->clock_done, 0); + x->playing = 0; + x->ended = 1; + } + if (read <= 0) { + // occurs when the previous read was a short read of a complete buffer + clock_delay(x->clock_done, 0); + x->playing = 0; + x->ended = 1; + } + } else { + memset(out, 0, s_n * sizeof(smpl_t)); + } + return (w + 4); +} + +static void +aubiostretchsf_tilde_tick(t_aubiostretchsf_tilde * x) +{ + outlet_bang(x->outlet_done); +} + +static void +aubiostretchsf_tilde_dsp (t_aubiostretchsf_tilde * x, t_signal ** sp) +{ + dsp_add (aubiostretchsf_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void * +aubiostretchsf_tilde_new (t_symbol *s, int argc, t_atom *argv) +{ + t_aubiostretchsf_tilde *x = (t_aubiostretchsf_tilde *)pd_new(aubiostretchsf_tilde_class); + x->out = new_fvec(sys_getblksize()); + if (x->out == NULL) return NULL; + x->clock_done = clock_new(x, (t_method)aubiostretchsf_tilde_tick); + x->transpose = 0.; + x->stretch = 1.; + x->playing = 0; + x->ended = 0; + x->inlet_s = floatinlet_new (&x->x_obj, &x->stretch); + x->inlet_t = floatinlet_new (&x->x_obj, &x->transpose); + x->outlet = outlet_new(&x->x_obj, gensym("signal")); + x->outlet_done = outlet_new(&x->x_obj, &s_bang); + return (void *)x; +} + +static void * +aubiostretchsf_tilde_open (t_aubiostretchsf_tilde *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *uri = atom_getsymbolarg(0, argc, argv); + if (!*uri->s_name) { + post("aubiostretchsf~: open: no filename given"); + return; + } + x->playing = 0; + // TODO: add aubio_timestretch_open method + if (x->o) del_aubio_timestretch(x->o); + x->o = new_aubio_timestretch(uri->s_name, "default", 1., sys_getblksize(), + sys_getsr()); +} + +void +aubiostretchsf_tilde_float(t_aubiostretchsf_tilde *x, t_floatarg f) { + if (x->o == NULL) return; + if (f == 2) { + uint_t res = aubio_timestretch_seek(x->o, 0); + if (res != 0) + post("failed seeking"); + x->ended = 0; + x->playing = 1; + } else if (f == 1) { + //x->stretch = f; + if (x->ended) { + uint_t res = aubio_timestretch_seek(x->o, 0); + if (res != 0) + post("failed seeking"); + x->ended = 0; + } + x->playing = 1; + } else { + x->playing = 0; + } +} + +void +aubiostretchsf_tilde_del (t_aubiostretchsf_tilde *x) +{ + del_fvec(x->out); + if (x->o) del_aubio_timestretch(x->o); + inlet_free(x->inlet_s); + inlet_free(x->inlet_t); + outlet_free(x->outlet); + outlet_free(x->outlet_done); + clock_free(x->clock_done); +} + +void +aubiostretchsf_tilde_setup (void) +{ + aubiostretchsf_tilde_class = class_new (gensym ("aubiostretchsf~"), + (t_newmethod) aubiostretchsf_tilde_new, + (t_method) aubiostretchsf_tilde_del, + sizeof (t_aubiostretchsf_tilde), + CLASS_DEFAULT, A_GIMME, 0); + class_addfloat (aubiostretchsf_tilde_class, (t_method)aubiostretchsf_tilde_float); + class_addmethod (aubiostretchsf_tilde_class, + (t_method)aubiostretchsf_tilde_open, gensym ("open"), A_GIMME, 0); + class_addmethod (aubiostretchsf_tilde_class, + (t_method)aubiostretchsf_tilde_dsp, gensym ("dsp"), A_CANT, 0); +}