From d1ceaf286dcdd8b1ab51838d66a9df2b8ca4dce1 Mon Sep 17 00:00:00 2001 From: Davide Morelli Date: Sun, 15 Jan 2006 22:54:41 +0000 Subject: adding voicing_analyzer and fixing typos svn path=/trunk/externals/frankenstein/; revision=4408 --- Makefile | 2 +- chords_memory.c | 165 +---------------------------- common.c | 150 +++++++++++++++++++++++++- common.h | 96 ++++++++++++++++- harmonizer.c | 8 +- themes_memory.c | 10 +- voicing_analyzer.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++ voicing_analyzer.vcproj | 133 +++++++++++++++++++++++ 8 files changed, 660 insertions(+), 176 deletions(-) create mode 100755 voicing_analyzer.c create mode 100755 voicing_analyzer.vcproj diff --git a/Makefile b/Makefile index 052a1dc..7bb548b 100755 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ PDPATH="H:\PureData\pd-0.38-3.msw\pd" current: pd_nt distclean -pd_nt: chord_melo.dll chords_memory.dll harmonizer.dll GArhythm.dll ritmo1.dll rhythms_memory.dll themes_memory.dll +pd_nt: chord_melo.dll chords_memory.dll harmonizer.dll voicing_analyzer.dll GArhythm.dll ritmo1.dll rhythms_memory.dll themes_memory.dll .SUFFIXES: .dll diff --git a/chords_memory.c b/chords_memory.c index 7a39cd3..1905eba 100755 --- a/chords_memory.c +++ b/chords_memory.c @@ -97,6 +97,7 @@ there are plenty of such algos, we must just copy them down. #include #include "m_pd.h" +#include "common.h" #define DEBUG 0 // messaggi di debug @@ -111,85 +112,6 @@ there are plenty of such algos, we must just copy them down. static t_class *chords_memory_class; -// how can a chord be? -#define TYPES_NUM 17 // keep me updated -typedef enum { - kMaj=0, - kMin=1, - kDim=2, - kAug=3, - kDom7=4, - kMaj7=5, - kMin7=6, - kMinMaj7=7, - kDim7=8, - kHalfDim7=9, - //pland adding 9ths 30.11.05 and beyond - kDomb9=10, - kMaj9=11, - kDom9=12, - kMin9=13, - kHalfDim9=14, - kMinMaj9=15, - kDimMaj9=16 - } chord_type_t; - -// how many tones do we have in our octave? -#define TONES_NUM 12 // keep me updated -typedef enum { - I=0, - Id=1, - II=2, - IId=3, - III=4, - IV=5, - IVd=6, - V=7, - Vd=8, - VI=9, - VId=10, - VII=11 - } chord_tone_t; - -// how many nodes does this graph have? -// for now TYPES_NUM*TONES_NUM -// when we introduce modulation -// we'll have more -#define NODES_NUM TYPES_NUM*TONES_NUM - -// this defines a chord in a tonality -typedef struct _chord -{ - chord_type_t mode; - chord_tone_t note; -} chord_t; - -// enumeration of absolute notes -// i'll need this when parsing strings like "C major" -typedef enum { - C=0, - Db=1, - D=2, - Eb=3, - E=4, - F=5, - Gb=6, - G=7, - Ab=8, - A=9, - Bb=10, - B=11 - } abs_note_t; - -// enumeration of modes -// i'll start with minor and major only -// but we could add phrigian, doric, misolidian ,e tc... -#define MODES_NUM 2 -typedef enum { - MAJOR=0, - MINOR=1 } modes_t; - -#define MODULATIONS_NUM MODES_NUM*TONES_NUM // data type for the steps of a walk typedef struct _step @@ -281,91 +203,6 @@ void chords_memory_init(t_chords_memory *x, t_floatarg f) // ------------- function for string manipulation (from string to chords) -// tries to find out absolute tones names in this string -abs_note_t from_string_to_abs_tone(const char *substr) -{ - if (strstr(substr, "C")) - return C; - if (strstr(substr, "Db")) - return Db; - if (strstr(substr, "D")) - return D; - if (strstr(substr, "Eb")) - return Eb; - if (strstr(substr, "E")) - return E; - if (strstr(substr, "F")) - return F; - if (strstr(substr, "Gb")) - return Gb; - if (strstr(substr, "G")) - return G; - if (strstr(substr, "Ab")) - return Ab; - if (strstr(substr, "A")) - return A; - if (strstr(substr, "Bb")) - return Bb; - if (strstr(substr, "B")) - return B; - return C; -} - -chord_type_t from_string_to_type(const char *substr) -{ - if (strstr(substr, "minor/major 7th")) - return kMinMaj7; - if (strstr(substr, "major 7th")) - return kMaj7; - if (strstr(substr, "major")) - return kMaj; - if (strstr(substr, "minor 7th")) - return kMin7; - if (strstr(substr, "minor")) - return kMin; - if (strstr(substr, "half diminished 7th")) - return kHalfDim7; - if (strstr(substr, "diminished 7th")) - return kDim7; - if (strstr(substr, "diminished")) - return kDim; - if (strstr(substr, "augmented")) - return kAug; - if (strstr(substr, "dominant 7th")) - return kDom7; - // pland adding chords 30.11.05 - if (strstr(substr, "dominant b9")) - return kDomb9; - if (strstr(substr, "major 9th")) - return kMaj9; - if (strstr(substr, "dominant 9th")) - return kDom9; - if (strstr(substr, "minor 9th")) - return kMin9; - if (strstr(substr, "half diminished 9th")) - return kHalfDim9; - if (strstr(substr, "minor major 9th")) - return kMinMaj9; - if (strstr(substr, "diminished major 9th")) - return kDimMaj9; - // TODO: other chords - // beware when adding new chords - // put shorter names at end of this function! - return C; -} - -// find the tonality mode in this string -modes_t from_string_to_mode(const char *substr) -{ - if (strstr(substr, "major")) - return MAJOR; - if (strstr(substr, "minor")) - return MINOR; - - // TODO: other modes (doric, misolidian , custom, etc.. - return C; -} - // builds a string for this chord // the string is in maxlib's chord format void chords_memory_chord2string(t_chords_memory *x, char *string, chord_t chord) diff --git a/common.c b/common.c index c136fcf..fdb5a78 100755 --- a/common.c +++ b/common.c @@ -11,6 +11,7 @@ David Plans Casal http://www.studios.uea.ac.uk/people/staff/casal #include #include +#include #include "m_pd.h" // to post errors and debug messages @@ -802,4 +803,151 @@ void freeNotes(t_note_event *currentEvent) free(currentEvent); } while(next); -} \ No newline at end of file +} + + +// ------------- function for string manipulation (from string to chords) + +// tries to find out absolute tones names in this string +abs_note_t from_string_to_abs_tone(const char *substr) +{ + if (strstr(substr, "C")) + return C; + if (strstr(substr, "Db")) + return Db; + if (strstr(substr, "D")) + return D; + if (strstr(substr, "Eb")) + return Eb; + if (strstr(substr, "E")) + return E; + if (strstr(substr, "F")) + return F; + if (strstr(substr, "Gb")) + return Gb; + if (strstr(substr, "G")) + return G; + if (strstr(substr, "Ab")) + return Ab; + if (strstr(substr, "A")) + return A; + if (strstr(substr, "Bb")) + return Bb; + if (strstr(substr, "B")) + return B; + return C; +} + +chord_type_t from_string_to_type(const char *substr) +{ + if (strstr(substr, "minor/major 7th")) + return kMinMaj7; + if (strstr(substr, "major 7th")) + return kMaj7; + if (strstr(substr, "major")) + return kMaj; + if (strstr(substr, "minor 7th")) + return kMin7; + if (strstr(substr, "minor")) + return kMin; + if (strstr(substr, "half diminished 7th")) + return kHalfDim7; + if (strstr(substr, "diminished 7th")) + return kDim7; + if (strstr(substr, "diminished")) + return kDim; + if (strstr(substr, "augmented")) + return kAug; + if (strstr(substr, "dominant 7th")) + return kDom7; + // pland adding chords 30.11.05 + if (strstr(substr, "dominant b9")) + return kDomb9; + if (strstr(substr, "major 9th")) + return kMaj9; + if (strstr(substr, "dominant 9th")) + return kDom9; + if (strstr(substr, "minor 9th")) + return kMin9; + if (strstr(substr, "half diminished 9th")) + return kHalfDim9; + if (strstr(substr, "minor major 9th")) + return kMinMaj9; + if (strstr(substr, "diminished major 9th")) + return kDimMaj9; + // TODO: other chords + // beware when adding new chords + // put shorter names at end of this function! + return C; +} + +// find the tonality mode in this string +modes_t from_string_to_mode(const char *substr) +{ + if (strstr(substr, "major")) + return MAJOR; + if (strstr(substr, "minor")) + return MINOR; + + // TODO: other modes (doric, misolidian , custom, etc.. + return C; +} + +// tries to find out absolute tones names in this string +abs_note_t string2note(const char *substr) +{ + if (strstr(substr, "C")) + return C; + if (strstr(substr, "Db")) + return Db; + if (strstr(substr, "D")) + return D; + if (strstr(substr, "Eb")) + return Eb; + if (strstr(substr, "E")) + return E; + if (strstr(substr, "F")) + return F; + if (strstr(substr, "Gb")) + return Gb; + if (strstr(substr, "G")) + return G; + if (strstr(substr, "Ab")) + return Ab; + if (strstr(substr, "A")) + return A; + if (strstr(substr, "Bb")) + return Bb; + if (strstr(substr, "B")) + return B; + return C; +} + +chord_type_t string2mode(const char *substr) +{ + if (strstr(substr, "minor/major 7th")) + return kMinMaj7; + if (strstr(substr, "major 7th")) + return kMaj7; + if (strstr(substr, "major")) + return kMaj; + if (strstr(substr, "minor 7th")) + return kMin7; + if (strstr(substr, "minor")) + return kMin; + if (strstr(substr, "half diminished 7th")) + return kHalfDim7; + if (strstr(substr, "diminished 7th")) + return kDim7; + if (strstr(substr, "diminished")) + return kDim; + if (strstr(substr, "augmented")) + return kAug; + if (strstr(substr, "dominant 7th")) + return kDom7; + // TODO: other chords + // beware when adding new chords + // put shorter names at end of this function! + return C; +} + diff --git a/common.h b/common.h index ac74379..f30bda4 100755 --- a/common.h +++ b/common.h @@ -129,6 +129,89 @@ struct t_rhythm_memory_representation // define a return value to express "rhythm not found in this representation" #define INVALID_RHYTHM 65535 +// chords data structure +// tells you how many durations there // how can a chord be? +#define TYPES_NUM 17 // keep me updated +typedef enum { + kMaj=0, + kMin=1, + kDim=2, + kAug=3, + kDom7=4, + kMaj7=5, + kMin7=6, + kMinMaj7=7, + kDim7=8, + kHalfDim7=9, + //pland adding 9ths 30.11.05 and beyond + kDomb9=10, + kMaj9=11, + kDom9=12, + kMin9=13, + kHalfDim9=14, + kMinMaj9=15, + kDimMaj9=16 + } chord_type_t; + +// how many tones do we have in our octave? +#define TONES_NUM 12 // keep me updated +typedef enum { + I=0, + Id=1, + II=2, + IId=3, + III=4, + IV=5, + IVd=6, + V=7, + Vd=8, + VI=9, + VId=10, + VII=11 + } chord_tone_t; + +// how many nodes does this graph have? +// for now TYPES_NUM*TONES_NUM +// when we introduce modulation +// we'll have more +#define NODES_NUM TYPES_NUM*TONES_NUM + +// this defines a chord in a tonality +typedef struct _chord +{ + chord_type_t mode; + chord_tone_t note; +} chord_t; + +// enumeration of absolute notes +// i'll need this when parsing strings like "C major" +typedef enum { + C=0, + Db=1, + D=2, + Eb=3, + E=4, + F=5, + Gb=6, + G=7, + Ab=8, + A=9, + Bb=10, + B=11 + } abs_note_t; + +// enumeration of modes +// i'll start with minor and major only +// but we could add phrigian, doric, misolidian ,e tc... +#define MODES_NUM 2 +typedef enum { + MAJOR=0, + MINOR=1 } modes_t; + +#define MODULATIONS_NUM MODES_NUM*TONES_NUM + + + // ------------------------------------------------ functions // ----------- rhythm manipolation functions @@ -139,7 +222,7 @@ t_duration int2duration(int n); // converts from duration to integer: used to know this duration // what corresponds in terms table index unsigned short int duration2int(t_duration dur); -// tells you how many durations there are + int possible_durations(); // converts from float (0-1) to duration. it performs quantization @@ -287,3 +370,14 @@ void concatenateNote(t_note_event *currentEvent, unsigned short int voice, float // used to free the memory allocated by this list void freeNotes(t_note_event *currentEvent); + + + +// ------------- function for string manipulation (from string to chords) + +// tries to find out absolute tones names in this string +abs_note_t from_string_to_abs_tone(const char *substr); +chord_type_t from_string_to_type(const char *substr); +modes_t from_string_to_mode(const char *substr); +chord_type_t string2mode(const char *substr); +abs_note_t string2note(const char *substr); diff --git a/harmonizer.c b/harmonizer.c index 18024f1..9a99559 100755 --- a/harmonizer.c +++ b/harmonizer.c @@ -62,11 +62,11 @@ static t_class *harmonizer_class; // this defines a chord in a tonality -typedef struct _chord +typedef struct _chord_abs { chord_type_t mode; abs_note_t note; -} chord_t; +} chord_abs_t; typedef struct _harmonizer @@ -75,8 +75,8 @@ typedef struct _harmonizer // genotypes int population[MAX_POPULATION][VOICES]; int current_voices[VOICES]; - chord_t current_chord; - chord_t target_chord; + chord_abs_t current_chord; + chord_abs_t target_chord; int target_notes[POSSIBLE_NOTES]; t_outlet *l_out; diff --git a/themes_memory.c b/themes_memory.c index d4d716a..cefdb5e 100755 --- a/themes_memory.c +++ b/themes_memory.c @@ -210,13 +210,13 @@ void end_measure(t_themes_memory *x) if (rhythm_found==0) { post("themes_memory: rhythm %i %i was not found ", x->next_main_rhythm_out, x->next_sub_rhythm_out); - return 0; + return; } if (wanted_rhythm==0) { error("themes_memory: wanted_rhythm should not be null! "); - return 0; + return; } // now I setup the events_out list @@ -385,9 +385,9 @@ void *themes_memory_new(t_symbol *s, int argc, t_atom *argv) //x->l_out = outlet_new(&x->x_obj, &s_list); x->bangs_out = outlet_new(&x->x_obj, gensym("bang")); // this outputs lists of events - x->list_out = outlet_new(&x->x_obj, "symbol"); + x->list_out = outlet_new(&x->x_obj, gensym("symbol")); // this outputs info on the last detected rhythm - x->info_out = outlet_new(&x->x_obj, "symbol"); + x->info_out = outlet_new(&x->x_obj, gensym("symbol")); // inlet for rhythms in the form of lists inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("rhythm_in")); @@ -406,7 +406,7 @@ void crash(t_themes_memory *x) { int *a; a = malloc(sizeof(int)); - a[9999999999999999999] = 1; + a[99999] = 1; } void themes_memory_setup(void) diff --git a/voicing_analyzer.c b/voicing_analyzer.c new file mode 100755 index 0000000..c1ab8e3 --- /dev/null +++ b/voicing_analyzer.c @@ -0,0 +1,272 @@ +/* +voicing_analyzer: + + +*/ +#include +#include +#include +// for string manipulation +#include +#include +#include "m_pd.h" + +// to sort arrays +#include "sglib.h" + + +#define VOICES 5 + +#define NOTES_RANGE 80 // this should be multiple of 16 +#define LOWER_POSSIBLE_NOTE 24 // lower note possible, it should be a C +#define POSSIBLE_NOTES (NOTES_RANGE/12*4) // 4 is the max number of notes in a chord + +// default values +#define DEF_WIDENESS 3 // 3 octaves +#define DEF_CENTER_NOTE 72 // central C + +#define DEBUG 0 // messaggi di debug +#define DEBUG_VERBOSE 0 // messaggi di debug + +static t_class *voicing_analyzer_class; + + +typedef struct _voicing_analyzer +{ + t_object x_obj; // myself + int current_voices[VOICES]; + int previous_voices[VOICES]; + t_outlet *small_intervals_out, *i_like_parallelism_out, + *center_note_out, *wideness_out; + +} t_voicing_analyzer; + + +void voicing_analyzer_free(t_voicing_analyzer *x) +{ +// freebytes(x->buf_strum1, sizeof(x->buf_strum1)); +// freebytes(x->buf_strum2, sizeof(x->buf_strum2)); +} + + +// here i evaluate this voicing +void analyze_it(t_voicing_analyzer *x, float *wideness, float *i_like_parallelism, int *center_note, float *small_intervals) +{ + int i, j, tmp, res, last, avgHI, avgLOW, sameDirection, parallel8_5; + int min,max, distance; + short int chord_notes[4]; + short int chord_notes_ok[4]; + short int transitions[VOICES]; + short int directions[VOICES]; + // intervals between voices + // for parallel and hidden 5ths + // voices spacing etc.. + short int intervals[VOICES][VOICES]; + short int notes[VOICES]; + res = 0; // starting fitness + tmp = 0; + + // shared objects + for (i=0; icurrent_voices[i]; + transitions[i] = x->current_voices[i] - x->previous_voices[i]; + if (transitions[i]!=0) + directions[i] = transitions[i]/abs(transitions[i]); + else + directions[i] = 0; + if (DEBUG_VERBOSE) + post("directions[%i]=%i", i, directions[i]); + + } + for (i=0; icurrent_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) + + sameDirection = 0; + parallel8_5 = 0; + + // all same direction? + if ( directions[0]==directions[1] && + directions[1]==directions[2] && + directions[2]==directions[3]) + { + sameDirection=1; + if (DEBUG_VERBOSE) + post("same direction!"); + } + + // parallel 5ths or octaves? (if yes return 0) + // how? + // hidden 8ths nor 5ths ? + for (i=0; i