* along with this program. If not, see http://www.gnu.org/licenses/ .
*/
-#define PITCH_ACCIDENTAL_MASK 0x07
-#define PITCH_ACCIDENTAL_SHIFT 0
+#include <stdint.h>
+
+#ifndef PITCH_H
+#define PITCH_H
+
+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)
typedef enum pitch_accidental
{
PITCH_ACCIDENTAL_DOUBLE_SHARP
} pitch_accidental_t;
-#define PITCH_ACCIDENTAL(pitch) (((pitch) & PITCH_ACCIDENTAL_MASK) >> PITCH_ACCIDENTAL_SHIFT)
-
-#define PITCH_NAME_MASK 0x38
-#define PITCH_NAME_SHIFT 3
-
typedef enum pitch_name
{
PITCH_NAME_C,
PITCH_NAME_B,
} pitch_name_t;
-#define PITCH_NAME(pitch) (((pitch) & PITCH_NAME_MASK) >> PITCH_NAME_SHIFT)
+/* Octave numbers are ISO octave numbers [0:8], (so Octave 4 is from
+ * middle C to the B above middle C).
+ */
-#define PITCH(name, accidental) (((name) << PITCH_NAME_SHIFT) | (accidental))
+/* Get a string representation of a pitch_t value.
+ *
+ * Note: The returned value is static to the pithc_string function and
+ * may be modified by future calls to pitch_string. So the caller
+ * should copy the value if needed. */
+const char *
+pitch_string (pitch_t pitch);
-#define PITCH_LITERAL(literal_name, literal_accidental) PITCH(PITCH_NAME_##literal_name, PITCH_ACCIDENTAL_##literal_accidental)
+/* Return a new pitch, a number of octaves above 'pitch'
+ *
+ * Note: Maximum octave value is 8. A pitch with octave 8 will not be
+ * raised.
+ */
+pitch_t
+pitch_raise_by_octaves (pitch_t pitch, int octaves);
-typedef enum pitch
-{
- PITCH_Cff = PITCH_LITERAL (C, DOUBLE_FLAT),
- PITCH_Cf = PITCH_LITERAL (C, FLAT),
- PITCH_C = PITCH_LITERAL (C, NATURAL),
- PITCH_Cs = PITCH_LITERAL (C, SHARP),
- PITCH_Css = PITCH_LITERAL (C, DOUBLE_SHARP),
-
- PITCH_Dff = PITCH_LITERAL (D, DOUBLE_FLAT),
- PITCH_Df = PITCH_LITERAL (D, FLAT),
- PITCH_D = PITCH_LITERAL (D, NATURAL),
- PITCH_Ds = PITCH_LITERAL (D, SHARP),
- PITCH_Dss = PITCH_LITERAL (D, DOUBLE_SHARP),
-
- PITCH_Eff = PITCH_LITERAL (E, DOUBLE_FLAT),
- PITCH_Ef = PITCH_LITERAL (E, FLAT),
- PITCH_E = PITCH_LITERAL (E, NATURAL),
- PITCH_Es = PITCH_LITERAL (E, SHARP),
- PITCH_Ess = PITCH_LITERAL (E, DOUBLE_SHARP),
-
- PITCH_Fff = PITCH_LITERAL (F, DOUBLE_FLAT),
- PITCH_Ff = PITCH_LITERAL (F, FLAT),
- PITCH_F = PITCH_LITERAL (F, NATURAL),
- PITCH_Fs = PITCH_LITERAL (F, SHARP),
- PITCH_Fss = PITCH_LITERAL (F, DOUBLE_SHARP),
-
- PITCH_Gff = PITCH_LITERAL (G, DOUBLE_FLAT),
- PITCH_Gf = PITCH_LITERAL (G, FLAT),
- PITCH_G = PITCH_LITERAL (G, NATURAL),
- PITCH_Gs = PITCH_LITERAL (G, SHARP),
- PITCH_Gss = PITCH_LITERAL (G, DOUBLE_SHARP),
-
- PITCH_Aff = PITCH_LITERAL (A, DOUBLE_FLAT),
- PITCH_Af = PITCH_LITERAL (A, FLAT),
- PITCH_A = PITCH_LITERAL (A, NATURAL),
- PITCH_As = PITCH_LITERAL (A, SHARP),
- PITCH_Ass = PITCH_LITERAL (A, DOUBLE_SHARP),
-
- PITCH_Bff = PITCH_LITERAL (B, DOUBLE_FLAT),
- PITCH_Bf = PITCH_LITERAL (B, FLAT),
- PITCH_B = PITCH_LITERAL (B, NATURAL),
- PITCH_Bs = PITCH_LITERAL (B, SHARP),
- PITCH_Bss = PITCH_LITERAL (B, DOUBLE_SHARP)
-} pitch_t;
+/* Return a new pitch, a number of octaves below 'pitch'
+ *
+ * Note: Minimum octave value is 9. A pitch with octave 8 will not be
+ * lowered.
+ */
+pitch_t
+pitch_lower_by_octaves (pitch_t pitch, int octaves);
+
+#endif /* PITCH_H */