From 1baf1d957e195290cfd59089767ca63a547a9917 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 7 Apr 2004 14:32:29 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r1560, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/mjlib/; revision=1561 --- monorythm.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 monorythm.c (limited to 'monorythm.c') diff --git a/monorythm.c b/monorythm.c new file mode 100644 index 0000000..62bcbac --- /dev/null +++ b/monorythm.c @@ -0,0 +1,238 @@ +#ifdef NT +#include "stdafx.h" +#include +#endif +#include "m_pd.h" +#include +#include +#include "monorythm.h" + +/** +* The monorhythm object is designed to help build polyrythms. Given +* a time interval and a pattern it produces the pattern within the time +* interval given. Thus if two where set going with the same time interval +* the two patterns (assuming they where different) would play against +* each other. +* +* this filename is spelt wrong 'cos I can't spell +*/ + +static t_class *monorhythm_class; + +/** +* clock tick - do a bang and wait the next +* time delay in the list +*/ + +static void monorhythm_tick(t_monorhythm *x) +{ + if ( x->t_running ) + { + monorhythm_do_beat( x ); + clock_delay(x->x_clock, x->x_beattime ); + } +} + +static void monorhythm_do_beat( t_monorhythm* x ) +{ + float beat; + if ( x->x_idx == x->x_size ) + { + x->x_idx = 0; + + } + if ( x->x_idx == 0) + { + outlet_bang( x->x_sync ); + } + beat = x->x_pattern[ x->x_idx++ ]; + if ( beat > 1 ) + { + if ( x->t_exclusive == 0 ) + { + outlet_bang( x->x_bang ); + } + outlet_bang( x->x_accent ); + } + else if ( beat == 1 ) + { + outlet_bang( x->x_bang ); + } +} + + +/** +* a bang causes a reset to the start of the bar - used to +* synchronize multiple monorhythm's. If the rhythm is not +* running it is started +*/ + + +static void monorhythm_bang(t_monorhythm *x) +{ + if ( x->x_beattime > 0 ) + { + monorhythm_restart( x ); + } +} + +/** +* reset the rhythm to start at the beginning +*/ + +static void monorhythm_restart(t_monorhythm *x) +{ + if ( x->x_beattime > 0 ) + { + x->t_running = 1; + x->x_idx = 0; + monorhythm_do_beat( x ); + clock_delay(x->x_clock, x->x_beattime ); + } +} + +/** +* a stop message turns us off +*/ + +static void monorhythm_stop(t_monorhythm *x) +{ + x->t_running = 0; +} + +/** +* set exclusive mode +*/ + +static void monorhythm_set_exclusive(t_monorhythm *x) +{ + x->t_exclusive = 1; +} + +/** +* set nonexclusive mode +*/ + +static void monorhythm_set_nonexclusive(t_monorhythm *x) +{ + x->t_exclusive = 0; +} + +/** +* free our clock and our timer array +*/ + +static void monorhythm_free(t_monorhythm *x) +{ + clock_free(x->x_clock); + free( x->x_pattern ); +} + +/* +* make a new monorhythm - we can provide a list of times +* so read these in too +*/ + +static void *monorhythm_new(t_symbol *s, int argc, t_atom *argv) +{ + float f; + t_monorhythm *x = (t_monorhythm *)pd_new(monorhythm_class); + x->x_pattern = NULL; + // parse any settings + if ( argc > 0 ) + { + f = atom_getfloat( &argv[0] ); + monorhythm_set_time( x , f ); + monorhythm_pattern_seq( x, s , argc - 1 , argv + 1 ); + } + x->t_running=0; + x->t_exclusive = 0; + // make us some ins and outs + x->x_clock = clock_new(x, (t_method)monorhythm_tick); + x->x_bang = outlet_new(&x->x_obj, gensym("bang")); + x->x_accent = outlet_new(&x->x_obj, gensym("accent")); + x->x_sync = outlet_new(&x->x_obj, gensym("sync")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("pattern")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("timeinterval")); + return (x); +} + +/** +* set a time sequence and free the old array +*/ + +static void monorhythm_pattern_seq( t_monorhythm *x, t_symbol *s, int ac, t_atom *av ) +{ + int i; + if ( x->x_pattern != NULL ) + { + free( x->x_pattern ); + } + if ( ac > 0 ) + { + x->x_pattern = (float *) malloc( ac * sizeof( float )); + for( i = 0 ; i < ac ; i++ ) + { + float t = atom_getfloat( &av[i] ); + x->x_pattern[i] = t; + } + x->x_size=ac; + monorhythm_calculate_beat_interval( x ); + } + else + { + // if there is no pattern it doens't do anything + x->x_pattern = NULL; + x->x_size=0; + x->t_running = 0; + } + x->x_idx = 0; +} + +/** +* the time interval is divided by the number of beats that are +* going to happen in order to get the beat time. If this would +* be invallid for any reason it is set to 0 and the rhythm is stopped +*/ + +static void monorhythm_calculate_beat_interval( t_monorhythm *x ) +{ + if ( ( x->x_size > 0 ) && ( x->x_time > 0 )) + { + x->x_beattime = x->x_time / x->x_size; + } + else + { + x->x_beattime = 0; + x->t_running = 0; + } +} + +/** +* set the time - recalculate the beat time +*/ + +static void monorhythm_set_time( t_monorhythm *x, t_float f ) +{ + x->x_time = f; + monorhythm_calculate_beat_interval( x ); +} + +/** +* make a new one and setup all of our messages +*/ + + void monorhythm_setup(void) +{ + monorhythm_class = class_new(gensym("monorhythm"), (t_newmethod)monorhythm_new, + (t_method)monorhythm_free, sizeof(t_monorhythm), 0, A_GIMME, 0); + class_addbang(monorhythm_class, monorhythm_bang); + class_addmethod(monorhythm_class, (t_method)monorhythm_stop, gensym("stop"), 0); + class_addmethod(monorhythm_class, (t_method)monorhythm_bang, gensym("start"), 0); + class_addmethod(monorhythm_class, (t_method)monorhythm_pattern_seq, gensym("pattern" ), A_GIMME, 0); + class_addmethod(monorhythm_class, (t_method)monorhythm_set_time, gensym("timeinterval" ), A_FLOAT, 0); + class_addmethod(monorhythm_class, (t_method)monorhythm_set_exclusive,gensym("exclusive"),0); + class_addmethod(monorhythm_class, (t_method)monorhythm_set_nonexclusive,gensym("nonexclusive"),0); + class_sethelpsymbol(monorhythm_class, gensym("mjLib/monorhythm")); +} + -- cgit v1.2.1