]> git.cworth.org Git - scherzo/commitdiff
Fix bugs in analysis for out-of-order chords
authorCarl Worth <cworth@cworth.org>
Wed, 18 Sep 2013 03:41:32 +0000 (20:41 -0700)
committerCarl Worth <cworth@cworth.org>
Wed, 18 Sep 2013 03:41:32 +0000 (20:41 -0700)
When the various notes of a chord were in different octaves, scherzo
was sometimes getting confused and was unable to match the chord to
its known signatures. We fix this by adding a secondary sort, (first
sort by absolute pitch to find bass note so to compute relative pitch,
and then second sort by relative pitch).

scherzo.c

index 7f6d5e9a5862ff63a157abcac5b44271f7ca9549..0b0a97f77e9ed2049f82422d1069300525e0fa39 100644 (file)
--- a/scherzo.c
+++ b/scherzo.c
@@ -407,13 +407,21 @@ typedef struct analyzed_note {
 } analyzed_note_t;
 
 static int
-_compare_analyzed_note (const void *va, const void *vb)
+_compare_analyzed_note_by_midi_pitch (const void *va, const void *vb)
 {
     const analyzed_note_t *a = va, *b = vb;
 
     return a->midi_pitch - b->midi_pitch;
 }
 
+static int
+_compare_analyzed_note_by_relative_pitch (const void *va, const void *vb)
+{
+    const analyzed_note_t *a = va, *b = vb;
+
+    return a->relative_pitch - b->relative_pitch;
+}
+
 static int
 _chord_signature_matches (analyzed_note_t *notes,
                          int num_notes,
@@ -519,16 +527,23 @@ scherzo_analyze_chord (scherzo_t *scherzo)
        notes[i].relative_pitch = 0;
     }
 
-    qsort (notes, num_notes, sizeof (analyzed_note_t), _compare_analyzed_note);
+    /* First, sort by midi pitch to find the bass note. */
+    qsort (notes, num_notes, sizeof (analyzed_note_t),
+          _compare_analyzed_note_by_midi_pitch);
     
     bass_pitch = notes[0].midi_pitch;
 
+    /* With the bass note identified, we can find all relative pitches. */
     for (i = 0; i < num_notes; i++) {
        notes[i].relative_pitch = notes[i].midi_pitch - bass_pitch;
        while (notes[i].relative_pitch >= 12)
            notes[i].relative_pitch -= 12;
     }
 
+    /* Now, sort again by relative pitch. */
+    qsort (notes, num_notes, sizeof (analyzed_note_t),
+          _compare_analyzed_note_by_relative_pitch);
+
     for (i = 0; i < ARRAY_SIZE (octaves); i++) {
        if (_chord_signature_matches (notes, num_notes, octaves[i].pitches, 1))
            chord_name = octaves[i].name;