#ifdef NT #include "stdafx.h" #include #endif #include "m_pd.h" #include #include #include "monorhythm.h" /** * The monorhythm object is designed to help build polyrhythms. 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); }