diff options
Diffstat (limited to 'src/common~.c')
-rw-r--r-- | src/common~.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/src/common~.c b/src/common~.c new file mode 100644 index 0000000..573eaf1 --- /dev/null +++ b/src/common~.c @@ -0,0 +1,247 @@ +//#include "commonget~.h" +#include "m_pd.h" + + +typedef struct _common { + t_symbol* name; + t_sample a[64]; + t_sample b[64]; + t_sample* w; + t_sample* r; + //int writers; + //int written; + int users; + struct _common* next; + struct _common* previous; + t_clock* clock; + int armed; + +} t_common; + + +static t_common* common; + + +// This should be triggered by the clock +static void common_swap(t_common* pg) { + //post("clock"); + + t_sample* temp = pg->r; + pg->r = pg->w; + pg->w = temp; + + int i; + t_sample* samples = pg->w; + for (i=0;i<64;i++) { + *samples++ = 0; + + } + + pg->armed = 0; + + //if (pg == NULL) post("ouc"); + //pg->written = 0; + +} + +static t_common* common_register(t_symbol* name) { + + t_common* new_common; + + //is_writer = is_writer ? 1 : 0; + + t_common* pg = common; + + if ( pg != NULL) { + + // Search for previous common + while( pg ) { + if ( pg->name == name) { + //#ifdef PARAMDEBUG + // post("Found put/get with same name"); + //#endif + //pg->writers = pg->writers + is_writer; + pg->users = pg->users + 1; + return pg; + } + if ( pg->next == NULL ) break; + pg = pg->next; + } + } + + + //post("Appending new put/get"); + // Append new common + new_common = getbytes(sizeof(*new_common)); + new_common->name = name; + //new_common->writers = is_writer; + new_common->users = 1; + new_common->armed = 0; + + new_common->clock = clock_new(new_common, (t_method)common_swap); + + new_common->r = new_common->a; + new_common->w = new_common->b; + + new_common->previous = pg; + if ( pg) { + pg->next = new_common; + } else { + common = new_common; + } + + return new_common; + +} + + +static void common_unregister(t_common* pg) { + + //post("Trying to remove %s",pg->name->s_name); + + //if ( is_writer) pg->writers = pg->writers - 1; + pg->users = pg->users - 1; + if ( pg->users <= 0) { + //post("Removing last put/get of this name"); + if (pg->previous) { + pg->previous->next = pg->next; + if (pg->next) pg->next->previous = pg->previous; + } else { + common = pg->next; + if ( pg->next != NULL) pg->next->previous = NULL; + } + clock_free(pg->clock); + freebytes(pg, sizeof *(pg) ); + } +} + + +static void common_arm(t_common* pg) { + + if (!pg->armed) { + pg->armed = 1; + clock_delay(pg->clock, 0); + } + +} + +/////////////// +// The class // +/////////////// + +static t_class *common_tilde_class; + +typedef struct _common_tilde { + t_object x_obj; + //t_sample f_common; + t_common* pg; + t_sample f; +} t_common_tilde; + +static t_int* common_tilde_perform(t_int *w) +{ + + t_common_tilde *x = (t_common_tilde *)(w[1]); + + t_sample *in = (t_sample *)(w[2]); + t_sample *out= (t_sample *)(w[3]); + int n = (int)(w[4]); + int m; + t_sample *samples; + + + if ( x->pg) { + + // Do adding + //if (x->pg->users > x->pg->writers) { + samples = x->pg->w; + m = n; + while (m--) { + *samples = *samples + *in; + samples++; in++; + } + + //} + + + // Do reading + samples = x->pg->r; + m = n; + while (m--) { + *out++ = *samples++; + } + + // Arm for swaping + common_arm( x->pg); + + } else { + + while (n--) { + *out++ = 0; + } + + } + + return (w+5); +} + + +static void common_tilde_set(t_common_tilde *x, t_symbol* s) { + + if (gensym("") != s ) { + if ( x->pg ) { + if ( x->pg->name != s) { + common_unregister(x->pg); + x->pg = common_register(s); + } + } else { + x->pg = common_register(s); + } + } + +} + + +static void common_tilde_dsp(t_common_tilde *x, t_signal **sp) +{ + + if ( (int) sp[0]->s_n == 64 ) { + dsp_add(common_tilde_perform, 4, x,sp[0]->s_vec,sp[1]->s_vec, sp[0]->s_n); + + } else { + error("common~ only works with a block size of 64"); + } + +} + +static void common_tilde_free( t_common_tilde *x) { + + if (x->pg) common_unregister(x->pg); +} + + +static void *common_tilde_new(t_symbol* s) +{ + t_common_tilde *x = (t_common_tilde *)pd_new(common_tilde_class); + + if (gensym("") != s ) x->pg = common_register(s); + + outlet_new(&x->x_obj, &s_signal); + + return (void *)x; +} + +void common_tilde_setup(void) { + common_tilde_class = class_new(gensym("common~"), + (t_newmethod)common_tilde_new, + (t_method)common_tilde_free, sizeof(t_common_tilde), + 0, A_DEFSYM, 0); + + class_addmethod(common_tilde_class, + (t_method)common_tilde_dsp, gensym("dsp"), 0); + + class_addmethod(common_tilde_class, + (t_method)common_tilde_set, gensym("set"), A_SYMBOL, 0); + + CLASS_MAINSIGNALIN(common_tilde_class, t_common_tilde, f); +} |