1 /* scherzo - Music notation training
3 * pitch.c - Common structures and functions for pitches, etc.
5 * Copyright © 2013 Carl Worth
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see http://www.gnu.org/licenses/ .
26 pitch_string (pitch_t pitch)
28 static char double_flat[] = "X𝄫";
29 static char flat[] = "X♭";
30 static char natural[] = "X";
31 static char sharp[] = "X♯";
32 static char double_sharp[] = "X𝄪";
35 switch (PITCH_ACCIDENTAL (pitch)) {
36 case PITCH_ACCIDENTAL_DOUBLE_FLAT:
39 case PITCH_ACCIDENTAL_FLAT:
42 case PITCH_ACCIDENTAL_NATURAL:
45 case PITCH_ACCIDENTAL_SHARP:
48 case PITCH_ACCIDENTAL_DOUBLE_SHARP:
53 switch (PITCH_NAME (pitch)) {
81 pitch_raise_by_octaves (pitch_t pitch, int octaves)
83 int new_octave = PITCH_OCTAVE (pitch) + octaves;
88 return PITCH (PITCH_NAME (pitch), PITCH_ACCIDENTAL (pitch), new_octave);
92 pitch_lower_by_octaves (pitch_t pitch, int octaves)
94 int new_octave = PITCH_OCTAVE (pitch) - octaves;
99 return PITCH (PITCH_NAME (pitch), PITCH_ACCIDENTAL (pitch), new_octave);
102 /* Number of half steps from 'root' up to 'pitch' (that is, counting
103 * the steps up a chromatic scale), within the same octave. */
105 pitch_from_root_in_half_steps (pitch_t pitch, pitch_t root)
107 int root_midi = pitch_to_midi (root);
108 int pitch_midi = pitch_to_midi (pitch);
110 while (pitch_midi < root_midi)
113 return (pitch_midi - root_midi) % 12;
117 pitch_spell_as_degree (pitch_t pitch, pitch_t root, int degree)
119 pitch_name_t name = PITCH_NAME (pitch);
120 pitch_accidental_t accidental = PITCH_ACCIDENTAL (pitch);
121 int octave = PITCH_OCTAVE (pitch);
122 int degree_zero_based = (degree - 1) % 7;
125 int note_degree_zero_based = name - PITCH_NAME (root);
126 if (note_degree_zero_based < 0)
127 note_degree_zero_based += 7;
129 if (note_degree_zero_based == degree_zero_based)
132 degree_delta = note_degree_zero_based - degree_zero_based;
133 if (degree_delta > 3)
134 degree_delta = - (7 - degree_delta);
135 if (degree_delta < -3)
136 degree_delta = - (-7 - degree_delta);
138 /* Cannot re-spell pitch more than one degree away. Return
140 if (abs (degree_delta) != 1)
143 if (degree_delta == -1) {
144 if (name == PITCH_NAME_B) {
165 if (degree_delta == +1) {
166 if (name == PITCH_NAME_C) {
186 /* Also cannot use accidentals to respell more than two half steps
187 * either direction. Return original pitch. */
188 if (accidental < 0 || accidental > PITCH_ACCIDENTAL_DOUBLE_SHARP)
191 return PITCH (name, accidental, octave);
194 /* Return a MIDI note value corresponding to 'pitch' */
196 pitch_to_midi (pitch_t pitch)
198 int octave = PITCH_OCTAVE (pitch);
199 unsigned char midi_note = 12 * (octave + 1);
201 switch (PITCH_NAME (pitch)) {
224 switch (PITCH_ACCIDENTAL (pitch)) {
225 case PITCH_ACCIDENTAL_DOUBLE_FLAT:
228 case PITCH_ACCIDENTAL_FLAT:
231 case PITCH_ACCIDENTAL_NATURAL:
233 case PITCH_ACCIDENTAL_SHARP:
236 case PITCH_ACCIDENTAL_DOUBLE_SHARP:
244 /* Return the pitch_t value corresponding to the given MIDI note value. */
246 pitch_from_midi (unsigned char midi_note)
248 int octave = octave = midi_note / 12 - 1;
250 switch (midi_note % 12)
254 return PITCH_LITERAL (C, NATURAL, octave);
257 return PITCH_LITERAL (C, SHARP, octave);
260 return PITCH_LITERAL (D, NATURAL, octave);
263 return PITCH_LITERAL (D, SHARP, octave);
266 return PITCH_LITERAL (E, NATURAL, octave);
269 return PITCH_LITERAL (F, NATURAL, octave);
272 return PITCH_LITERAL (F, SHARP, octave);
275 return PITCH_LITERAL (G, NATURAL, octave);
278 return PITCH_LITERAL (G, SHARP, octave);
281 return PITCH_LITERAL (A, NATURAL, octave);
284 return PITCH_LITERAL (A, SHARP, octave);
287 return PITCH_LITERAL (B, NATURAL, octave);