]> git.cworth.org Git - scherzo/commitdiff
Encode octave within pitch_t value
authorCarl Worth <cworth@cworth.org>
Sat, 28 Sep 2013 19:18:01 +0000 (12:18 -0700)
committerCarl Worth <cworth@cworth.org>
Sat, 28 Sep 2013 19:18:01 +0000 (12:18 -0700)
This simplifies the code quite a bit. Instead of passing around pairs
of (pitch, octave) all over the place a simple pitch_t value suffices.

pitch.h
scherzo.c
score.c
score.h

diff --git a/pitch.h b/pitch.h
index 525f14c8ae5038426bfe97c0c879ee8c67a3d637..657e8fe07f8f291f1a4846c4cf0e596f1f2cdf7d 100644 (file)
--- a/pitch.h
+++ b/pitch.h
 #ifndef PITCH_H
 #define PITCH_H
 
-#define PITCH_ACCIDENTAL_MASK 0x07
-#define PITCH_ACCIDENTAL_SHIFT 0
+typedef uint32_t pitch_t;
+
+#define PITCH_ACCIDENTAL_SHIFT (0)
+#define PITCH_ACCIDENTAL_MASK  (0x07 << PITCH_ACCIDENTAL_SHIFT)
+
+#define PITCH_NAME_SHIFT       (3)
+#define PITCH_NAME_MASK                (0x07 << PITCH_NAME_SHIFT)
+
+#define PITCH_OCTAVE_SHIFT     (6)
+#define PITCH_OCTAVE_MASK      (0x07 << PITCH_OCTAVE_SHIFT)
+
+#define PITCH_ACCIDENTAL(pitch)        \
+    (((pitch) & PITCH_ACCIDENTAL_MASK) >> PITCH_ACCIDENTAL_SHIFT)
+#define PITCH_NAME(pitch)      \
+    (((pitch) & PITCH_NAME_MASK) >> PITCH_NAME_SHIFT)
+#define PITCH_OCTAVE(pitch)    \
+    (((pitch) & PITCH_OCTAVE_MASK) >> PITCH_OCTAVE_SHIFT)
+
+#define PITCH(name, accidental, octave)                  \
+    (((octave) << PITCH_OCTAVE_SHIFT)          | \
+     ((name) << PITCH_NAME_SHIFT)              | \
+     ((accidental) << PITCH_ACCIDENTAL_SHIFT))
+
+#define PITCH_LITERAL(literal_name, literal_accidental, octave)        \
+    PITCH(PITCH_NAME_##literal_name,                           \
+         PITCH_ACCIDENTAL_##literal_accidental,                \
+         octave)
+
+#define PITCH_NATURAL(literal_name, octave) \
+    PITCH_LITERAL(literal_name, NATURAL, octave)
 
 typedef enum pitch_accidental
 {
@@ -35,11 +63,6 @@ typedef enum pitch_accidental
     PITCH_ACCIDENTAL_DOUBLE_SHARP
 } pitch_accidental_t;
 
-#define PITCH_ACCIDENTAL(pitch) (((pitch) & PITCH_ACCIDENTAL_MASK) >> PITCH_ACCIDENTAL_SHIFT)
-
-#define PITCH_NAME_MASK 0x38
-#define PITCH_NAME_SHIFT 3
-
 typedef enum pitch_name
 {
     PITCH_NAME_C,
@@ -51,13 +74,8 @@ typedef enum pitch_name
     PITCH_NAME_B,
 } pitch_name_t;
 
-#define PITCH_NAME(pitch) (((pitch) & PITCH_NAME_MASK) >> PITCH_NAME_SHIFT)
-
-#define PITCH(name, accidental) (((name) << PITCH_NAME_SHIFT) | (accidental))
-
-#define PITCH_LITERAL(literal_name, literal_accidental) PITCH(PITCH_NAME_##literal_name, PITCH_ACCIDENTAL_##literal_accidental)
-#define PITCH_NATURAL(literal_name) PITCH_LITERAL(literal_name, NATURAL)
-
-typedef uint32_t pitch_t;
+/* Octave numbers are ISO octave numbers [0:8], (so Octave 4 is from
+ * middle C to the B above middle C).
+ */
 
 #endif /* PITCH_H */
index d3ca62843fa1e0beb4921b3a2c3c887e66af4119..0192c0c1a4dee0ca60fdc68d2ead86336aeaad24 100644 (file)
--- a/scherzo.c
+++ b/scherzo.c
@@ -80,10 +80,10 @@ typedef struct scherzo
 
 /* Forward declarations. */
 static score_note_t *
-scherzo_press_note (scherzo_t *scherzo, pitch_t pitch, int octave);
+scherzo_press_note (scherzo_t *scherzo, pitch_t pitch);
 
 static void
-scherzo_release_note (scherzo_t *scherzo, pitch_t pitch, int octave);
+scherzo_release_note (scherzo_t *scherzo, pitch_t pitch);
 
 static void
 scherzo_press_pedal (scherzo_t *scherzo);
@@ -148,11 +148,11 @@ on_key_press_event (GtkWidget *widget,
     scherzo_t *scherzo = user_data;
     int octave;
     /* Initialize to keep the compiler quiet. */
-    pitch_name_t pitch_name = PITCH_NATURAL (C);
+    pitch_name_t pitch_name = PITCH_NATURAL (C, 0);
     pitch_t pitch;
 
     if (scherzo->challenge.note)
-       octave = scherzo->challenge.note->octave;
+       octave = PITCH_OCTAVE (scherzo->challenge.note->pitch);
     else
        octave = scherzo->keyboard_octave;
 
@@ -228,14 +228,14 @@ on_key_press_event (GtkWidget *widget,
        break;
     }
 
-    pitch = PITCH (pitch_name, scherzo->keyboard_accidental);
+    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))
     {
        score_note_t *note;
 
-       note = scherzo_press_note (scherzo, pitch, octave);
+       note = scherzo_press_note (scherzo, pitch);
        _judge_note (scherzo, note);
        gtk_widget_queue_draw (scherzo->window);
 
@@ -259,7 +259,7 @@ on_key_release_event (unused (GtkWidget *widget),
     pitch_t pitch;
 
     if (scherzo->challenge.note)
-       octave = scherzo->challenge.note->octave;
+       octave = PITCH_OCTAVE (scherzo->challenge.note->pitch);
     else
        octave = scherzo->keyboard_octave;
 
@@ -297,12 +297,12 @@ on_key_release_event (unused (GtkWidget *widget),
        break;
     }
 
-    pitch = PITCH (pitch_name, scherzo->keyboard_accidental);
+    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))
     {
-       scherzo_release_note (scherzo, pitch, octave);
+       scherzo_release_note (scherzo, pitch);
        _score_challenge (scherzo);
        gtk_widget_queue_draw (scherzo->window);
 
@@ -315,9 +315,9 @@ on_key_release_event (unused (GtkWidget *widget),
 }
 
 static unsigned char
-_pitch_and_octave_to_midi (pitch_t pitch,
-                                int octave)
+_pitch_to_midi (pitch_t pitch)
 {
+    int octave = PITCH_OCTAVE (pitch);
     unsigned char midi_note = 12 * (octave + 1);
 
     switch (PITCH_NAME (pitch)) {
@@ -364,51 +364,49 @@ _pitch_and_octave_to_midi (pitch_t pitch,
 }
 
 /* octave can optionally by NULL */
-static void
-_midi_to_pitch_and_octave (unsigned char midi_note,
-                                pitch_t *pitch,
-                                int *octave)
+static pitch_t
+_midi_to_pitch (unsigned char midi_note)
 {
-    if (octave)
-       *octave = midi_note / 12 - 1;
+    int octave = octave = midi_note / 12 - 1;
 
     switch (midi_note % 12)
     {
+    default:
     case 0:
-       *pitch = PITCH_LITERAL (C, NATURAL);
+       return PITCH_LITERAL (C, NATURAL, octave);
        break;
     case 1:
-       *pitch = PITCH_LITERAL (C, SHARP);
+       return PITCH_LITERAL (C, SHARP, octave);
        break;
     case 2:
-       *pitch = PITCH_LITERAL (D, NATURAL);
+       return PITCH_LITERAL (D, NATURAL, octave);
        break;
     case 3:
-       *pitch = PITCH_LITERAL (D, SHARP);
+       return PITCH_LITERAL (D, SHARP, octave);
        break;
     case 4:
-       *pitch = PITCH_LITERAL (E, NATURAL);
+       return PITCH_LITERAL (E, NATURAL, octave);
        break;
     case 5:
-       *pitch = PITCH_LITERAL (F, NATURAL);
+       return PITCH_LITERAL (F, NATURAL, octave);
        break;
     case 6:
-       *pitch = PITCH_LITERAL (F, SHARP);
+       return PITCH_LITERAL (F, SHARP, octave);
        break;
     case 7:
-       *pitch = PITCH_LITERAL (G, NATURAL);
+       return PITCH_LITERAL (G, NATURAL, octave);
        break;
     case 8:
-       *pitch = PITCH_LITERAL (G, SHARP);
+       return PITCH_LITERAL (G, SHARP, octave);
        break;
     case 9:
-       *pitch = PITCH_LITERAL (A, NATURAL);
+       return PITCH_LITERAL (A, NATURAL, octave);
        break;
     case 10:
-       *pitch = PITCH_LITERAL (A, SHARP);
+       return PITCH_LITERAL (A, SHARP, octave);
        break;
     case 11:
-       *pitch = PITCH_LITERAL (B, NATURAL);
+       return PITCH_LITERAL (B, NATURAL, octave);
        break;
     }
 }
@@ -492,21 +490,16 @@ _modified_degree_to_half_steps (const modified_degree_t *degree)
 }
 
 /* Number of half steps from 'root' up to 'pitch' (that is, counting
- * the steps up a chromatic scale). */
+ * the steps up a chromatic scale), within the same octave. */
 static int
 _pitch_from_root_in_half_steps (pitch_t pitch, pitch_t root)
 {
-    int root_midi = _pitch_and_octave_to_midi (root, 0);
-    int pitch_midi = _pitch_and_octave_to_midi (pitch, 0);
+    int root_midi = _pitch_to_midi (root);
+    int pitch_midi = _pitch_to_midi (pitch);
 
-    if (pitch_midi < root_midi)
+    while (pitch_midi < root_midi)
        pitch_midi += 12;
 
-    if (pitch_midi < root_midi) {
-       fprintf (stderr, "Internal error: midi values differ by more than expected.\n");
-       exit (1);
-    }
-
     return (pitch_midi - root_midi) % 12;
 }
 
@@ -767,6 +760,7 @@ scherzo_adjust_note_to_match_modified_degree (score_note_t *note,
 {
     pitch_name_t name = PITCH_NAME (note->pitch);
     pitch_accidental_t accidental = PITCH_ACCIDENTAL (note->pitch);
+    int octave = PITCH_OCTAVE (note->pitch);
     int degree_zero_based = (degree->degree - 1) % 7;
     int degree_delta;
 
@@ -791,7 +785,7 @@ scherzo_adjust_note_to_match_modified_degree (score_note_t *note,
     if (degree_delta == -1) {
        if (name == PITCH_NAME_B) {
            name = PITCH_NAME_C;
-           note->octave++;
+           octave++;
        } else {
            name++;
        }
@@ -813,7 +807,7 @@ scherzo_adjust_note_to_match_modified_degree (score_note_t *note,
     if (degree_delta == +1) {
        if (name == PITCH_NAME_C) {
            name = PITCH_NAME_B;
-           note->octave--;
+           octave--;
        } else {
            name--;
        }
@@ -836,7 +830,7 @@ scherzo_adjust_note_to_match_modified_degree (score_note_t *note,
        exit (1);
     }
 
-    note->pitch = PITCH (name, accidental);
+    note->pitch = PITCH (name, accidental, octave);
 }
 
 static void
@@ -850,8 +844,8 @@ _spell_chord_by_signature (note_group_t *chord,
 
     /* Sanitize root to eliminate things like double-flats,
      * double-sharps, Cb, E#, etc. */
-    root_midi = _pitch_and_octave_to_midi (root, 0);
-    _midi_to_pitch_and_octave (root_midi, &root, NULL);
+    root_midi = _pitch_to_midi (root);
+    root = _midi_to_pitch (root_midi);
     
     for (i = 0; i < num_notes; i++) {
        note_half_steps = _pitch_from_root_in_half_steps (chord->notes[i]->pitch,
@@ -906,8 +900,7 @@ scherzo_analyze_chord (scherzo_t *scherzo)
     for (i = 0; i < num_notes; i++) {
        score_note_t *note = note_group->notes[i];
        notes[i].note = note;
-       notes[i].midi_pitch = _pitch_and_octave_to_midi (note->pitch,
-                                                              note->octave);
+       notes[i].midi_pitch = _pitch_to_midi (note->pitch);
        /* Relative pitch will be filled in after sorting. */
        notes[i].relative_pitch = 0;
     }
@@ -1007,13 +1000,9 @@ note_group_add_note (note_group_t *group, score_note_t *note)
     int i;
 
     /* Do nothing if note is already in group. */
-    for (i = 0; i < group->num_notes; i++) {
-       if (group->notes[i]->pitch == note->pitch &&
-           group->notes[i]->octave == note->octave)
-       {
+    for (i = 0; i < group->num_notes; i++)
+       if (group->notes[i]->pitch == note->pitch)
            return;
-       }
-    }
 
     group->num_notes++;
 
@@ -1047,7 +1036,7 @@ note_group_remove_note_at (note_group_t *group, int i)
 }
 
 static score_note_t *
-scherzo_press_note (scherzo_t *scherzo, pitch_t pitch, int octave)
+scherzo_press_note (scherzo_t *scherzo, pitch_t pitch)
 {
     score_staff_t *staff;
     score_note_t *note;
@@ -1055,22 +1044,18 @@ scherzo_press_note (scherzo_t *scherzo, pitch_t pitch, int octave)
 
     if (scherzo->challenge.note) {
        staff = scherzo->challenge.staff;
-    } else if (octave >= 4) {
+    } else if (PITCH_OCTAVE (pitch) >= 4) {
        staff = scherzo->treble;
     } else {
        staff = scherzo->bass;
     }
 
     /* Do nothing if this note is already pressed. */
-    for (i = 0; i < scherzo->notes_pressed.num_notes; i++) {
-       if (scherzo->notes_pressed.notes[i]->pitch == pitch &&
-           scherzo->notes_pressed.notes[i]->octave == octave)
-       {
+    for (i = 0; i < scherzo->notes_pressed.num_notes; i++)
+       if (scherzo->notes_pressed.notes[i]->pitch == pitch)
            return scherzo->notes_pressed.notes[i];
-       }
-    }
 
-    note = score_add_note (staff, pitch, octave, SCORE_DURATION_WHOLE);
+    note = score_add_note (staff, pitch, SCORE_DURATION_WHOLE);
 
     note_group_add_note (&scherzo->notes_pressed, note);
 
@@ -1083,17 +1068,17 @@ scherzo_press_note (scherzo_t *scherzo, pitch_t pitch, int octave)
 }
 
 static void
-scherzo_release_note (scherzo_t *scherzo, pitch_t pitch, int octave)
+scherzo_release_note (scherzo_t *scherzo, pitch_t pitch)
 {
     score_note_t *note;
     int i;
     int found = 0;
-    int target_midi = _pitch_and_octave_to_midi (pitch, octave);
+    int target_midi = _pitch_to_midi (pitch);
     int note_midi;
 
     for (i = scherzo->notes_pressed.num_notes - 1; i >=0; i--) {
        note = scherzo->notes_pressed.notes[i];
-       note_midi = _pitch_and_octave_to_midi (note->pitch, note->octave);
+       note_midi = _pitch_to_midi (note->pitch);
        if (note_midi == target_midi) {
            found = 1;
            if (! scherzo->pedal_pressed)
@@ -1112,23 +1097,13 @@ scherzo_release_note (scherzo_t *scherzo, pitch_t pitch, int octave)
 static score_note_t *
 scherzo_press_note_midi (scherzo_t *scherzo, unsigned char midi_note)
 {
-    pitch_t pitch;
-    int octave;
-
-    _midi_to_pitch_and_octave (midi_note, &pitch, &octave);
-
-    return scherzo_press_note (scherzo, pitch, octave);
+    return scherzo_press_note (scherzo, _midi_to_pitch (midi_note));
 }
 
 static void
 scherzo_release_note_midi (scherzo_t *scherzo, unsigned char midi_note)
 {
-    pitch_t pitch;
-    int octave;
-    _midi_to_pitch_and_octave (midi_note, &pitch, &octave);
-
-    scherzo_release_note (scherzo, pitch, octave);
+    scherzo_release_note (scherzo, _midi_to_pitch (midi_note));
 }
 
 static void
@@ -1152,7 +1127,7 @@ scherzo_release_pedal (scherzo_t *scherzo)
     /* Make new notes in score for all pressed notes. */
     for (i = 0; i < scherzo->notes_pressed.num_notes; i++) {
        note = scherzo->notes_pressed.notes[i];
-       new_note = score_add_note (note->staff, note->pitch, note->octave, note->duration);
+       new_note = score_add_note (note->staff, note->pitch, note->duration);
        scherzo->notes_pressed.notes[i] = new_note;
     }
 
@@ -1177,6 +1152,7 @@ _select_challenge (scherzo_t *scherzo)
     bool_t introduced_unused;
     item_t *item;
     challenge_t *challenge = &scherzo->challenge;
+    pitch_name_t pitch_name;
     pitch_t pitch;
     int octave;
     char *s;
@@ -1210,25 +1186,25 @@ _select_challenge (scherzo_t *scherzo)
 
     switch (*s) {
     case 'C':
-       pitch = PITCH_NATURAL (C);
+       pitch_name = PITCH_NAME_C;
        break;
     case 'D':
-       pitch = PITCH_NATURAL (D);
+       pitch_name = PITCH_NAME_D;
        break;
     case 'E':
-       pitch = PITCH_NATURAL (E);
+       pitch_name = PITCH_NAME_E;
        break;
     case 'F':
-       pitch = PITCH_NATURAL (F);
+       pitch_name = PITCH_NAME_F;
        break;
     case 'G':
-       pitch = PITCH_NATURAL (G);
+       pitch_name = PITCH_NAME_G;
        break;
     case 'A':
-       pitch = PITCH_NATURAL (A);
+       pitch_name = PITCH_NAME_A;
        break;
     case 'B':
-       pitch = PITCH_NATURAL (B);
+       pitch_name = PITCH_NAME_B;
        break;
     default:
        fprintf (stderr, "Malformed pitch name: %s (expected 'A' - 'G')\n", s);
@@ -1243,7 +1219,9 @@ _select_challenge (scherzo_t *scherzo)
 
     octave = *s - '0';
 
-    challenge->note = score_add_note (challenge->staff, pitch, octave,
+    pitch = PITCH (pitch_name, PITCH_ACCIDENTAL_NATURAL, octave);
+
+    challenge->note = score_add_note (challenge->staff, pitch,
                                      SCORE_DURATION_WHOLE);
     challenge->satisfied = 0;
     challenge->mistaken = 0;
@@ -1260,8 +1238,7 @@ _judge_note (scherzo_t *scherzo, score_note_t *note)
        return;
     }
 
-    if (note->pitch == challenge->note->pitch &&
-       note->octave == challenge->note->octave)
+    if (note->pitch == challenge->note->pitch)
     {
        challenge->satisfied = 1;
        score_set_note_color_rgb (note, 18/256., 130/256., 28/256.); /* green */
diff --git a/score.c b/score.c
index e587c2799ed93a6396456b8d929388d56f482a30..0c868c6f4a255b93787533db9cb6a80a6ff85919 100644 (file)
--- a/score.c
+++ b/score.c
@@ -178,9 +178,10 @@ static double
 _score_note_to_line (score_staff_t *staff, score_note_t *note)
 {
     pitch_name_t name = PITCH_NAME (note->pitch);
+    int octave = PITCH_OCTAVE (note->pitch);
     int c_line = _score_clef_c_line (staff->clef);
 
-    return c_line - (name - PITCH_NAME_C) / 2.0 - 3.5 * (note->octave - 4);
+    return c_line - (name - PITCH_NAME_C) / 2.0 - 3.5 * (octave - 4);
 }
 
 /* chord->width is updated as a side effect */
@@ -595,7 +596,6 @@ score_remove_chord (score_chord_t *chord)
 score_note_t *
 score_add_note (score_staff_t *staff,
                pitch_t pitch,
-               int octave,
                score_duration_t duration)
 {
     score_note_t *note;
@@ -606,7 +606,6 @@ score_add_note (score_staff_t *staff,
     for (i = 0; i < staff->num_notes; i++) {
        note = staff->notes[i];
        if (note->pitch == pitch &&
-           note->octave == octave &&
            note->duration == duration)
        {
            return note;
@@ -619,7 +618,6 @@ score_add_note (score_staff_t *staff,
 
     note->staff = staff;
     note->pitch = pitch;
-    note->octave = octave;
     note->duration = duration;
 
     note->color.r = 0.0;
@@ -694,7 +692,6 @@ score_set_note_color_rgb (score_note_t *note,
 score_note_t *
 score_staff_find_note (score_staff_t *staff,
                       pitch_t pitch,
-                      int octave,
                       score_duration_t duration)
 {
     int i;
@@ -702,12 +699,8 @@ score_staff_find_note (score_staff_t *staff,
 
     for (i = 0; i < staff->num_notes; i++) {
        note = staff->notes[i];
-       if (note->pitch == pitch &&
-           note->octave == octave &&
-           note->duration == duration)
-       {
+       if (note->pitch == pitch && note->duration == duration)
            return note;
-       }
     }
 
     return NULL;
diff --git a/score.h b/score.h
index 5dd61887d340da2bbb5ca5420af8dc23bd968bc4..d5391012bb428e26f901a8432535ce797f3c8700 100644 (file)
--- a/score.h
+++ b/score.h
@@ -55,7 +55,6 @@ typedef struct score_note
 {
     score_staff_t *staff;
     pitch_t pitch;
-    int octave;
     score_duration_t duration;
 
     struct {
@@ -109,10 +108,7 @@ score_add_brace (score_t *score, int staves);
 score_staff_t *
 score_add_staff (score_t *score, score_clef_t clef);
 
-/* Add a note to a staff of the given pitch, octave, and duration.
- *
- * Octave numbers are ISO octave numbers [0:8], (so Octave 4 is from
- * middle C to the B above middle C).
+/* Add a note to a staff of the given pitch and duration.
  *
  * Duration values can be symbolic (SCORE_DURATION_WHOLE, _QUARTER,
  * _EIGHTH, etc.) or numerical as simply the denominator (WHOLE=1,
@@ -121,7 +117,6 @@ score_add_staff (score_t *score, score_clef_t clef);
 score_note_t *
 score_add_note (score_staff_t *staff,
                pitch_t pitch,
-               int octave,
                score_duration_t);
 
 /* Add a chord symbol of 'name' to a staff.
@@ -154,7 +149,6 @@ score_set_note_color_rgb (score_note_t *note,
 score_note_t *
 score_staff_find_note (score_staff_t *staff,
                       pitch_t pitch,
-                      int octave,
                       score_duration_t duration);
 
 /* Draw the given score_t onto the given cairo_t.