]> git.cworth.org Git - scherzo/blobdiff - scherzo-key.c
Move key-signature code to new scherzo-key.c and scherzo-key.h
[scherzo] / scherzo-key.c
diff --git a/scherzo-key.c b/scherzo-key.c
new file mode 100644 (file)
index 0000000..67d2c1e
--- /dev/null
@@ -0,0 +1,137 @@
+/* scherzo - Music notation training
+ *
+ *     key.c - Common structures and functions for keys
+ *
+ * Copyright © 2013 Carl Worth
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see http://www.gnu.org/licenses/ .
+ */
+
+#include <stdbool.h>
+
+#include "scherzo-key.h"
+
+#define ARRAY_SIZE(arr) ((int) (sizeof(arr) / sizeof(arr[0])))
+
+void
+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),
+       PITCH_CLASS_LITERAL (B, FLAT),
+       PITCH_CLASS_LITERAL (E, FLAT),
+       PITCH_CLASS_LITERAL (A, FLAT),
+       PITCH_CLASS_LITERAL (D, FLAT),
+       PITCH_CLASS_LITERAL (G, FLAT),
+       PITCH_CLASS_LITERAL (C, FLAT)
+    };
+
+    key->pitch = PITCH_CLASS (PITCH_NAME (pitch), PITCH_ACCIDENTAL (pitch));
+
+    key->num_sharps = 0;
+    for (i = 0; i < ARRAY_SIZE (sharp_keys); i++)
+       if (sharp_keys[i] == key->pitch)
+           key->num_sharps = i;
+
+    key->num_flats = 0;
+    for (i = 0; i < ARRAY_SIZE (flat_keys); i++)
+       if (flat_keys[i] == key->pitch)
+           key->num_flats = i;
+}
+
+bool
+scherzo_key_contains_pitch (scherzo_key_t *key, pitch_t pitch)
+{
+    pitch_accidental_t accidental = PITCH_ACCIDENTAL (pitch);
+    int i;
+
+    pitch_name_t sharps_order[] = {
+       PITCH_NAME_F,
+       PITCH_NAME_C,
+       PITCH_NAME_G,
+       PITCH_NAME_D,
+       PITCH_NAME_A,
+       PITCH_NAME_E,
+       PITCH_NAME_B
+    };
+
+    pitch_name_t flats_order[] = {
+       PITCH_NAME_B,
+       PITCH_NAME_E,
+       PITCH_NAME_A,
+       PITCH_NAME_D,
+       PITCH_NAME_G,
+       PITCH_NAME_C,
+       PITCH_NAME_F
+    };
+
+    if (accidental == PITCH_ACCIDENTAL_DOUBLE_SHARP ||
+       accidental == PITCH_ACCIDENTAL_DOUBLE_FLAT)
+    {
+       return false;
+    }
+
+    if (key->num_sharps) {
+       if (accidental == PITCH_ACCIDENTAL_FLAT)
+           return false;
+       for (i = 0; i < key->num_sharps; i++) {
+           if (sharps_order[i] == PITCH_NAME (pitch)) {
+               if (accidental == PITCH_ACCIDENTAL_SHARP)
+                   return true;
+               else
+                   return false;
+           }
+       }
+       if (accidental == PITCH_ACCIDENTAL_SHARP)
+           return false;
+       else
+           return true;
+    }
+
+    if (key->num_flats) {
+       if (accidental == PITCH_ACCIDENTAL_SHARP)
+           return false;
+       for (i = 0; i < key->num_flats; i++) {
+           if (flats_order[i] == PITCH_NAME (pitch)) {
+               if (accidental == PITCH_ACCIDENTAL_FLAT)
+                   return true;
+               else
+                   return false;
+           }
+       }
+       if (accidental == PITCH_ACCIDENTAL_FLAT)
+           return false;
+       else
+           return true;
+    }
+
+    if (accidental == PITCH_ACCIDENTAL_NATURAL)
+       return true;
+    else
+       return false;
+}