/* -*- c-basic-offset: 2; indent-tabs-mode: nil; -*- */ /* * FreeDots -- MusicXML to braille music transcription * * Copyright 2008-2010 Mario Lang All Rights Reserved. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This code 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 (a copy is included in the LICENSE.txt file that * accompanied this code). * * You should have received a copy of the GNU General Public License * along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * This file is maintained by Mario Lang <mlang@delysid.org>. */ package freedots.music; /** * An abstract representation of pitch with step, alter and octave values. */ public abstract class AbstractPitch implements Comparable<AbstractPitch> { /** * @return the step (a value from 0 to 6) */ public abstract int getStep(); /** * @return alteration (usually between -2 and 2) */ public abstract int getAlter(); /** * @return the octave */ public abstract int getOctave(); public int getMIDIPitch() { int midiPitch = (getOctave()+1) * CHROMATIC_STEPS + STEP_TO_CHROMATIC[getStep()] + getAlter(); return midiPitch; } @Override public final boolean equals(Object object) { if (object instanceof AbstractPitch) { AbstractPitch other = (AbstractPitch)object; if (this.getStep() == other.getStep()) { if (this.getAlter() == other.getAlter()) { if (this.getOctave() == other.getOctave()) return true; } } } return false; } public final int diatonicDifference(AbstractPitch other) { return ((this.getOctave()*STEPS) + this.getStep()) - ((other.getOctave()*STEPS) + other.getStep()); } public int compareTo(AbstractPitch other) { int diatonicDifference = diatonicDifference(other); if (diatonicDifference != 0) return diatonicDifference; else { final boolean flatter = getAlter() < other.getAlter(); final boolean sharper = getAlter() > other.getAlter(); return flatter ? -1 : sharper ? 1 : 0; } } public final AbstractPitch nextStep(AccidentalContext accidentalContext) { int octave = getOctave(); int step = getStep(); double alter = 0; if (step < STEPS-1) { step += 1; } else { octave += 1; step = 0; } alter = accidentalContext.getAlter(octave, step); return new TemporaryPitch(octave, step, (int)alter); } public AbstractPitch previousStep(AccidentalContext accidentalContext) { int octave = getOctave(); int step = getStep(); double alter = 0; if (step > 0) step -= 1; else { octave -= 1; step = STEPS-1; } alter = accidentalContext.getAlter(octave, step); return new TemporaryPitch(octave, step, (int)alter); } class TemporaryPitch extends AbstractPitch { private int octave, step, alter; TemporaryPitch(final int octave, final int step, final int alter) { this.octave = octave; this.step = step; this.alter = alter; } public int getOctave() { return octave; } public int getStep() { return step; } public int getAlter() { return alter; } } @Override public final String toString() { final String[] stepNames = new String[] {"C", "D", "E", "F", "G", "A", "B"}; return stepNames[getStep()]+getOctave()+" ("+getAlter()+")"; } private static final int STEPS = 7; private static final int CHROMATIC_STEPS = 12; private static final int[] STEP_TO_CHROMATIC = new int[] { 0, 2, 4, 5, 7, 9, 11 }; }