From 0928c7fa0e2b91005ac6c319650e9e13468903cd Mon Sep 17 00:00:00 2001 From: Davide Morelli Date: Tue, 27 Dec 2005 01:28:51 +0000 Subject: added rhythms playing. still need debugging svn path=/trunk/externals/frankenstein/; revision=4300 --- common.c | 4 +- common.h | 2 +- rhythms_memory.c | 128 ++++++++++++++++++++++++++++++++++++++++--------- test-rhythms_memory.pd | 66 +++++++++++++++---------- 4 files changed, 150 insertions(+), 50 deletions(-) diff --git a/common.c b/common.c index 9fe2c36..7b024a0 100755 --- a/common.c +++ b/common.c @@ -683,7 +683,7 @@ void rhythm_memory_evaluate(t_rhythm_memory_representation *rep_list, // the mem } // return 0 if failed finding the rhythm, 1 if the rhythm was found int rhythm_memory_get_rhythm(t_rhythm_memory_representation *rep_list, // the memory - t_rhythm_event *out_rhythm, // a pointer to the returned rhythm + t_rhythm_event **out_rhythm, // a pointer to the returned rhythm // the id of the main rhythm wanted unsigned short int id, // the sub-id of the sub-rhythm wanted @@ -705,7 +705,7 @@ int rhythm_memory_get_rhythm(t_rhythm_memory_representation *rep_list, // the me if (curr2->id == sub_id) { // i've found the rhythm! - out_rhythm=curr2->rhythm; + *out_rhythm=curr2->rhythm; return 1; } curr2 = curr2->next; diff --git a/common.h b/common.h index c9bfa39..cbf3744 100755 --- a/common.h +++ b/common.h @@ -257,7 +257,7 @@ void rhythm_memory_evaluate(t_rhythm_memory_representation *rep_list, // the mem ); // return 0 if failed finding the rhythm, 1 if the rhythm was found int rhythm_memory_get_rhythm(t_rhythm_memory_representation *rep_list, // the memory - t_rhythm_event *out_rhythm, // a pointer to the returned rhythm + t_rhythm_event **out_rhythm, // a pointer to the returned rhythm // the id of the main rhythm wanted unsigned short int id, // the sub-id of the sub-rhythm wanted diff --git a/rhythms_memory.c b/rhythms_memory.c index 80a74dd..dd6871e 100755 --- a/rhythms_memory.c +++ b/rhythms_memory.c @@ -9,9 +9,9 @@ uses graphs to store rhythms TODO: * test and debug core functionalities * memory save/load to file - * output rhythms in realtime (BANGs) * output rhythms in the form of list of floats * add velo + * input rhythms from a list (second inlet) */ @@ -35,7 +35,11 @@ typedef struct event typedef struct _rhythms_memory { t_object x_obj; // myself - t_outlet *l_out; + // 3 outlets: + // bangs_out plays the wanted rhythmsin realtime + // list_out outputs the wanted rhythm as a list of floats + // info_out outputs info on the last recognized rhythm + t_outlet *bangs_out, *list_out, *info_out; t_rhythm_event *curr_seq; int seq_initialized; // the memory @@ -51,6 +55,7 @@ typedef struct _rhythms_memory event *events_out; t_clock *x_clock; double x_deltime; + double last_event_out_time; } t_rhythms_memory; @@ -64,13 +69,16 @@ void rhythms_memory_free(t_rhythms_memory *x) clock_free(x->x_clock); } +// called when a new measure starts void start_measure(t_rhythms_memory *x) { // I call the pd functions to get a representation // of this very moment x->measure_start_time = clock_getlogicaltime(); + x->last_event_out_time = 0; } +// called when a new event occours void add_event(t_rhythms_memory *x, unsigned short int voice) { event *newEvent, *currEvent, *lastEvent; @@ -98,6 +106,7 @@ void add_event(t_rhythms_memory *x, unsigned short int voice) post("event added"); } +// called when a measure ends void end_measure(t_rhythms_memory *x) { float fduration; @@ -110,6 +119,8 @@ void end_measure(t_rhythms_memory *x) // these 2 are for output rhythm int rhythm_found; t_rhythm_event *wanted_rhythm; + t_rhythm_event *curr_rhythm; + event *lastOutEvent; // I call the pd functions to get a representation // of this very moment @@ -160,7 +171,7 @@ void end_measure(t_rhythms_memory *x) SETFLOAT(lista+2, (float) subid); SETFLOAT(lista+3, (float) root_closeness); SETFLOAT(lista+4, (float) sub_closeness); - outlet_anything(x->l_out, + outlet_anything(x->info_out, gensym("list") , 5, lista); @@ -184,9 +195,10 @@ void end_measure(t_rhythms_memory *x) // for the wanted rhythm if (x->next_main_rhythm_out) { + wanted_rhythm = 0; // ask the memory for the wanted rhythm rhythm_found = rhythm_memory_get_rhythm(x->rhythms_memory, // the memory - wanted_rhythm, // a pointer to the returned rhythm + &wanted_rhythm, // a pointer to the returned rhythm // the id of the main rhythm wanted x->next_main_rhythm_out, // the sub-id of the sub-rhythm wanted @@ -197,15 +209,55 @@ void end_measure(t_rhythms_memory *x) return 0; } + if (wanted_rhythm==0) + { + error("rhythms_memory: wanted_rhythm should not be null! "); + return 0; + } + // now I setup the events_out list // for each event in wanted_rhythm // allocate and link an element of elements_out + curr_rhythm = wanted_rhythm; + lastOutEvent = 0; + while (curr_rhythm) + { + event *newEvent; + newEvent = malloc(sizeof(event)); + newEvent->next = 0; + newEvent->voice = curr_rhythm->voice; + newEvent->when = (double) (duration2float(curr_rhythm->start) * x->measure_length); + post("DEBUG: add event in moment: %f", newEvent->when); + if (x->events_out) + { + // this is not the first event + // assign the next + lastOutEvent->next = newEvent; + } else + { + // this is the first event + x->events_out = newEvent; + } + // change the last pointer + lastOutEvent = newEvent; + curr_rhythm = curr_rhythm->next; + } - //--> TODO <-- - // also setup the timer for the first event - - //--> TODO <-- + if (x->events_out) + { + // setup the clock + clock_delay(x->x_clock, x->events_out->when); + // remember when next event will occour + x->last_event_out_time = x->events_out->when; + // remember the curr event + lastOutEvent = x->events_out; + //reassign next event + x->events_out = x->events_out->next; + // free old event + free(lastOutEvent); + } + x->next_main_rhythm_out = 0; } @@ -217,42 +269,60 @@ void end_measure(t_rhythms_memory *x) // this function is called by pd // when the timer bangs -static void delay_tick(t_rhythms_memory *x) +static void rhythms_tick(t_rhythms_memory *x) { + event *lastOutEvent; // here i must: // take the next element in x->events_out // and compute when I'll need to schedule next event // (next_event - curr_event) - - // TODO - // set the next element as the current one // and free the memory allocated for the old curr event - - // TODO - - // set up the timer - - // TODO + // set up the timer + post("DEBUG: eveng bang"); + // first of all trigger the bang! + outlet_bang(x->bangs_out); + //then do the stuff + if (x->events_out) + { + // setup the clock + clock_delay(x->x_clock, x->events_out->when - x->last_event_out_time); + // remember when next event will occour + x->last_event_out_time = x->events_out->when ; + // remember the curr event + lastOutEvent = x->events_out; + //reassign next event + x->events_out = x->events_out->next; + // free old event + free(lastOutEvent); + } } // the user wants me to play a rhythm in the next measure // the user MUST pass 2 args: main_rhythm and sub_rhythm wanted static void ask_rhythm(t_rhythms_memory *x, t_symbol *s, int argc, t_atom *argv) { - if (argc<3) + if (argc<2) { error("this method needs at least 2 floats: main_rhythm and sub_rhythm wanted"); return; } - argv++; + //argv++; x->next_main_rhythm_out = atom_getfloat(argv++); x->next_sub_rhythm_out = atom_getfloat(argv); + post("DEBUG: asked rhythm %i %i", x->next_main_rhythm_out, x->next_sub_rhythm_out); // i have nothing left to do: // when this measure will end a list of events_out will be set // from the current values of x->next_main_rhythm_out and x->next_sub_rhythm_out } +// add this rhythm to the memory +static void add_rhythm(t_rhythms_memory *x, t_symbol *s, int argc, t_atom *argv) +{ + // TODO + post("TODO"); +} + static void rhythms_memory_bang(t_rhythms_memory *x) { // generate a random value @@ -289,9 +359,18 @@ void *rhythms_memory_new(t_symbol *s, int argc, t_atom *argv) int i; time_t a; t_rhythms_memory *x = (t_rhythms_memory *)pd_new(rhythms_memory_class); + // first is for bangs (to let this external play in realtime //x->l_out = outlet_new(&x->x_obj, &s_list); - x->l_out = outlet_new(&x->x_obj, "symbol"); - + x->bangs_out = outlet_new(&x->x_obj, gensym("bang")); + // this outputs lists of events + x->list_out = outlet_new(&x->x_obj, "symbol"); + // this outputs info on the last detected rhythm + x->info_out = outlet_new(&x->x_obj, "symbol"); + + // inlet for rhythms in the form of lists + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("rhythm_in")); + + x->x_clock = clock_new(x, (t_method)rhythms_tick); x->seq_initialized = 0; rhythm_memory_create(&(x->rhythms_memory)); @@ -317,7 +396,10 @@ void rhythms_memory_setup(void) class_doaddfloat(rhythms_memory_class, (t_method)add_event); class_addmethod(rhythms_memory_class, (t_method)crash, gensym("crash"), 0); // the user asks for a rhythm - class_addmethod(rhythms_memory_class, (t_method)ask_rhythm, gensym("rhythm"), + class_addmethod(rhythms_memory_class, (t_method)ask_rhythm, gensym("rhythm_out"), + A_GIMME, 0); + // adds a rhythm passing it as a list of floats + class_addmethod(rhythms_memory_class, (t_method)add_rhythm, gensym("rhythm_in"), A_GIMME, 0); } diff --git a/test-rhythms_memory.pd b/test-rhythms_memory.pd index 4223f0f..67f9221 100755 --- a/test-rhythms_memory.pd +++ b/test-rhythms_memory.pd @@ -1,28 +1,28 @@ -#N canvas 224 39 661 478 12; -#X obj 134 262 rhythms_memory; +#N canvas 91 38 909 527 12; +#X obj 126 256 rhythms_memory; #X msg 126 212 measure; -#X msg 317 224 0; -#X obj 168 46 metro 500; -#X obj 130 84 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X msg 232 220 0; +#X obj 123 48 metro 500; +#X obj 85 86 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 168 23 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +#X obj 123 25 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; -#X obj 169 69 int 0; -#X obj 220 70 + 1; -#X obj 169 92 % 4; +#X obj 124 71 int 0; +#X obj 175 72 + 1; +#X obj 124 94 % 4; #X obj 127 155 sel 0; #X obj 125 185 bang; -#X obj 317 189 bng 30 250 50 0 empty empty empty 0 -6 0 8 -258699 -1 +#X obj 232 185 bng 30 250 50 0 empty empty empty 0 -6 0 8 -258699 -1 -1; -#X obj 133 285 unpack f f f f f; -#X floatatom 131 312 5 0 0 1 is_this_a_new_rhythm - -; -#X floatatom 160 330 5 0 0 1 id - -; -#X floatatom 193 348 5 0 0 1 subid - -; -#X floatatom 225 368 5 0 0 1 root_closeness - -; -#X floatatom 257 391 5 0 0 1 sub_closeness - -; -#X text 344 314 (0=known \, 1=new root \, 2=new sub); -#X obj 169 115 t f f; -#X msg 444 194 crash; +#X obj 231 363 unpack f f f f f; +#X floatatom 229 390 5 0 0 1 is_this_a_new_rhythm - -; +#X floatatom 258 408 5 0 0 1 id - -; +#X floatatom 291 426 5 0 0 1 subid - -; +#X floatatom 323 446 5 0 0 1 root_closeness - -; +#X floatatom 355 469 5 0 0 1 sub_closeness - -; +#X text 442 392 (0=known \, 1=new root \, 2=new sub); +#X obj 124 117 t f f; +#X msg 568 247 crash; #N canvas 0 0 454 304 drum 0; #X obj 108 27 inlet; #X obj 108 212 outlet~; @@ -42,12 +42,28 @@ #X connect 7 0 4 0; #X connect 8 0 6 0; #X connect 8 1 5 0; -#X restore 429 115 pd drum; -#X obj 429 82 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +#X restore 276 155 pd drum; +#X obj 274 124 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; -#X obj 423 147 dac~; -#X floatatom 192 152 5 0 0 0 - - -; -#X connect 0 0 12 0; +#X obj 270 187 dac~; +#X floatatom 180 155 5 0 0 0 - - -; +#X msg 384 39 rhythm 1 1; +#X obj 126 294 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 489 133 1 0 0.5; +#X text 381 17 you can ask it to play a stored rhythm; +#X text 559 227 (crash me! for debugging); +#X text 405 98 you will be able to send rhythms in the form of list +of floats (TODO); +#X obj 180 319 print; +#X text 152 294 here you get the wanted rhythms played in realtime +; +#X text 235 315 here you'll get the wanted rhythms in the form of lists +of floats (TODO); +#X text 373 361 here you get info on the last detected rhythm; +#X connect 0 0 26 0; +#X connect 0 1 31 0; +#X connect 0 2 12 0; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 4 0; @@ -73,3 +89,5 @@ #X connect 21 0 23 1; #X connect 22 0 21 0; #X connect 22 0 11 0; +#X connect 25 0 0 0; +#X connect 27 0 0 1; -- cgit v1.2.1