/**
Copyright (C) <2015> <coolAlias>
This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such,
you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package zeldaswordskills.util;
/**
*
* 12 notes per octave for 2 octaves, starting on A1 (natural) up to G2-sharp,
* with an extra flat A1 as the first value to round out the control-scheme.
*
* Keep in mind that for the standard music GUI used by the ocarina, only notes
* from B1 natural to F2 natural are playable.
*
*/
public enum SongNote
{
A1_FLAT(Note.A, Pitch.FLAT),
A1(Note.A, Pitch.NATURAL),
B1_FLAT(Note.B, Pitch.FLAT),
B1(Note.B, Pitch.NATURAL),
C1(Note.C, Pitch.NATURAL),
C1_SHARP(Note.C, Pitch.SHARP),
D1(Note.D, Pitch.NATURAL),
D1_SHARP(Note.D, Pitch.SHARP),
E1(Note.E, Pitch.NATURAL),
F1(Note.F, Pitch.NATURAL),
F1_SHARP(Note.F, Pitch.SHARP),
G1(Note.G, Pitch.NATURAL),
G1_SHARP(Note.G, Pitch.SHARP),
A2(Note.A, Pitch.NATURAL),
B2_FLAT(Note.B, Pitch.FLAT),
B2(Note.B, Pitch.NATURAL),
C2(Note.C, Pitch.NATURAL),
C2_SHARP(Note.C, Pitch.SHARP),
D2(Note.D, Pitch.NATURAL),
D2_SHARP(Note.D, Pitch.SHARP),
E2(Note.E, Pitch.NATURAL),
F2(Note.F, Pitch.NATURAL),
F2_SHARP(Note.F, Pitch.SHARP),
G2(Note.G, Pitch.NATURAL),
G2_SHARP(Note.G, Pitch.SHARP);
/** The corresponding musical note, e.g. C, G, etc. */
public final Note note;
/** The pitch of the note, i.e. flat, sharp, or natural */
public final Pitch pitch;
private SongNote(Note note, Pitch pitch) {
this.note = note;
this.pitch = pitch;
}
@Override
public String toString() {
return note.toString() + getOctave() + "-" + pitch.toString();
}
/**
* Returns the octave of this note, determined by ordinal position
* Note that the main scale is considered octave 1, with lower or
* higher octaves relative to that value.
*/
public int getOctave() {
return ((ordinal() - 1) / 12) + 1;
}
public boolean isFlat() {
return pitch == Pitch.FLAT;
}
public boolean isSharp() {
return pitch == Pitch.SHARP;
}
/**
* Returns a SongNote from a PlayableNote and a modifier
* @param note Any {@link PlayableNote}
* @param modifier Number of half-steps to modify the note, in either direction
* (negative lowers pitch, positive raises pitch, 0 stays the same).
* Valid values range from -3 to 3, inclusive.
* @return Corresponding SongNote based on the note played and the modifier
* Null should be impossible, but check anyway to be safe
*/
public static SongNote getNote(PlayableNote note, int modifier) {
modifier = (modifier < -3 ? -3 : (modifier > 3 ? 3 : modifier));
int i = note.note.ordinal() + modifier;
return (i < 0 || i > SongNote.values().length ? null : SongNote.values()[i]);
}
/** Playable notes, with their corresponding {@link SongNote} */
public static enum PlayableNote {
D1(SongNote.D1),
F1(SongNote.F1),
A2(SongNote.A2),
B2(SongNote.B2),
D2(SongNote.D2);
protected final SongNote note;
private PlayableNote(SongNote note) {
this.note = note;
}
@Override
public String toString() {
return this.name();
}
/**
* Returns the ordinal position of PlayableNote corresponding to the note,
* or PlayableNote.values().length if the note is not a PlayableNote.
* Used for getting the texture y position.
*/
public static int getOrdinalFromNote(SongNote note) {
for (PlayableNote playable : PlayableNote.values()) {
if (playable.note == note) {
return playable.ordinal();
}
}
return PlayableNote.values().length;
}
}
public static enum Pitch {
FLAT, NATURAL, SHARP;
@Override
public String toString() {
return this.name().toLowerCase();
}
}
/** Scale starts on A, meaning the lowest possible is A1-flat and the highest is A2-sharp */
public static enum Note {
A, B, C, D, E, F, G;
@Override
public String toString() {
return this.name();
}
/** Returns the previous note (previous from A is G) */
public Note prev() {
return (this == A ? G : Note.values()[ordinal() - 1]);
}
/** Returns the next note (next from G is A) */
public Note next() {
return (this == G ? A : Note.values()[ordinal() + 1]);
}
}
}