]> git.cworth.org Git - scherzo/commitdiff
Add recognition of 6, m6, and 7-flat-5 chords.
authorCarl Worth <cworth@cworth.org>
Thu, 26 Sep 2013 00:23:17 +0000 (17:23 -0700)
committerCarl Worth <cworth@cworth.org>
Thu, 26 Sep 2013 00:40:11 +0000 (17:40 -0700)
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

index 098008930e4d4d77b4dd21ec82ad40ca52d19554..d1a164c76e6e9ac052faf1def3810dcf4d8681b6 100644 (file)
--- 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 (&degrees[i]) -
-                _modified_degree_to_half_steps (&degrees[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 (&degrees[i]) -
+            _modified_degree_to_half_steps (&degrees[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) {