PITCH_LITERAL(literal_name, NATURAL, octave)
/* PITCH_CLASS is useful for comparing pitches while ignoring any octave. */
-#define PITCH_CLASS(name, accidental) PITCH(name, accidental, 0)
+#define PITCH_CLASS(pitch) PITCH(PITCH_NAME(pitch), PITCH_ACCIDENTAL(pitch), 0)
#define PITCH_CLASS_LITERAL(literal_name, literal_accidental) \
PITCH_LITERAL(literal_name, literal_accidental, 0)
pitch_t
pitch_from_midi (unsigned char midi_note);
+/* Return true if 'a' and 'b' sound identical, (even if spelled differently)
+ *
+ * This comparison considers octaves as significant. So Bb and A# in
+ * the same octave are considered enharmonic, but Bb and A# in
+ * different octaves are not. */
+int
+pitch_enharmonic_to (pitch_t a, pitch_t b);
+
#endif /* PITCH_H */
*/
#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
return FALSE;
}
-/* Return true if 'a' and 'b' sound identical, (even if spelled differently)
- *
- * This comparison considers octaves as significant. So Bb and A# in
- * the same octave are considered enharmonic, but Bb and A# in
- * different octaves are not. */
-static int
-_pitches_are_enharmonic (pitch_t a, pitch_t b)
-{
- return pitch_to_midi (a) == pitch_to_midi (b);
-}
-
/* Determine a chord name (if any) from the current notes pressed */
typedef struct analyzed_pitch {
int i;
for (i = 0; i < group->num_pitches; i++)
- if (_pitches_are_enharmonic (group->pitches[i], pitch))
+ if (pitch_enharmonic_to (group->pitches[i], pitch))
pitch_group_remove_pitch_at (group, i);
}