X-Git-Url: https://git.cworth.org/git?p=scherzo;a=blobdiff_plain;f=scherzo.c;h=dacefa8e8e8e186ec9fa6f20b9f79f05ab34e420;hp=dd7fdbf076109c5f3728280c6ab4b0c1f246e0aa;hb=f492c33c1fd33c1dc0a2c892753300c7225dbd51;hpb=b04b7c233ac3732f0374b3d268524d573fe65978 diff --git a/scherzo.c b/scherzo.c index dd7fdbf..dacefa8 100644 --- a/scherzo.c +++ b/scherzo.c @@ -280,8 +280,6 @@ on_key_press_event (GtkWidget *widget, if (pitch != PITCH_NOT_A_PITCH) { - pitch = scherzo_key_spell_pitch (&scherzo->key, pitch); - scherzo_press_note (scherzo, pitch); return TRUE; @@ -389,8 +387,6 @@ on_key_release_event (unused (GtkWidget *widget), if (pitch != PITCH_NOT_A_PITCH) { - pitch = scherzo_key_spell_pitch (&scherzo->key, pitch); - scherzo_release_note (scherzo, pitch); return TRUE; @@ -926,7 +922,17 @@ scherzo_update_notes_and_chord (scherzo_t *scherzo) /* Don't print root pitch for octaves and inversions, * (since a pitch name alone looks like a major triad) */ if (signature->num_degrees < 3) { + /* In fact, don't print anything for octaves and + * inversions for now. It leads to a bit of flashing when + * playing chords. + * + * FIXME: What I'd like to have here is a small timeout, + * such that names only appear once an interval has been + * held for at least 100 ms or so. With that, it would be + * nice to display the interval names once again. + * chord_name = talloc_strdup (local, signature->name); + */ } else { _spell_chord_by_signature (&scherzo->notes_pressed, signature, *root); @@ -961,11 +967,54 @@ scherzo_update_notes_and_chord (scherzo_t *scherzo) talloc_free (local); } +static void +scherzo_set_key (scherzo_t *scherzo, pitch_t pitch) +{ + scherzo_key_init (&scherzo->key, pitch); + score_set_key (scherzo->score, pitch); +} + +static bool +pitches_are_diatonic_scale (pitch_t *pitches, int num_pitches) +{ + int diatonic_half_steps[7] = { + 0, 2, 4, 5, 7, 9, 11 + }; + int half_steps; + pitch_t root; + int i; + + if (num_pitches < 7) + return 0; + + root = pitches[0]; + + for (i = 0; i < 7; i++) { + half_steps = pitch_from_root_in_half_steps (pitches[i], root); + if (half_steps != diatonic_half_steps[i]) + return false; + } + + return true; +} + static void scherzo_press_note (scherzo_t *scherzo, pitch_t pitch) { int i; + pitch = scherzo_key_spell_pitch (&scherzo->key, pitch); + +#define NUM_RECENT_PITCHES 7 + static pitch_t recent_pitches[NUM_RECENT_PITCHES]; + + memmove (recent_pitches, recent_pitches + 1, + (NUM_RECENT_PITCHES - 1) * sizeof (pitch_t)); + recent_pitches[NUM_RECENT_PITCHES - 1] = pitch; + + if (pitches_are_diatonic_scale (recent_pitches, NUM_RECENT_PITCHES)) + scherzo_set_key (scherzo, recent_pitches[0]); + /* Do nothing if this note is already pressed. */ for (i = 0; i < scherzo->notes_pressed.num_pitches; i++) if (scherzo->notes_pressed.pitches[i] == pitch) @@ -982,6 +1031,8 @@ scherzo_press_note (scherzo_t *scherzo, pitch_t pitch) static void scherzo_release_note (scherzo_t *scherzo, pitch_t pitch) { + pitch = scherzo_key_spell_pitch (&scherzo->key, pitch); + pitch_group_remove_pitch_enharmonic (&scherzo->notes_pressed, pitch); scherzo_update_notes_and_chord (scherzo); @@ -1236,8 +1287,7 @@ main (int argc, char *argv[]) scherzo.pedal_pressed = 0; /* Default to key of C Major, naturally. */ - scherzo_key_init (&scherzo.key, PITCH_CLASS_LITERAL (C, NATURAL)); - score_set_key (scherzo.score, scherzo.key.pitch); + scherzo_set_key (&scherzo, PITCH_CLASS_LITERAL (C, NATURAL)); mnemon_init (&scherzo.mnemon); /* XXX: Should create a default file if one cannot be loaded. */