From bfc81675d5856cedc4bf02d412c06b98c296654e Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 25 Sep 2013 17:23:17 -0700 Subject: [PATCH] Add recognition of 6, m6, and 7-flat-5 chords. One trick here is the ambiguity that, for example, C6 looks the same as Am7 in first inversion and Cm7 looks the same as D#6 in 3rd inversion. We rework the recognition code a bit so that chords with a smaller inversion number will be preferred over chords with a larger inversion number. That way, with the above examples, scherzo will report C6 and Cm7 rather than "Am7 1st inversion" and "D#6 3rd inversion". --- scherzo.c | 147 +++++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 74 deletions(-) diff --git a/scherzo.c b/scherzo.c index 0980089..d1a164c 100644 --- a/scherzo.c +++ b/scherzo.c @@ -489,55 +489,46 @@ _chord_signature_matches (analyzed_note_t *notes, int num_notes, modified_degree_t *degrees, int num_degrees, - int *inversion_ret, + int inversion, score_pitch_t *root) { #define MAX_DEGREES 4 int relative_pitches[MAX_DEGREES]; - int inversion, max_inversions; int i, root_index; assert (num_degrees <= MAX_DEGREES); if (num_notes != num_degrees) - return 0; + return 0; - max_inversions = num_degrees; + if (inversion >= num_degrees) + return 0; /* We never spell simple intervals as inversions. */ - if (num_degrees == 2) - max_inversions = 1; - - for (inversion = 0; inversion < max_inversions; inversion++) { - for (i = 0; i < num_degrees; i++) { - /* The num_degrees is in the addition just to ensure all - * inputs to the modulus operator remain positive. */ - int index = (i + num_degrees - inversion) % num_degrees; - - /* Again, adding a 12 to keep things positive. */ - relative_pitches[index] = - (12 + - _modified_degree_to_half_steps (°rees[i]) - - _modified_degree_to_half_steps (°rees[inversion])) % 12; + if (num_degrees == 2 && inversion > 0) + return 0; + + for (i = 0; i < num_degrees; i++) { + /* The num_degrees is in the addition just to ensure all + * inputs to the modulus operator remain positive. */ + int index = (i + num_degrees - inversion) % num_degrees; + + /* Again, adding a 12 to keep things positive. */ + relative_pitches[index] = + (12 + + _modified_degree_to_half_steps (°rees[i]) - + _modified_degree_to_half_steps (°rees[inversion])) % 12; - } - - for (i = 0; i < num_notes; i++) - if (notes[i].relative_pitch != relative_pitches[i]) - goto NEXT_INVERSION; - - root_index = (num_notes - inversion) % num_notes; - *root = notes[root_index].note->pitch; + } - *inversion_ret = inversion; + for (i = 0; i < num_notes; i++) + if (notes[i].relative_pitch != relative_pitches[i]) + return 0; - return 1; + root_index = (num_notes - inversion) % num_notes; + *root = notes[root_index].note->pitch; - NEXT_INVERSION: - ; - } - - return 0; + return 1; } static const char * @@ -676,11 +667,16 @@ scherzo_analyze_chord (scherzo_t *scherzo) { {{1, 0}, {3, -1}, {5, -1}}, "°" } }; - struct { modified_degree_t degrees[4]; const char *name; } sevenths[] = { + struct { modified_degree_t degrees[4]; const char *name; } tetrachords[] = { + /* Sixth chords */ + { {{1, 0}, {3, 0}, {5, 0}, {6, 0}}, "6" }, + { {{1, 0}, {3, -1}, {5, 0}, {6, 0}}, "m6" }, + /* Seventh chords */ { {{1, 0}, {3, 0}, {5, +1}, {7, 0}}, SUP "+M7" PUS }, { {{1, 0}, {3, 0}, {5, +1}, {7, -1}}, SUP "+7" PUS }, { {{1, 0}, {3, 0}, {5, 0}, {7, 0}}, "M7" }, { {{1, 0}, {3, 0}, {5, 0}, {7, -1}}, "7" }, + { {{1, 0}, {3, 0}, {5, -1}, {7, -1}}, SUP "7♭5" PUS }, { {{1, 0}, {3, -1}, {5, 0}, {7, 0}}, "m" SUP "M7" PUS }, { {{1, 0}, {3, -1}, {5, 0}, {7, -1}}, "m7" }, { {{1, 0}, {3, -1}, {5, -1}, {7, 0}}, "°" SUP "M7" PUS }, @@ -750,52 +746,55 @@ scherzo_analyze_chord (scherzo_t *scherzo) } } - switch (num_notes) { - case 1: - for (i = 0; i < ARRAY_SIZE (octaves); i++) { - if (_chord_signature_matches (notes, num_notes, - octaves[i].degrees, 1, - &inversion, &root)) - { - chord_name = octaves[i].name; - break; + for (inversion = 0; inversion < 4; inversion++) { + switch (num_notes) { + case 1: + for (i = 0; i < ARRAY_SIZE (octaves); i++) { + if (_chord_signature_matches (notes, num_notes, + octaves[i].degrees, 1, + inversion, &root)) + { + chord_name = octaves[i].name; + goto CHORD_NAME_KNOWN; + } } - } - break; - case 2: - for (i = 0; i < ARRAY_SIZE (intervals); i++) { - if (_chord_signature_matches (notes, num_notes, - intervals[i].degrees, 2, - &inversion, &root)) - { - chord_name = intervals[i].name; - break; + break; + case 2: + for (i = 0; i < ARRAY_SIZE (intervals); i++) { + if (_chord_signature_matches (notes, num_notes, + intervals[i].degrees, 2, + inversion, &root)) + { + chord_name = intervals[i].name; + goto CHORD_NAME_KNOWN; + } } - } - break; - case 3: - for (i = 0; i < ARRAY_SIZE (triads); i++) { - if (_chord_signature_matches (notes, num_notes, - triads[i].degrees, 3, - &inversion, &root)) - { - chord_name = triads[i].name; - break; + break; + case 3: + for (i = 0; i < ARRAY_SIZE (triads); i++) { + if (_chord_signature_matches (notes, num_notes, + triads[i].degrees, 3, + inversion, &root)) + { + chord_name = triads[i].name; + goto CHORD_NAME_KNOWN; + } } - } - break; - case 4: - for (i = 0; i < ARRAY_SIZE(sevenths); i++) { - if (_chord_signature_matches (notes, num_notes, - sevenths[i].degrees, 4, - &inversion, &root)) - { - chord_name = sevenths[i].name; - break; + break; + case 4: + for (i = 0; i < ARRAY_SIZE(tetrachords); i++) { + if (_chord_signature_matches (notes, num_notes, + tetrachords[i].degrees, 4, + inversion, &root)) + { + chord_name = tetrachords[i].name; + goto CHORD_NAME_KNOWN; + } } + break; } - break; } + CHORD_NAME_KNOWN: if (chord_name) { if (inversion) { -- 2.43.0