From 878ee3f2844f1c2cdbf14e3f9b9acbd43bdd9edf Mon Sep 17 00:00:00 2001 From: Ed Kelly Date: Sat, 15 Sep 2012 13:29:19 +0000 Subject: gemnotes 0.2.3 svn path=/trunk/externals/ekext/; revision=16237 --- gemnotes_0.2.3/src/gemnotes_countbars.c | 255 ++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100755 gemnotes_0.2.3/src/gemnotes_countbars.c (limited to 'gemnotes_0.2.3/src/gemnotes_countbars.c') diff --git a/gemnotes_0.2.3/src/gemnotes_countbars.c b/gemnotes_0.2.3/src/gemnotes_countbars.c new file mode 100755 index 0000000..4650d22 --- /dev/null +++ b/gemnotes_0.2.3/src/gemnotes_countbars.c @@ -0,0 +1,255 @@ +#include "m_pd.h" +#include + +static t_class *gemnotes_countbars_class; + +/* list inlet: [rhythm dur vel start] + * when the BPM changes, the offset accumulates the start time of the first + * note, and is subtracted from subsequent inter-onset times + */ + +/* The Gemnotes system can only handle one voice at the moment. */ + +/* this object is probably where key signatures (flatsharp flag) and dynamics + * will be calculated eventually, since it has access to the pitch and + * velocity information + */ + +typedef struct _gemnotes_countbars { + t_object x_obj; + t_atom outlist[5]; + t_float bpm, qtime, divtime, numer, denom; + // int setoffset, iotdiv; + t_float allcount, barcount, barlen, bardiv, iot, offset, rhythm, dur, notedur, nbars; + t_float start, pitch, vel; + t_float prevstart, previot, prevdurt, prevdur, tdiff, polydiff; + t_float outstart; + int ndurs, polycompare, debug; + t_outlet *note, *bars; +} t_gemnotes_countbars; + +/* There are real problems with this algorithm. Firstly it assumes that all notes + * are not polyrhythmic against the basic pulse, so manual editing of the score + * will be necessary if there are polyrhythmic note divisions. Secondly, there can + * only be one voice with chords. + * Perhaps this should all be folded into polyquant, with polyquant + * measuring all 136 MIDI timings internally... + * ...for live input transcription, there would need to be quantization + * of the inter-onset time. + * I need to learn about clocks in PD! + */ + +void gemnotes_countbars_note (t_gemnotes_countbars *z, t_symbol *s, int argc, t_atom *argv) +{ + float newcount = 0; + if(argc == 5) + { + z->prevstart = z->start; + z->prevdur = z->dur; + + z->pitch = atom_getfloat(argv); + z->rhythm = atom_getfloat(argv+1); + z->dur = atom_getfloat(argv+2); + z->vel = atom_getfloat(argv+3); + z->start = atom_getfloat(argv+4); + + z->prevdurt = z->notedur; + z->notedur = z->divtime * z->dur; + + + z->previot = z->iot; + z->iot = z->start - z->prevstart; + + z->tdiff = z->iot - z->prevdurt; + z->outstart = 0; + /* Deal with polyrhythmic notes - a kludge until polyquant is integrated with this object */ + z->polydiff = z->iot / z->divtime; + z->polycompare = (int)z->polydiff; + if(z->tdiff < 2 && z->tdiff > -2 && z->allcount > 0) + { + newcount = z->barcount + z->prevdur; + if(newcount >= z->barlen) + { + z->nbars++; + outlet_float(z->bars, z->nbars); + } + z->barcount = (float)((int)newcount % (int)z->barlen); + z->allcount++; + if(z->debug == 1) post("barcount = %d, barlen = %d, + sign",(int)z->barcount, (int)z->barlen); + z->outstart = -1; + } + else if((float)z->polycompare - z->polydiff < -2) + { + newcount = z->barcount + z->polydiff; + if(newcount >= z->barlen) + { + z->nbars++; + outlet_float(z->bars, z->nbars); + newcount -= z->barlen; + z->barcount = newcount; + } + else if(newcount < z->barlen) + { + z->barcount = newcount; + } + z->outstart = z->barcount; + if(z->debug == 1) post("barcount = %d, barlen = %d, poly",(int)z->barcount, (int)z->barlen); + } + else if(z->iot < 2 && z->allcount > 0) + { + z->outstart = -2; + post("chord"); + } + else if(z->allcount == 0) + { + z->outstart = 0; + z->allcount++; + z->nbars = 1; + outlet_float(z->bars, z->nbars); + post("start"); + } + else if(z->tdiff > 1) + { + //assumes that the inter-onset time is always either 1 duration or more + //this bit will need to be changed for multi-voice scenarios to be supported + //but since it is proportional notation, maybe we can minimize rests + z->ndurs = 1; + while(z->tdiff > 1) + { + z->ndurs++; + z->tdiff -= z->divtime; + } + z->allcount += (float)z->ndurs; + newcount = (float)z->ndurs; + while(newcount >= z->barlen) + { + newcount -= z->barlen; + z->nbars++; + outlet_float(z->bars, z->nbars); + } + newcount += z->barcount; + if(newcount >= z->barlen) + { + z->nbars++; + outlet_float(z->bars, z->nbars); + } + z->barcount = (float)((int)(z->barcount + (float)z->ndurs) % (int)z->barlen); + z->outstart = z->barcount; + if(z->debug == 1) post("barcount = %d, barlen = %d - floatstart",(int)z->barcount, (int)z->barlen); + } + else + { + post("iot:%f,tdiff:%f,prevdur:%f,previot:%f,nomethod",z->iot, z->tdiff, z->prevdurt, z->previot); + } + SETFLOAT(&z->outlist[0], z->outstart); + SETFLOAT(&z->outlist[1], z->pitch); + SETFLOAT(&z->outlist[2], z->dur); + SETFLOAT(&z->outlist[4], z->vel); + outlet_list(z->note, gensym("list"), 5, z->outlist); + } +} + +void gemnotes_countbars_bpm (t_gemnotes_countbars *z, t_floatarg f) +{ + if(f != z->bpm && f > 0) + { + post("Tempo = %f Beats Per-Minute",f); + z->bpm = f; + // z->setoffset = 1; + z->qtime = 60000/f; + z->divtime = z->qtime / (z->bardiv / 4); + z->notedur = z->divtime * z->dur; + } +} + +void gemnotes_countbars_bar (t_gemnotes_countbars *z, t_symbol *s, int argc, t_atom *argv) +{ + if(argc > 2) + { + z->numer = atom_getfloat(argv); + z->denom = atom_getfloat(argv+1); + z->bardiv = atom_getfloat(argv+2); + z->barlen = z->numer / z->denom * z->bardiv; + z->divtime = z->qtime / (z->bardiv / 4); + z->prevdurt = z->divtime; + z->barcount = 0; + post("Bar of %d/%d, divisions: %d", (int)z->numer, (int)z->denom, (int)z->bardiv); + } + else if(argc > 1) + { + z->numer = atom_getfloat(argv); + z->denom = atom_getfloat(argv+1); + z->barlen = z->numer / z->denom * z->bardiv; + z->divtime = z->qtime / (z->bardiv / 4); + z->prevdurt = z->divtime; + z->barcount = 0; + post("Bar of %d/%d, divisions: %d", (int)z->numer, (int)z->denom, (int)z->bardiv); + } + else if(argc > 0) + { + z->numer = atom_getfloat(argv); + z->barlen = z->numer / z->denom * z->bardiv; + z->divtime = z->qtime / (z->bardiv / 4); + z->prevdurt = z->divtime; + z->barcount = 0; + post("Bar of %d/%d, divisions: %d", (int)z->numer, (int)z->denom, (int)z->bardiv); + } +} + +void gemnotes_countbars_debug(t_gemnotes_countbars *z, t_floatarg f) +{ + z->debug = f != 0 ? (int)f : 0; +} + +void gemnotes_countbars_reset(t_gemnotes_countbars *z) +{ + z->allcount = z->barcount = 0; + z->nbars = 1; +} + +void *gemnotes_countbars_new(t_symbol *s, int argc, t_atom *argv) +{ + t_gemnotes_countbars *z = (t_gemnotes_countbars *)pd_new(gemnotes_countbars_class); + int i; + for(i=0;i<5;i++) SETFLOAT(&z->outlist[i], 0); + + z->bpm = 120; + z->numer = 4; + z->denom = 4; + z->bardiv = 16; + // args: bpm, numer, denom, div + if(argc > 0) z->bpm = atom_getfloat(argv); + if(argc > 1) z->numer = atom_getfloat(argv+1); + if(argc > 2) z->denom = atom_getfloat(argv+2); + if(argc > 3) z->bardiv = atom_getfloat(argv+3); + + z->qtime = 60000/z->bpm; + z->divtime = z->qtime / (z->bardiv / z->denom); + z->prevdurt = z->divtime; + + z->barlen = z->numer / z->denom * z->bardiv; + z->barcount = z->allcount = 0; + z->previot = 0; + z->prevstart = -125; + z->nbars = 1; + z->note = outlet_new(&z->x_obj, gensym("list")); + z->bars = outlet_new(&z->x_obj, gensym("float")); + + return(void *)z; +} + +void gemnotes_countbars_setup(void) +{ + gemnotes_countbars_class = class_new(gensym("gemnotes_countbars"), + (t_newmethod)gemnotes_countbars_new, + 0, sizeof(t_gemnotes_countbars), + 0, A_GIMME, 0); + post("gemnotes_countbars - yu need this for realtime notation..."); + post("version 0.4...by Ed Kelly 2010 - morph_2016@yahoo.co.uk"); + + class_addmethod(gemnotes_countbars_class, (t_method)gemnotes_countbars_note, gensym("note"), A_GIMME, 0); + class_addmethod(gemnotes_countbars_class, (t_method)gemnotes_countbars_bar, gensym("bar"), A_GIMME, 0); + class_addmethod(gemnotes_countbars_class, (t_method)gemnotes_countbars_bpm, gensym("bpm"), A_DEFFLOAT, 0); + class_addmethod(gemnotes_countbars_class, (t_method)gemnotes_countbars_reset, gensym("reset"), A_DEFFLOAT, 0); + class_addmethod(gemnotes_countbars_class, (t_method)gemnotes_countbars_debug, gensym("debug"), A_DEFFLOAT, 0); +} -- cgit v1.2.1