X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=scherzo.c;h=ed62f762a60a2eef8bda0a929e88762a3cca8a60;hb=d381e83531820e71a4ab5ad8361da7ffbcb8ae32;hp=d6b3af55f8d56cf6dee4cc2fde49ae1c65fc4d59;hpb=73ba6a9e9a9308747fd0fa301e1a349746eaf47c;p=scherzo diff --git a/scherzo.c b/scherzo.c index d6b3af5..ed62f76 100644 --- a/scherzo.c +++ b/scherzo.c @@ -147,7 +147,8 @@ on_key_press_event (GtkWidget *widget, { scherzo_t *scherzo = user_data; int octave; - score_pitch_name_t pitch_name; + /* Initialize to keep the compiler quiet. */ + score_pitch_name_t pitch_name = SCORE_PITCH_C; score_pitch_t pitch; if (scherzo->challenge.note) @@ -253,7 +254,8 @@ on_key_release_event (unused (GtkWidget *widget), { scherzo_t *scherzo = user_data; int octave; - score_pitch_name_t pitch_name; + /* Initialize to keep the compiler quiet. */ + score_pitch_name_t pitch_name = SCORE_PITCH_NAME_C; score_pitch_t pitch; if (scherzo->challenge.note) @@ -487,12 +489,13 @@ _chord_signature_matches (analyzed_note_t *notes, int num_notes, modified_degree_t *degrees, int num_degrees, - int *inversion_ret) + int *inversion_ret, + score_pitch_t *root) { #define MAX_DEGREES 4 int relative_pitches[MAX_DEGREES]; int inversion, max_inversions; - int i; + int i, root_index; assert (num_degrees <= MAX_DEGREES); @@ -523,6 +526,9 @@ _chord_signature_matches (analyzed_note_t *notes, 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; return 1; @@ -534,6 +540,86 @@ _chord_signature_matches (analyzed_note_t *notes, return 0; } +static const char * +_pitch_str (score_pitch_t pitch) +{ + switch (pitch) { + case SCORE_PITCH_Cff: + return "C𝄫"; + case SCORE_PITCH_Cf: + return "C♭"; + case SCORE_PITCH_C: + return "C"; + case SCORE_PITCH_Cs: + return "C♯"; + case SCORE_PITCH_Css: + return "C𝄪"; + case SCORE_PITCH_Dff: + return "D𝄫"; + case SCORE_PITCH_Df: + return "D♭"; + case SCORE_PITCH_D: + return "D"; + case SCORE_PITCH_Ds: + return "D♯"; + case SCORE_PITCH_Dss: + return "D𝄪"; + case SCORE_PITCH_Eff: + return "E𝄫"; + case SCORE_PITCH_Ef: + return "E♭"; + case SCORE_PITCH_E: + return "E"; + case SCORE_PITCH_Es: + return "E♯"; + case SCORE_PITCH_Ess: + return "E𝄪"; + case SCORE_PITCH_Fff: + return "F𝄫"; + case SCORE_PITCH_Ff: + return "F♭"; + case SCORE_PITCH_F: + return "F"; + case SCORE_PITCH_Fs: + return "F♯"; + case SCORE_PITCH_Fss: + return "F𝄪"; + case SCORE_PITCH_Gff: + return "G𝄫"; + case SCORE_PITCH_Gf: + return "G♭"; + case SCORE_PITCH_G: + return "G"; + case SCORE_PITCH_Gs: + return "G♯"; + case SCORE_PITCH_Gss: + return "G𝄪"; + case SCORE_PITCH_Aff: + return "A𝄫"; + case SCORE_PITCH_Af: + return "A♭"; + case SCORE_PITCH_A: + return "A"; + case SCORE_PITCH_As: + return "A♯"; + case SCORE_PITCH_Ass: + return "A𝄪"; + case SCORE_PITCH_Bff: + return "B𝄫"; + case SCORE_PITCH_Bf: + return "B♭"; + case SCORE_PITCH_B: + return "B"; + case SCORE_PITCH_Bs: + return "B♯"; + case SCORE_PITCH_Bss: + return "B𝄪"; + } + + fprintf (stderr, "Internal error: Unknown pitch %d\n", pitch); + exit (1); +} + static void scherzo_analyze_chord (scherzo_t *scherzo) { @@ -542,6 +628,7 @@ scherzo_analyze_chord (scherzo_t *scherzo) note_group_t *note_group; unsigned i, j, num_notes; int bass_pitch, inversion; + score_pitch_t root; const char *chord_name = NULL; if (scherzo->pedal_pressed) @@ -552,40 +639,53 @@ scherzo_analyze_chord (scherzo_t *scherzo) num_notes = note_group->num_notes; struct { modified_degree_t degrees[1]; const char *name; } octaves[] = { - { {{1, 0}}, "Octave"} + { {{1, 0}}, " Octave"} }; struct { modified_degree_t degrees[2]; const char *name; } intervals[] = { - { {{1, 0}, {2, -1}}, "Minor 2nd"}, - { {{1, 0}, {2, 0}}, "Major 2nd"}, - { {{1, 0}, {3, -1}}, "Minor 3rd"}, - { {{1, 0}, {3, 0}}, "Major 3rd"}, - { {{1, 0}, {4, 0}}, "Perfect 4th"}, - { {{1, 0}, {5, -1}}, "Diminished 5th"}, - { {{1, 0}, {5, 0}}, "Perfect 5th"}, - { {{1, 0}, {6, -1}}, "Minor 6th"}, - { {{1, 0}, {6, 0}}, "Major 6th"}, - { {{1, 0}, {7, -1}}, "Minor 7th"}, - { {{1, 0}, {7, 0}}, "Major 7th"} + { {{1, 0}, {2, -1}}, " Minor 2nd"}, + { {{1, 0}, {2, 0}}, " Major 2nd"}, + { {{1, 0}, {3, -1}}, " Minor 3rd"}, + { {{1, 0}, {3, 0}}, " Major 3rd"}, + { {{1, 0}, {4, 0}}, " Perfect 4th"}, + { {{1, 0}, {5, -1}}, " Diminished 5th"}, + { {{1, 0}, {5, 0}}, " Perfect 5th"}, + { {{1, 0}, {6, -1}}, " Minor 6th"}, + { {{1, 0}, {6, 0}}, " Major 6th"}, + { {{1, 0}, {7, -1}}, " Minor 7th"}, + { {{1, 0}, {7, 0}}, " Major 7th"} }; +/* XXX: The superscript rise value should be relative to the current + * font size. Best would be for pango to support this. See: + * + * https://bugzilla.gnome.org/show_bug.cgi?id=708780 + * + * For now, these are emipirically-derived values that look reasonable + * at the default size that score.c is using to draw the staff. If the + * user scales the staff up or down then these will look wrong. + */ + +#define SUP "" +#define PUS "" + struct { modified_degree_t degrees[3]; const char *name; } triads[] = { - { {{1, 0}, {3, 0}, {5, +1}}, "Augmented triad" }, - { {{1, 0}, {3, 0}, {5, 0}}, "Major triad" }, - { {{1, 0}, {3, -1}, {5, 0}}, "Minor triad" }, - { {{1, 0}, {3, -1}, {5, -1}}, "Diminished triad" } + { {{1, 0}, {3, 0}, {5, +1}}, SUP "+" PUS }, + { {{1, 0}, {3, 0}, {5, 0}}, "M" }, + { {{1, 0}, {3, -1}, {5, 0}}, "m" }, + { {{1, 0}, {3, -1}, {5, -1}}, "°" } }; struct { modified_degree_t degrees[4]; const char *name; } sevenths[] = { - { {{1, 0}, {3, 0}, {5, +1}, {7, 0}}, "Augmented/major 7" }, - { {{1, 0}, {3, 0}, {5, +1}, {7, -1}}, "Augmented 7" }, - { {{1, 0}, {3, 0}, {5, 0}, {7, 0}}, "Major 7" }, - { {{1, 0}, {3, 0}, {5, 0}, {7, -1}}, "Dominant 7" }, - { {{1, 0}, {3, -1}, {5, 0}, {7, 0}}, "Minor/major 7" }, - { {{1, 0}, {3, -1}, {5, 0}, {7, -1}}, "Minor 7" }, - { {{1, 0}, {3, -1}, {5, -1}, {7, 0}}, "Diminished/major 7" }, - { {{1, 0}, {3, -1}, {5, -1}, {7, -1}}, "Half-diminished 7" }, - { {{1, 0}, {3, -1}, {5, -1}, {7, -2}}, "Diminished 7" } + { {{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, -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 }, + { {{1, 0}, {3, -1}, {5, -1}, {7, -1}}, "𝆩" SUP "7" PUS }, + { {{1, 0}, {3, -1}, {5, -1}, {7, -2}}, "°" SUP "7" PUS } }; if (scherzo->chord) { @@ -654,7 +754,8 @@ 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, &inversion)) + octaves[i].degrees, 1, + &inversion, &root)) { chord_name = octaves[i].name; break; @@ -664,7 +765,8 @@ scherzo_analyze_chord (scherzo_t *scherzo) case 2: for (i = 0; i < ARRAY_SIZE (intervals); i++) { if (_chord_signature_matches (notes, num_notes, - intervals[i].degrees, 2, &inversion)) + intervals[i].degrees, 2, + &inversion, &root)) { chord_name = intervals[i].name; break; @@ -674,7 +776,8 @@ scherzo_analyze_chord (scherzo_t *scherzo) case 3: for (i = 0; i < ARRAY_SIZE (triads); i++) { if (_chord_signature_matches (notes, num_notes, - triads[i].degrees, 3, &inversion)) + triads[i].degrees, 3, + &inversion, &root)) { chord_name = triads[i].name; break; @@ -684,7 +787,8 @@ scherzo_analyze_chord (scherzo_t *scherzo) case 4: for (i = 0; i < ARRAY_SIZE(sevenths); i++) { if (_chord_signature_matches (notes, num_notes, - sevenths[i].degrees, 4, &inversion)) + sevenths[i].degrees, 4, + &inversion, &root)) { chord_name = sevenths[i].name; break; @@ -711,10 +815,13 @@ scherzo_analyze_chord (scherzo_t *scherzo) inversion); exit(1); } - chord_name = talloc_asprintf (local, "%s %s", + chord_name = talloc_asprintf (local, "%s%s %s", + _pitch_str (root), chord_name, inversion_str); } else { - chord_name = talloc_strdup (local, chord_name); + chord_name = talloc_asprintf (local, "%s%s", + _pitch_str (root), + chord_name); } } else { chord_name = talloc_strdup (local, "Unknown chord");