*/
#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "scherzo-key.h"
{
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 (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
else
return false;
}
+
+pitch_t
+scherzo_key_spell_pitch (scherzo_key_t *key, pitch_t pitch)
+{
+ pitch_t root = key->pitch;
+ int half_steps = pitch_from_root_in_half_steps (pitch, root);
+ pitch_name_t new_pitch_name;
+ int i;
+ int half_steps_per_degree[] = {
+ 0, 2, 4, 5, 7, 9, 11
+ };
+
+ for (i = 0; i < ARRAY_SIZE (half_steps_per_degree); i++)
+ if (half_steps_per_degree[i] == half_steps)
+ goto WITHIN_SCALE;
+
+ return pitch;
+
+WITHIN_SCALE:
+ new_pitch_name = (PITCH_NAME (root) + i) % 7;
+
+ /* Original pitch is spelled correctly. Return it as is. */
+ if (new_pitch_name == PITCH_NAME (pitch))
+ return pitch;
+
+ return pitch_spell_as_degree (pitch, root, i + 1);
+}