From e39b05789f12947502eba1114c9682cb0305bdd2 Mon Sep 17 00:00:00 2001 From: Davide Morelli Date: Sat, 21 Jan 2006 11:22:52 +0000 Subject: number of voices is now settable svn path=/trunk/externals/frankenstein/; revision=4459 --- voicing_analyzer.c | 117 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 87 insertions(+), 30 deletions(-) (limited to 'voicing_analyzer.c') diff --git a/voicing_analyzer.c b/voicing_analyzer.c index 703b74f..abd7675 100755 --- a/voicing_analyzer.c +++ b/voicing_analyzer.c @@ -34,20 +34,35 @@ static t_class *voicing_analyzer_class; typedef struct _voicing_analyzer { t_object x_obj; // myself - int current_voices[VOICES]; - int previous_voices[VOICES]; + //int current_voices[VOICES]; + //int previous_voices[VOICES]; + int *current_voices; + int *previous_voices; t_outlet *small_intervals_out, *i_like_parallelism_out, *center_note_out, *wideness_out; - + int voices; } t_voicing_analyzer; void voicing_analyzer_free(t_voicing_analyzer *x) { + free(x->current_voices); + free(x->previous_voices); // freebytes(x->buf_strum1, sizeof(x->buf_strum1)); // freebytes(x->buf_strum2, sizeof(x->buf_strum2)); } +void voicing_analyzer_allocate(t_voicing_analyzer *x) +{ + int i; + x->current_voices = malloc(sizeof(int)*x->voices); + x->previous_voices = malloc(sizeof(int)*x->voices); + for (i=0; ivoices; i++) + { + x->current_voices[i] = 60; + x->previous_voices[i] = 60; + } +} // here i evaluate this voicing void analyze_it(t_voicing_analyzer *x, float *wideness, float *i_like_parallelism, int *center_note, float *small_intervals) @@ -56,18 +71,32 @@ void analyze_it(t_voicing_analyzer *x, float *wideness, float *i_like_parallelis int min,max, distance; short int chord_notes[4]; short int chord_notes_ok[4]; - short int transitions[VOICES]; - short int directions[VOICES]; + //short int transitions[VOICES]; + short int *transitions; + //short int directions[VOICES]; + short int *directions; // intervals between voices // for parallel and hidden 5ths // voices spacing etc.. - short int intervals[VOICES][VOICES]; - short int notes[VOICES]; + //short int intervals[VOICES][VOICES]; + short int **intervals; + //short int notes[VOICES]; + short int *notes; res = 0; // starting fitness tmp = 0; + // allocate arrays + transitions = malloc(sizeof(short int)*x->voices); + directions = malloc(sizeof(short int)*x->voices); + notes = malloc(sizeof(short int)*x->voices); + intervals = malloc(sizeof(short int *) * x->voices); + for (i=0; ivoices; i++) + { + intervals[i] = malloc(sizeof(short int) * x->voices); + } + // shared objects - for (i=0; ivoices; i++) { notes[i]=x->current_voices[i]; transitions[i] = x->current_voices[i] - x->previous_voices[i]; @@ -79,16 +108,16 @@ void analyze_it(t_voicing_analyzer *x, float *wideness, float *i_like_parallelis post("directions[%i]=%i", i, directions[i]); } - for (i=0; ivoices; i++) { - for (j=i+1; jvoices; j++) { intervals[i][j] = (x->current_voices[i] - x->current_voices[j])%12 ; if (DEBUG_VERBOSE) post("intervals[%i][%i]=%i", i, j, intervals[i][j]); } } - SGLIB_ARRAY_SINGLE_QUICK_SORT(short int, notes, VOICES, SGLIB_NUMERIC_COMPARATOR) + SGLIB_ARRAY_SINGLE_QUICK_SORT(short int, notes, x->voices, SGLIB_NUMERIC_COMPARATOR) sameDirection = 0; parallel8_5 = 0; @@ -106,9 +135,9 @@ void analyze_it(t_voicing_analyzer *x, float *wideness, float *i_like_parallelis // parallel 5ths or octaves? (if yes return 0) // how? // hidden 8ths nor 5ths ? - for (i=0; ivoices; i++) { - for (j=i+1; jvoices; j++) { if (intervals[i][j]==7 || intervals[i][j]==0) { @@ -128,24 +157,24 @@ void analyze_it(t_voicing_analyzer *x, float *wideness, float *i_like_parallelis *i_like_parallelism = (float) -1; *i_like_parallelism += sameDirection; if (parallel8_5) - *i_like_parallelism += (float) ( ((float)parallel8_5) / ((float)(VOICES*(VOICES-1))) ); + *i_like_parallelism += (float) ( ((float)parallel8_5) / ((float)(x->voices*(x->voices - 1))) ); // is voice spacing uniform ?(except for the bass) // TODO: use notes[] // are voices average centered? - for (i=0; ivoices; i++) { tmp+=notes[i]; if (DEBUG_VERBOSE) post("average note is %i at passage %i", tmp, i); } // this is the average note - *center_note = tmp/(VOICES); + *center_note = tmp/(x->voices); // are intervals small? tmp=0; - for (i=0; ivoices; i++) { // if (DEBUG_VERBOSE) // post("transitions[%i] = %i",i, transitions[i]); @@ -171,16 +200,24 @@ void analyze_it(t_voicing_analyzer *x, float *wideness, float *i_like_parallelis res -= 3; } - *small_intervals = (float) (((float) res) / ((float) (5 * VOICES))); + *small_intervals = (float) (((float) res) / ((float) (5 * x->voices))); // now wideness min = notes[0]; - max = notes[VOICES-1]; + max = notes[x->voices-1]; distance = max - min; *wideness = (float) (((float)distance) / ((float)12)); - + // free memory + free(transitions); + free(directions); + free(notes); + for (i=0; ivoices; i++) + { + free(intervals[i]); + } + free(intervals); } typedef struct fitness_list_element_t @@ -193,12 +230,12 @@ typedef struct fitness_list_element_t void analyze_voicing(t_voicing_analyzer *x) { - t_atom lista[VOICES]; + t_atom lista[4]; float small_intervals=0; float i_like_parallelism=0; float wideness=0; int center_note=0; - + analyze_it(x, &wideness, &i_like_parallelism, ¢er_note, &small_intervals); // order is important! @@ -214,13 +251,13 @@ void set_current_voices(t_voicing_analyzer *x, t_symbol *sl, int argc, t_atom *a { int i=0; - if (argcvoices) { error("insufficient notes sent!"); return; } // fill input array with actual data sent to inlet - for (i=0;ivoices;i++) { x->previous_voices[i] = x->current_voices[i]; x->current_voices[i] = atom_getint(argv++); @@ -231,13 +268,31 @@ void set_current_voices(t_voicing_analyzer *x, t_symbol *sl, int argc, t_atom *a } +void set_voices(t_voicing_analyzer *x, t_floatarg f) +{ + int newval = (int) f; + if (newval<1) + { + error("number of voices must be > 0 !"); + return; + } + x->voices = newval; + voicing_analyzer_free(x); + voicing_analyzer_allocate(x); +} void print_help(t_voicing_analyzer *x) { post(""); post("voicing_analyzer is an external that analyze voicing"); - post("takes as input %i midi notes", VOICES); + post("takes as input a list of midi notes"); + post("and send out 4 values (from left to right):"); + post("1)the center note of the chord (average value)"); + post("2)wideness of the chord (how many octaves)"); + post("3)small intervals were used? (-1=no, 1=yes)"); + post("4)parallelism was used? (parallel octaves and fifths) (-1=no, 1=yes)"); post("available commands:"); + post("voices: changes the number of expected notes"); post("this externalis part of the frank framework"); post("authors: davide morelli, david casals"); @@ -252,12 +307,12 @@ void *voicing_analyzer_new(t_symbol *s, int argc, t_atom *argv) x->wideness_out = outlet_new(&x->x_obj, gensym("float")); x->small_intervals_out = outlet_new(&x->x_obj, gensym("float")); x->i_like_parallelism_out = outlet_new(&x->x_obj, gensym("float")); - - for (i=0;ivoices = VOICES; + if (argc>0) { - x->previous_voices[i] = 0; - x->current_voices[i] = 0; + x->voices = atom_getintarg(0, argc, argv); } + voicing_analyzer_allocate(x); return (x); } @@ -268,6 +323,8 @@ void voicing_analyzer_setup(void) (t_method)voicing_analyzer_free, sizeof(t_voicing_analyzer), CLASS_DEFAULT, A_GIMME, 0); class_addmethod(voicing_analyzer_class, (t_method)print_help, gensym("help"),0, 0); class_addlist(voicing_analyzer_class, (t_method)set_current_voices); - + // set number of voices + class_addmethod(voicing_analyzer_class, (t_method)set_voices, gensym("voices"), A_DEFFLOAT, 0); + } -- cgit v1.2.1