From faada59567f8cb252f4a909116595ce309ff5828 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Fri, 23 May 2003 12:29:55 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r647, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/miXed/; revision=648 --- cyclone/sickle/record.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 cyclone/sickle/record.c (limited to 'cyclone/sickle/record.c') diff --git a/cyclone/sickle/record.c b/cyclone/sickle/record.c new file mode 100644 index 0000000..ba2e3b5 --- /dev/null +++ b/cyclone/sickle/record.c @@ -0,0 +1,242 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include "m_pd.h" +#include "shared.h" +#include "sickle/sic.h" +#include "sickle/arsic.h" + +typedef struct _record +{ + t_arsic x_arsic; + float x_startpoint; /* the inputs */ + float x_endpoint; + int x_appendmode; + int x_loopmode; + int x_startindex; + int x_endindex; /* (one past last record position) */ + int x_pauseindex; + int x_phase; /* writing head */ + float x_sync; + float x_syncincr; + int x_isrunning; /* to know if sync should be 0.0 or 1.0 */ + t_clock *x_clock; +} t_record; + +static t_class *record_class; + +static void record_tick(t_record *x) +{ + arsic_redraw((t_arsic *)x); +} + +static void record_setsync(t_record *x) +{ + /* CHECKED: clipped to array size -- using indices, not points */ + float range = (float)(x->x_endindex - x->x_startindex); + int phase = x->x_phase; + if (phase == SHARED_INT_MAX || range < 1.0) + { + x->x_sync = (x->x_isrunning ? 1.0 : 0); /* CHECKED */ + x->x_syncincr = 0; + } + else + { + x->x_sync = (float)(phase - x->x_startindex) / range; + x->x_syncincr = 1.0 / range; + } +} + +static void record_mstoindex(t_record *x) +{ + t_arsic *sic = (t_arsic *)x; + x->x_startindex = (int)(x->x_startpoint * sic->s_ksr); + if (x->x_startindex < 0) + x->x_startindex = 0; /* CHECKED */ + x->x_endindex = (int)(x->x_endpoint * sic->s_ksr); + if (x->x_endindex > sic->s_vecsize + || x->x_endindex <= 0) + x->x_endindex = sic->s_vecsize; /* CHECKED (both ways) */ + record_setsync(x); +} + +static void record_set(t_record *x, t_symbol *s) +{ + arsic_setarray((t_arsic *)x, s, 1); + record_mstoindex(x); +} + +static void record_startpoint(t_record *x, t_floatarg f) +{ + x->x_startpoint = f; + record_mstoindex(x); +} + +static void record_endpoint(t_record *x, t_floatarg f) +{ + x->x_endpoint = f; + record_mstoindex(x); +} + +static void record_float(t_record *x, t_float f) +{ + if (x->x_isrunning = (f != 0)) + { + /* CHECKED: no (re)start in append mode */ + /* LATER consider restart if x->x_pauseindex == SHARED_INT_MAX */ + x->x_phase = x->x_appendmode ? x->x_pauseindex : x->x_startindex; + if (x->x_phase >= x->x_endindex) x->x_phase = SHARED_INT_MAX; + } + else if (x->x_phase != SHARED_INT_MAX) /* CHECKED: no rewind */ + { + record_tick(x); + x->x_pauseindex = x->x_phase; + x->x_phase = SHARED_INT_MAX; + } + record_setsync(x); +} + +static void record_append(t_record *x, t_floatarg f) +{ + if (f != 0) + { + x->x_appendmode = 1; /* CHECKED: always allow appending */ + } + else x->x_appendmode = 0; +} + +static void record_loop(t_record *x, t_floatarg f) +{ + x->x_loopmode = (f != 0); +} + +static t_int *record_perform(t_int *w) +{ + t_arsic *sic = (t_arsic *)(w[1]); + int nblock = (int)(w[2]); + int nch = sic->s_nchannels; + t_float *out = (t_float *)(w[3 + nch]); + t_record *x = (t_record *)sic; + int phase = x->x_phase; + int endphase = x->x_endindex; + float sync = x->x_sync; + if (sic->s_playable && endphase > phase) + { + int vecsize = sic->s_vecsize; + float syncincr = x->x_syncincr; + int ch, over, i, nxfer; +loopover: + if ((nxfer = endphase - phase) > nblock) + { + nxfer = nblock; + over = 0; + } + else over = 1; + ch = nch; + while (ch--) + { + t_float *vp = sic->s_vectors[ch]; + if (vp) + { + t_float *ip = (t_float *)(w[3 + ch]); + vp += phase; + i = nxfer; + /* LATER consider handling under and overflows */ + while (i--) *vp++ = *ip++; + } + } + i = nxfer; + while (i--) + { + *out++ = sync; + sync += syncincr; + } + if (over) + { + nblock -= nxfer; + if (x->x_loopmode + && (phase = x->x_startindex) < endphase) + { + x->x_phase = phase; + x->x_sync = sync = 0; + if (nblock > 0) goto loopover; + goto done; + } + clock_delay(x->x_clock, 0); + /* CHECKED: no restart in append mode */ + x->x_pauseindex = SHARED_INT_MAX; + x->x_phase = SHARED_INT_MAX; + x->x_sync = 1.0; + x->x_syncincr = 0; + } + else + { + x->x_phase += nxfer; + x->x_sync = sync; + goto done; + } + } + while (nblock--) *out++ = sync; +done: + return (w + sic->s_nperfargs + 1); +} + +static void record_dsp(t_record *x, t_signal **sp) +{ + arsic_dsp((t_arsic *)x, sp, record_perform, 1); + record_mstoindex(x); +} + +static void record_free(t_record *x) +{ + arsic_free((t_arsic *)x); + if (x->x_clock) clock_free(x->x_clock); +} + +static void *record_new(t_symbol *s, t_floatarg f) +{ + /* one auxiliary signal: sync output */ + t_record *x = (t_record *)arsic_new(record_class, s, (int)f, 0, 1); + if (x) + { + int nch = arsic_getnchannels((t_arsic *)x); + arsic_setminsize((t_arsic *)x, 2); + x->x_startpoint = 0; + x->x_endpoint = 0; + x->x_appendmode = 0; + x->x_loopmode = 0; + x->x_pauseindex = SHARED_INT_MAX; + x->x_phase = SHARED_INT_MAX; + x->x_isrunning = 0; + record_mstoindex(x); + x->x_clock = clock_new(x, (t_method)record_tick); + while (--nch) + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft-2")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft-1")); + outlet_new((t_object *)x, &s_signal); + } + return (x); +} + +void record_tilde_setup(void) +{ + record_class = class_new(gensym("record~"), + (t_newmethod)record_new, + (t_method)record_free, + sizeof(t_record), 0, + A_DEFSYM, A_DEFFLOAT, 0); + arsic_setup(record_class, record_dsp, record_float); + class_addmethod(record_class, (t_method)record_startpoint, + gensym("ft-2"), A_FLOAT, 0); + class_addmethod(record_class, (t_method)record_endpoint, + gensym("ft-1"), A_FLOAT, 0); + class_addmethod(record_class, (t_method)record_append, + gensym("append"), A_FLOAT, 0); + class_addmethod(record_class, (t_method)record_loop, + gensym("loop"), A_FLOAT, 0); + class_addmethod(record_class, (t_method)record_set, + gensym("set"), A_SYMBOL, 0); +} -- cgit v1.2.1