]> git.cworth.org Git - scherzo/commitdiff
Rework computer keyboard input to be mapped piano keyboard
authorCarl Worth <cworth@cworth.org>
Tue, 1 Oct 2013 15:47:34 +0000 (08:47 -0700)
committerCarl Worth <cworth@cworth.org>
Tue, 1 Oct 2013 16:30:48 +0000 (09:30 -0700)
Instead of using computer keyboard letter names for piano note names,
(which allowed only entering natural notes), we now map the piano
keyboard onto the computer keyboard. The naturals are on the home row,
(middle C is on 'A' and the next higher C is on 'K'), and the sharps
map onto the top row in the obvious position, (C# on 'W, D# on 'E',
etc.).

pitch.h
scherzo.c

diff --git a/pitch.h b/pitch.h
index 4467aa86a825c239faa6842819c21d85b58fb1e6..3d1dd2e125b98cda6cc4c2ecfe150c54278258db 100644 (file)
--- a/pitch.h
+++ b/pitch.h
@@ -60,6 +60,8 @@ typedef uint32_t pitch_t;
 #define PITCH_CLASS_LITERAL(literal_name, literal_accidental) \
     PITCH_LITERAL(literal_name, literal_accidental, 0)
 
 #define PITCH_CLASS_LITERAL(literal_name, literal_accidental) \
     PITCH_LITERAL(literal_name, literal_accidental, 0)
 
+#define PITCH_NOT_A_PITCH ((pitch_t) -1)
+
 typedef enum pitch_accidental
 {
     PITCH_ACCIDENTAL_DOUBLE_FLAT,
 typedef enum pitch_accidental
 {
     PITCH_ACCIDENTAL_DOUBLE_FLAT,
index e8d0d274231e42d0adf1da3d8b3d91ad171c5f7b..e57ccbe9b3fe7f831d535bf73d77544d62dce04e 100644 (file)
--- a/scherzo.c
+++ b/scherzo.c
@@ -66,7 +66,6 @@ typedef struct scherzo
      * keyboard". Any "piano keyboard" key knows its own octave and
      * accidental already. */
     int keyboard_octave;
      * keyboard". Any "piano keyboard" key knows its own octave and
      * accidental already. */
     int keyboard_octave;
-    pitch_accidental_t keyboard_accidental;
 
     int midi_fd;
     snd_midi_event_t *snd_midi_event;
 
     int midi_fd;
     snd_midi_event_t *snd_midi_event;
@@ -151,9 +150,7 @@ on_key_press_event (GtkWidget *widget,
 {
     scherzo_t *scherzo = user_data;
     int octave;
 {
     scherzo_t *scherzo = user_data;
     int octave;
-    /* Initialize to keep the compiler quiet. */
-    pitch_name_t pitch_name = PITCH_NATURAL (C, 0);
-    pitch_t pitch;
+    pitch_t pitch = PITCH_NOT_A_PITCH;
 
     if (scherzo->challenge.active)
        octave = PITCH_OCTAVE (scherzo->challenge.pitch);
 
     if (scherzo->challenge.active)
        octave = PITCH_OCTAVE (scherzo->challenge.pitch);
@@ -175,38 +172,89 @@ on_key_press_event (GtkWidget *widget,
        gtk_widget_queue_draw (widget);
        return TRUE;
        break;
        gtk_widget_queue_draw (widget);
        return TRUE;
        break;
-    case GDK_KEY_q:
-    case GDK_KEY_Q:
     case GDK_KEY_Escape:
        gtk_main_quit ();
        return FALSE;
     case GDK_KEY_Escape:
        gtk_main_quit ();
        return FALSE;
-    case GDK_KEY_c:
-    case GDK_KEY_C:
-       pitch_name = PITCH_NAME_C;
+    /* Map a piano keyboard onto the computer keyboard with white keys
+     * along the home row, (piano C on computer A, up to next octave
+     * higher C on computer K). Black keys are in the expected
+     * positions, (C# is W, D# is E, etc.).
+     */
+    case GDK_KEY_a:
+    case GDK_KEY_A:
+       pitch = PITCH_LITERAL (C, NATURAL, octave);
+       break;
+    case GDK_KEY_s:
+    case GDK_KEY_S:
+       pitch = PITCH_LITERAL (D, NATURAL, octave);
        break;
     case GDK_KEY_d:
     case GDK_KEY_D:
        break;
     case GDK_KEY_d:
     case GDK_KEY_D:
-       pitch_name = PITCH_NAME_D;
-       break;
-    case GDK_KEY_e:
-    case GDK_KEY_E:
-       pitch_name = PITCH_NAME_E;
+       pitch = PITCH_LITERAL (E, NATURAL, octave);
        break;
     case GDK_KEY_f:
     case GDK_KEY_F:
        break;
     case GDK_KEY_f:
     case GDK_KEY_F:
-       pitch_name = PITCH_NAME_F;
+       pitch = PITCH_LITERAL (F, NATURAL, octave);
        break;
     case GDK_KEY_g:
     case GDK_KEY_G:
        break;
     case GDK_KEY_g:
     case GDK_KEY_G:
-       pitch_name = PITCH_NAME_G;
+       pitch = PITCH_LITERAL (G, NATURAL, octave);
        break;
        break;
-    case GDK_KEY_a:
-    case GDK_KEY_A:
-       pitch_name = PITCH_NAME_A;
+    case GDK_KEY_h:
+    case GDK_KEY_H:
+       pitch = PITCH_LITERAL (A, NATURAL, octave);
        break;
        break;
-    case GDK_KEY_b:
-    case GDK_KEY_B:
-       pitch_name = PITCH_NAME_B;
+    case GDK_KEY_j:
+    case GDK_KEY_J:
+       pitch = PITCH_LITERAL (B, NATURAL, octave);
+       break;
+    case GDK_KEY_k:
+    case GDK_KEY_K:
+       pitch = PITCH_LITERAL (C, NATURAL, octave + 1);
+       break;
+    case GDK_KEY_l:
+    case GDK_KEY_L:
+       pitch = PITCH_LITERAL (D, NATURAL, octave + 1);
+       break;
+    case GDK_KEY_semicolon:
+    case GDK_KEY_colon:
+       pitch = PITCH_LITERAL (E, NATURAL, octave + 1);
+       break;
+    case GDK_KEY_apostrophe:
+    case GDK_KEY_quotedbl:
+       pitch = PITCH_LITERAL (F, NATURAL, octave + 1);
+       break;
+    case GDK_KEY_w:
+    case GDK_KEY_W:
+       pitch = PITCH_LITERAL (C, SHARP, octave);
+       break;
+    case GDK_KEY_e:
+    case GDK_KEY_E:
+       pitch = PITCH_LITERAL (D, SHARP, octave);
+       break;
+    case GDK_KEY_t:
+    case GDK_KEY_T:
+       pitch = PITCH_LITERAL (F, SHARP, octave);
+       break;
+    case GDK_KEY_y:
+    case GDK_KEY_Y:
+       pitch = PITCH_LITERAL (G, SHARP, octave);
+       break;
+    case GDK_KEY_u:
+    case GDK_KEY_U:
+       pitch = PITCH_LITERAL (A, SHARP, octave);
+       break;
+    case GDK_KEY_o:
+    case GDK_KEY_O:
+       pitch = PITCH_LITERAL (C, SHARP, octave + 1);
+       break;
+    case GDK_KEY_p:
+    case GDK_KEY_P:
+       pitch = PITCH_LITERAL (D, SHARP, octave + 1);
+       break;
+    case GDK_KEY_bracketright:
+    case GDK_KEY_braceright:
+       pitch = PITCH_LITERAL (F, SHARP, octave + 1);
        break;
     case GDK_KEY_0:
     case GDK_KEY_1:
        break;
     case GDK_KEY_0:
     case GDK_KEY_1:
@@ -222,20 +270,9 @@ on_key_press_event (GtkWidget *widget,
     case GDK_KEY_space:
        scherzo_press_pedal (scherzo);
        break;
     case GDK_KEY_space:
        scherzo_press_pedal (scherzo);
        break;
-    case GDK_KEY_Up:
-       if (scherzo->keyboard_accidental < PITCH_ACCIDENTAL_DOUBLE_SHARP)
-           scherzo->keyboard_accidental++;
-       break;
-    case GDK_KEY_Down:
-       if (scherzo->keyboard_accidental > PITCH_ACCIDENTAL_DOUBLE_FLAT)
-           scherzo->keyboard_accidental--;
-       break;
     }
 
     }
 
-    pitch = PITCH (pitch_name, scherzo->keyboard_accidental, octave);
-
-    if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
-       (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g))
+    if (pitch != PITCH_NOT_A_PITCH) 
     {
        scherzo_press_note (scherzo, pitch);
        _judge_pitch (scherzo, pitch);
     {
        scherzo_press_note (scherzo, pitch);
        _judge_pitch (scherzo, pitch);
@@ -256,9 +293,7 @@ on_key_release_event (unused (GtkWidget *widget),
 {
     scherzo_t *scherzo = user_data;
     int octave;
 {
     scherzo_t *scherzo = user_data;
     int octave;
-    /* Initialize to keep the compiler quiet. */
-    pitch_name_t pitch_name = PITCH_NAME_C;
-    pitch_t pitch;
+    pitch_t pitch = PITCH_NOT_A_PITCH;
 
     if (scherzo->challenge.active)
        octave = PITCH_OCTAVE (scherzo->challenge.pitch);
 
     if (scherzo->challenge.active)
        octave = PITCH_OCTAVE (scherzo->challenge.pitch);
@@ -266,43 +301,88 @@ on_key_release_event (unused (GtkWidget *widget),
        octave = scherzo->keyboard_octave;
 
     switch (key->keyval) {
        octave = scherzo->keyboard_octave;
 
     switch (key->keyval) {
-    case GDK_KEY_c:
-    case GDK_KEY_C:
-       pitch_name = PITCH_NAME_C;
+    case GDK_KEY_a:
+    case GDK_KEY_A:
+       pitch = PITCH_LITERAL (C, NATURAL, octave);
+       break;
+    case GDK_KEY_s:
+    case GDK_KEY_S:
+       pitch = PITCH_LITERAL (D, NATURAL, octave);
        break;
     case GDK_KEY_d:
     case GDK_KEY_D:
        break;
     case GDK_KEY_d:
     case GDK_KEY_D:
-       pitch_name = PITCH_NAME_D;
-       break;
-    case GDK_KEY_e:
-    case GDK_KEY_E:
-       pitch_name = PITCH_NAME_E;
+       pitch = PITCH_LITERAL (E, NATURAL, octave);
        break;
     case GDK_KEY_f:
     case GDK_KEY_F:
        break;
     case GDK_KEY_f:
     case GDK_KEY_F:
-       pitch_name = PITCH_NAME_F;
+       pitch = PITCH_LITERAL (F, NATURAL, octave);
        break;
     case GDK_KEY_g:
     case GDK_KEY_G:
        break;
     case GDK_KEY_g:
     case GDK_KEY_G:
-       pitch_name = PITCH_NAME_G;
+       pitch = PITCH_LITERAL (G, NATURAL, octave);
        break;
        break;
-    case GDK_KEY_a:
-    case GDK_KEY_A:
-       pitch_name = PITCH_NAME_A;
+    case GDK_KEY_h:
+    case GDK_KEY_H:
+       pitch = PITCH_LITERAL (A, NATURAL, octave);
        break;
        break;
-    case GDK_KEY_b:
-    case GDK_KEY_B:
-       pitch_name = PITCH_NAME_B;
+    case GDK_KEY_j:
+    case GDK_KEY_J:
+       pitch = PITCH_LITERAL (B, NATURAL, octave);
+       break;
+    case GDK_KEY_k:
+    case GDK_KEY_K:
+       pitch = PITCH_LITERAL (C, NATURAL, octave + 1);
+       break;
+    case GDK_KEY_l:
+    case GDK_KEY_L:
+       pitch = PITCH_LITERAL (D, NATURAL, octave + 1);
+       break;
+    case GDK_KEY_semicolon:
+    case GDK_KEY_colon:
+       pitch = PITCH_LITERAL (E, NATURAL, octave + 1);
+       break;
+    case GDK_KEY_apostrophe:
+    case GDK_KEY_quotedbl:
+       pitch = PITCH_LITERAL (F, NATURAL, octave + 1);
+       break;
+    case GDK_KEY_w:
+    case GDK_KEY_W:
+       pitch = PITCH_LITERAL (C, SHARP, octave);
+       break;
+    case GDK_KEY_e:
+    case GDK_KEY_E:
+       pitch = PITCH_LITERAL (D, SHARP, octave);
+       break;
+    case GDK_KEY_t:
+    case GDK_KEY_T:
+       pitch = PITCH_LITERAL (F, SHARP, octave);
+       break;
+    case GDK_KEY_y:
+    case GDK_KEY_Y:
+       pitch = PITCH_LITERAL (G, SHARP, octave);
+       break;
+    case GDK_KEY_u:
+    case GDK_KEY_U:
+       pitch = PITCH_LITERAL (A, SHARP, octave);
+       break;
+    case GDK_KEY_o:
+    case GDK_KEY_O:
+       pitch = PITCH_LITERAL (C, SHARP, octave + 1);
+       break;
+    case GDK_KEY_p:
+    case GDK_KEY_P:
+       pitch = PITCH_LITERAL (D, SHARP, octave + 1);
+       break;
+    case GDK_KEY_bracketright:
+    case GDK_KEY_braceright:
+       pitch = PITCH_LITERAL (F, SHARP, octave + 1);
        break;
     case GDK_KEY_space:
        scherzo_release_pedal (scherzo);
        break;
     }
 
        break;
     case GDK_KEY_space:
        scherzo_release_pedal (scherzo);
        break;
     }
 
-    pitch = PITCH (pitch_name, scherzo->keyboard_accidental, octave);
-
-    if ((key->keyval >= GDK_KEY_A && key->keyval <= GDK_KEY_G) ||
-       (key->keyval >= GDK_KEY_a && key->keyval <= GDK_KEY_g))
+    if (pitch != PITCH_NOT_A_PITCH)
     {
        scherzo_release_note (scherzo, pitch);
        _score_challenge (scherzo);
     {
        scherzo_release_note (scherzo, pitch);
        _score_challenge (scherzo);
@@ -1347,9 +1427,8 @@ main (int argc, char *argv[])
 
     scherzo.chord = NULL;
 
 
     scherzo.chord = NULL;
 
-    /* Default to octave 4 and natural for computer keyboard keypresses. */
+    /* Default to octave 4 for computer keyboard keypresses. */
     scherzo.keyboard_octave = 4;
     scherzo.keyboard_octave = 4;
-    scherzo.keyboard_accidental = PITCH_ACCIDENTAL_NATURAL;
 
     pitch_group_init (scherzo.ctx, &scherzo.notes_pressed);
     pitch_group_init (scherzo.ctx, &scherzo.notes_pedaled);
 
     pitch_group_init (scherzo.ctx, &scherzo.notes_pressed);
     pitch_group_init (scherzo.ctx, &scherzo.notes_pedaled);