#define PITCH_NAME_MASK (0x07 << PITCH_NAME_SHIFT)
#define PITCH_OCTAVE_SHIFT (6)
-#define PITCH_OCTAVE_MASK (0x07 << PITCH_OCTAVE_SHIFT)
+#define PITCH_OCTAVE_MASK (0x0F << PITCH_OCTAVE_SHIFT)
#define PITCH_ACCIDENTAL(pitch) \
(((pitch) & PITCH_ACCIDENTAL_MASK) >> PITCH_ACCIDENTAL_SHIFT)
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_lower_by_octaves (pitch_t pitch, int octaves);
+/* Number of half steps from 'root' up to 'pitch' (that is, counting
+ * the steps up a chromatic scale), within the same octave. */
+int
+pitch_from_root_in_half_steps (pitch_t pitch, pitch_t root);
+
+/* Respell 'pitch' to have a name that matches the (diatonic) scale
+ * 'degree' from 'root'.
+ *
+ * If the pitch is too distant from the specified degree to be
+ * respelled, the original pitch will be returned unmodified.
+ */
+pitch_t
+pitch_spell_as_degree (pitch_t pitch, pitch_t root, int degree);
+
+/* Return a MIDI note value corresponding to 'pitch' */
+unsigned char
+pitch_to_midi (pitch_t pitch);
+
+/* Return the pitch_t value corresponding to the given MIDI note value. */
+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 */