aboutsummaryrefslogtreecommitdiff
path: root/voicing_analyzer.c
diff options
context:
space:
mode:
authorDavide Morelli <morellid@users.sourceforge.net>2006-01-21 11:22:52 +0000
committerDavide Morelli <morellid@users.sourceforge.net>2006-01-21 11:22:52 +0000
commite39b05789f12947502eba1114c9682cb0305bdd2 (patch)
tree8273bfbcf91021b3b31d1f18330dadf82fff05ae /voicing_analyzer.c
parent8bda90bf0ab202a9916ecabbc9372000642c3be7 (diff)
number of voices is now settable
svn path=/trunk/externals/frankenstein/; revision=4459
Diffstat (limited to 'voicing_analyzer.c')
-rwxr-xr-xvoicing_analyzer.c117
1 files changed, 87 insertions, 30 deletions
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; i<x->voices; 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; i<x->voices; i++)
+ {
+ intervals[i] = malloc(sizeof(short int) * x->voices);
+ }
+
// shared objects
- for (i=0; i<VOICES; i++)
+ for (i=0; i<x->voices; 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; i<VOICES; i++)
+ for (i=0; i<x->voices; i++)
{
- for (j=i+1; j<VOICES; j++)
+ for (j=i+1; j<x->voices; 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; i<VOICES; i++)
+ for (i=0; i<x->voices; i++)
{
- for (j=i+1; j<VOICES; j++)
+ for (j=i+1; j<x->voices; 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; i<VOICES; i++)
+ for (i=0; i<x->voices; 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; i<VOICES; i++)
+ for (i=0; i<x->voices; 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; i<x->voices; 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, &center_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 (argc<VOICES)
+ if (argc<x->voices)
{
error("insufficient notes sent!");
return;
}
// fill input array with actual data sent to inlet
- for (i=0;i<VOICES;i++)
+ for (i=0;i<x->voices;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;i<VOICES;i++)
+ x->voices = 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);
+
}