]> git.cworth.org Git - scherzo/blobdiff - scherzo-key.c
Fix key signature setting to accept an enharmonic pitch
[scherzo] / scherzo-key.c
index 18cd261f6d5823e6727978b19397a415af23c592..8fea502de8044cc8b6fad289f3838c5b29260b78 100644 (file)
@@ -19,6 +19,8 @@
  */
 
 #include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 #include "scherzo-key.h"
 
@@ -29,17 +31,6 @@ scherzo_key_init (scherzo_key_t *key, pitch_t pitch)
 {
     int i;
 
-    pitch_t sharp_keys[] = {
-       PITCH_CLASS_LITERAL (C, NATURAL),
-       PITCH_CLASS_LITERAL (G, NATURAL),
-       PITCH_CLASS_LITERAL (D, NATURAL),
-       PITCH_CLASS_LITERAL (A, NATURAL),
-       PITCH_CLASS_LITERAL (E, NATURAL),
-       PITCH_CLASS_LITERAL (B, NATURAL),
-       PITCH_CLASS_LITERAL (F, SHARP),
-       PITCH_CLASS_LITERAL (C, SHARP),
-    };
-
     pitch_t flat_keys[] = {
        PITCH_CLASS_LITERAL (C, NATURAL),
        PITCH_CLASS_LITERAL (F, NATURAL),
@@ -51,17 +42,66 @@ scherzo_key_init (scherzo_key_t *key, pitch_t pitch)
        PITCH_CLASS_LITERAL (C, FLAT)
     };
 
-    key->pitch = PITCH_CLASS (PITCH_NAME (pitch), PITCH_ACCIDENTAL (pitch));
+    pitch_t sharp_keys[] = {
+       PITCH_CLASS_LITERAL (C, NATURAL),
+       PITCH_CLASS_LITERAL (G, NATURAL),
+       PITCH_CLASS_LITERAL (D, NATURAL),
+       PITCH_CLASS_LITERAL (A, NATURAL),
+       PITCH_CLASS_LITERAL (E, NATURAL),
+       PITCH_CLASS_LITERAL (B, NATURAL),
+       PITCH_CLASS_LITERAL (F, SHARP),
+       PITCH_CLASS_LITERAL (C, SHARP),
+    };
+
+    /* Remove octave from 'pitch' */
+    pitch = PITCH_CLASS (pitch);
 
     key->num_sharps = 0;
-    for (i = 0; i < ARRAY_SIZE (sharp_keys); i++)
-       if (sharp_keys[i] == key->pitch)
+    key->num_flats = 0;
+
+    /* First, look for a key that exactly matches the specified pitch. */
+    for (i = 0; i < ARRAY_SIZE (flat_keys); i++) {
+       if (flat_keys[i] == pitch) {
+           key->pitch = flat_keys[i];
+           key->num_flats = i;
+           return;
+       }
+    }
+
+    for (i = 0; i < ARRAY_SIZE (sharp_keys); i++) {
+       if (sharp_keys[i] == pitch) {
+           key->pitch = sharp_keys[i];
            key->num_sharps = i;
+           return;
+       }
+    }
 
-    key->num_flats = 0;
-    for (i = 0; i < ARRAY_SIZE (flat_keys); i++)
-       if (flat_keys[i] == key->pitch)
+    /* Second, if we haven't found a key, look for something enharmonic. */
+    for (i = 0; i < ARRAY_SIZE (flat_keys); i++) {
+       if (pitch_enharmonic_to (flat_keys[i], pitch)) {
+           key->pitch = flat_keys[i];
            key->num_flats = i;
+           return;
+       }
+    }
+
+    for (i = 0; i < ARRAY_SIZE (sharp_keys); i++) {
+       if (pitch_enharmonic_to (sharp_keys[i], pitch)) {
+           key->pitch = sharp_keys[i];
+           key->num_sharps = i;
+           return;
+       }
+    }
+
+    /* The pitch_enharmonic_to function won't catch this wraparound. */
+    if (pitch == PITCH_CLASS_LITERAL (B, SHARP)) {
+       key->pitch = PITCH_CLASS_LITERAL (C, NATURAL);
+       return;
+    }
+
+    fprintf (stderr, "Interal error: Failed to find a key for %s.\n",
+            pitch_string (pitch));
+    exit (1);
 }
 
 bool