X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;f=scherzo.c;h=d6b3af55f8d56cf6dee4cc2fde49ae1c65fc4d59;hb=73ba6a9e9a9308747fd0fa301e1a349746eaf47c;hp=c0582f132517c674e762d1952459c5860113a703;hpb=5f7bba84e7e609d6dba0a960d0e4afb00bce3c85;p=scherzo diff --git a/scherzo.c b/scherzo.c index c0582f1..d6b3af5 100644 --- a/scherzo.c +++ b/scherzo.c @@ -486,10 +486,12 @@ static int _chord_signature_matches (analyzed_note_t *notes, int num_notes, modified_degree_t *degrees, - int num_degrees) + int num_degrees, + int *inversion_ret) { #define MAX_DEGREES 4 int relative_pitches[MAX_DEGREES]; + int inversion, max_inversions; int i; assert (num_degrees <= MAX_DEGREES); @@ -497,14 +499,39 @@ _chord_signature_matches (analyzed_note_t *notes, if (num_notes != num_degrees) return 0; - for (i = 0; i < num_degrees; i++) - relative_pitches[i] = _modified_degree_to_half_steps (°rees[i]); + max_inversions = num_degrees; - for (i = 0; i < num_notes; i++) - if (notes[i].relative_pitch != relative_pitches[i]) - 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; + + } + + for (i = 0; i < num_notes; i++) + if (notes[i].relative_pitch != relative_pitches[i]) + goto NEXT_INVERSION; + + *inversion_ret = inversion; - return 1; + return 1; + + NEXT_INVERSION: + ; + } + + return 0; } static void @@ -514,7 +541,7 @@ scherzo_analyze_chord (scherzo_t *scherzo) analyzed_note_t *notes; note_group_t *note_group; unsigned i, j, num_notes; - int bass_pitch; + int bass_pitch, inversion; const char *chord_name = NULL; if (scherzo->pedal_pressed) @@ -525,7 +552,7 @@ scherzo_analyze_chord (scherzo_t *scherzo) num_notes = note_group->num_notes; struct { modified_degree_t degrees[1]; const char *name; } octaves[] = { - { {{0, 0}}, "Octave"} + { {{1, 0}}, "Octave"} }; struct { modified_degree_t degrees[2]; const char *name; } intervals[] = { @@ -627,37 +654,73 @@ scherzo_analyze_chord (scherzo_t *scherzo) case 1: for (i = 0; i < ARRAY_SIZE (octaves); i++) { if (_chord_signature_matches (notes, num_notes, - octaves[i].degrees, 1)) + octaves[i].degrees, 1, &inversion)) + { chord_name = octaves[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)) + intervals[i].degrees, 2, &inversion)) + { chord_name = intervals[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)) + triads[i].degrees, 3, &inversion)) + { chord_name = triads[i].name; + break; + } } break; case 4: for (i = 0; i < ARRAY_SIZE(sevenths); i++) { if (_chord_signature_matches (notes, num_notes, - sevenths[i].degrees, 4)) + sevenths[i].degrees, 4, &inversion)) + { chord_name = sevenths[i].name; + break; + } } break; } - if (chord_name) - scherzo->chord = score_add_chord (scherzo->treble, chord_name); - else - scherzo->chord = score_add_chord (scherzo->treble, "Unknown or not a chord"); + if (chord_name) { + if (inversion) { + const char *inversion_str; + switch (inversion) { + case 1: + inversion_str = "1st inversion"; + break; + case 2: + inversion_str = "2nd inversion"; + break; + case 3: + inversion_str = "3rd inversion"; + break; + default: + fprintf (stderr, "Internal error: Unexpected inversion: %d\n", + inversion); + exit(1); + } + chord_name = talloc_asprintf (local, "%s %s", + chord_name, inversion_str); + } else { + chord_name = talloc_strdup (local, chord_name); + } + } else { + chord_name = talloc_strdup (local, "Unknown chord"); + } + + scherzo->chord = score_add_chord (scherzo->treble, chord_name); DONE: talloc_free (local);