+typedef uint32_t pitch_t;
+
+#define PITCH_ACCIDENTAL_SHIFT (0)
+#define PITCH_ACCIDENTAL_MASK (0x07 << PITCH_ACCIDENTAL_SHIFT)
+
+#define PITCH_NAME_SHIFT (3)
+#define PITCH_NAME_MASK (0x07 << PITCH_NAME_SHIFT)
+
+#define PITCH_OCTAVE_SHIFT (6)
+#define PITCH_OCTAVE_MASK (0x07 << PITCH_OCTAVE_SHIFT)
+
+#define PITCH_ACCIDENTAL(pitch) \
+ (((pitch) & PITCH_ACCIDENTAL_MASK) >> PITCH_ACCIDENTAL_SHIFT)
+#define PITCH_NAME(pitch) \
+ (((pitch) & PITCH_NAME_MASK) >> PITCH_NAME_SHIFT)
+#define PITCH_OCTAVE(pitch) \
+ (((pitch) & PITCH_OCTAVE_MASK) >> PITCH_OCTAVE_SHIFT)
+
+#define PITCH(name, accidental, octave) \
+ (((octave) << PITCH_OCTAVE_SHIFT) | \
+ ((name) << PITCH_NAME_SHIFT) | \
+ ((accidental) << PITCH_ACCIDENTAL_SHIFT))
+
+#define PITCH_LITERAL(literal_name, literal_accidental, octave) \
+ PITCH(PITCH_NAME_##literal_name, \
+ PITCH_ACCIDENTAL_##literal_accidental, \
+ octave)
+
+#define PITCH_NATURAL(literal_name, octave) \
+ 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_LITERAL(literal_name, literal_accidental) \
+ PITCH_LITERAL(literal_name, literal_accidental, 0)
+
+#define PITCH_NOT_A_PITCH ((pitch_t) -1)