]> git.cworth.org Git - scherzo/blobdiff - scherzo.c
Allow keys 0-8 to specify desired octave.
[scherzo] / scherzo.c
index 9b0e2d9ced96bc43dfcf5f8c388d373549c8923f..55a2cc98d40d00b7f80f40d572a07846a6351c76 100644 (file)
--- a/scherzo.c
+++ b/scherzo.c
@@ -51,6 +51,11 @@ typedef struct scherzo
     score_staff_t *treble;
     score_staff_t *bass;
     score_chord_t *chord;
+
+    /* This is for a "computer keyboard". Any "piano keyboard" key
+     * knows its own octave. */
+    int keyboard_octave;
+
     int midi_fd;
     snd_midi_event_t *snd_midi_event;
 
@@ -129,7 +134,7 @@ on_key_press_event (GtkWidget *widget,
     if (scherzo->challenge.note)
        octave = scherzo->challenge.note->octave;
     else
-       octave = 4;
+       octave = scherzo->keyboard_octave;
 
     switch (key->keyval) {
     case GDK_KEY_plus:
@@ -179,6 +184,17 @@ on_key_press_event (GtkWidget *widget,
     case GDK_KEY_B:
        pitch = SCORE_PITCH_B;
        break;
+    case GDK_KEY_0:
+    case GDK_KEY_1:
+    case GDK_KEY_2:
+    case GDK_KEY_3:
+    case GDK_KEY_4:
+    case GDK_KEY_5:
+    case GDK_KEY_6:
+    case GDK_KEY_7:
+    case GDK_KEY_8:
+       scherzo->keyboard_octave = key->keyval - GDK_KEY_0;
+       break;
     }
 
     if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
@@ -210,7 +226,7 @@ on_key_release_event (unused (GtkWidget *widget),
     if (scherzo->challenge.note)
        octave = scherzo->challenge.note->octave;
     else
-       octave = 4;
+       octave = scherzo->keyboard_octave;
 
     switch (key->keyval) {
     case GDK_KEY_c:
@@ -398,6 +414,11 @@ _chord_signature_matches (analyzed_note_t *notes,
        }
     }
 
+    /* If there are fewer notes in the signature than in the chord,
+     * then there is no match. */
+    if (n < num_notes)
+           return 0;
+
     return 1;
 }
 
@@ -410,6 +431,20 @@ scherzo_analyze_chord (scherzo_t *scherzo)
     int bass_pitch;
     const char *chord_name = NULL;
 
+    struct { int pitches[2]; const char *name; } intervals[] = {
+       { {0, 1}, "Minor 2nd"},
+       { {0, 2}, "Major 2nd"},
+       { {0, 3}, "Minor 3rd"},
+       { {0, 4}, "Major 3rd"},
+       { {0, 5}, "Perfect 4th"},
+       { {0, 6}, "Diminished 5th/Augmented 4th"},
+       { {0, 7}, "Perfect 5th"},
+       { {0, 8}, "Minor 6th"},
+       { {0, 9}, "Major 6th"},
+       { {0, 10}, "Minor 7th"},
+       { {0, 11}, "Major 7th"}
+    };
+
     struct { int pitches[3]; const char *name; } triads[] = {
        { {0, 4, 8}, "Augmented triad" },
        { {0, 4, 7}, "Major triad" },
@@ -417,12 +452,24 @@ scherzo_analyze_chord (scherzo_t *scherzo)
        { {0, 3, 6}, "Diminished triad" }
     };
 
+    struct { int pitches[4]; const char *name; } sevenths[] = {
+       { {0, 4, 8, 11}, "Augmented/major 7" },
+       { {0, 4, 7, 11}, "Major 7" },
+       { {0, 4, 7, 10}, "Dominant 7" },
+       { {0, 3, 7, 11}, "Minor/major 7" },
+       { {0, 3, 7, 10}, "Minor 7" },
+       { {0, 3, 6, 10}, "Half-diminished 7" },
+       { {0, 3, 6, 9},  "Diminished 7" },
+       { {0, 4, 8, 10}, "Augmented 7" },
+       { {0, 3, 6, 11}, "Diminished/major 7" },
+    };
+
     if (scherzo->chord) {
        score_remove_chord (scherzo->chord);
        scherzo->chord = NULL;
     }
 
-    if (num_notes == 0)
+    if (num_notes <= 1)
        goto DONE;
 
     notes = talloc_array (local, analyzed_note_t, num_notes);
@@ -446,17 +493,20 @@ scherzo_analyze_chord (scherzo_t *scherzo)
        notes[i].relative_pitch = notes[i].midi_pitch - bass_pitch;
     }
 
+    for (i = 0; i < ARRAY_SIZE (intervals); i++) {
+       if (_chord_signature_matches (notes, num_notes, intervals[i].pitches, 2))
+           chord_name = intervals[i].name;
+    }
+
     for (i = 0; i < ARRAY_SIZE (triads); i++) {
        if (_chord_signature_matches (notes, num_notes, triads[i].pitches, 3))
            chord_name = triads[i].name;
     }
 
-/*
-    for (i = 0; i < num_sevenths; i++) {
-       if (_chord_signature_matches (notes, num_notes, seventh[i].pitches, 4))
-           chord_name = seventh[i].name;
+    for (i = 0; i < ARRAY_SIZE(sevenths); i++) {
+       if (_chord_signature_matches (notes, num_notes, sevenths[i].pitches, 4))
+           chord_name = sevenths[i].name;
     }
-*/
 
     if (chord_name)
        scherzo->chord = score_add_chord (scherzo->treble, chord_name);
@@ -474,10 +524,13 @@ scherzo_add_note (scherzo_t *scherzo, score_pitch_t pitch, int octave)
     score_note_t *note;
     int i;
 
-    if (scherzo->challenge.note)
+    if (scherzo->challenge.note) {
        staff = scherzo->challenge.staff;
-    else
+    } else if (octave >= 4) {
        staff = scherzo->treble;
+    } else {
+       staff = scherzo->bass;
+    }
 
     /* Do nothing if this note is already pressed. */
     for (i = 0; i < scherzo->num_notes_pressed; i++) {
@@ -757,6 +810,9 @@ main (int argc, char *argv[])
 
     scherzo.chord = NULL;
 
+    /* Default to octave 4 for computer keyboard keypresses. */
+    scherzo.keyboard_octave = 4;
+
     scherzo.num_notes_pressed = 0;
     scherzo.notes_pressed = NULL;