aboutsummaryrefslogtreecommitdiff
path: root/monorhythm.c
diff options
context:
space:
mode:
Diffstat (limited to 'monorhythm.c')
-rw-r--r--monorhythm.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/monorhythm.c b/monorhythm.c
new file mode 100644
index 0000000..2855820
--- /dev/null
+++ b/monorhythm.c
@@ -0,0 +1,238 @@
+#ifdef NT
+#include "stdafx.h"
+#include <io.h>
+#endif
+#include "m_pd.h"
+#include <stdlib.h>
+#include <time.h>
+#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);
+ class_sethelpsymbol(monorhythm_class, gensym("mjLib/monorhythm"));
+}
+