package com.xenoage.zong.core.music.direction; import static com.xenoage.utils.collections.ArrayUtils.indexOf; import static com.xenoage.zong.core.music.direction.WedgeType.Crescendo; /** * Dynamic values: forte, piano, sforzando and so on. * * These are the same dynamics as supported in MusicXML. * * @author Andreas Wenger */ public enum DynamicValue { p, pp, ppp, pppp, ppppp, pppppp, f, ff, fff, ffff, fffff, ffffff, mp, mf, sf, sfp, sfpp, fp, rf, rfz, sfz, sffz, fz; /** * When this is the start dynamic value of a wedge (crescendo/diminuendo), * the wedge ends by default at the returned value. */ public DynamicValue getWedgeEndValue(WedgeType type) { return getWedgeEndValue(type == Crescendo ? 1 : -1); } /** * When this is the start dynamic value of a diminuendo, * the diminuendo ends by default at the returned value. */ public DynamicValue getDiminuendoEndValue() { return getWedgeEndValue(-1); } /** * Gets the end dynamic of a crescendo (dir = 1) or * diminuendo (dir = -1), when this is the start value. */ private DynamicValue getWedgeEndValue(int dir) { DynamicValue[] wedgeProgress = {pp, p, mf, f, ff}; int index = indexOf(wedgeProgress, round()) + dir; if (index < 0) return pp; else if (index >= wedgeProgress.length) return ff; else return wedgeProgress[index]; } /** * Returns the nearest commonly used dynamic value (pp, p, mf, f, ff) * to this value. */ private DynamicValue round() { switch (this) { case pp: case p: case mf: case f: case ff: return this; //everything lower than pp is treated as pp, //everything higher than ff as ff case ppp: case pppp: case ppppp: case pppppp: return pp; case fff: case ffff: case fffff: case ffffff: return ff; //mp is like mf case mp: return mf; //sXY-values are treated as Y case sf: case rf: case rfz: case sfz:case fz: return f; case sfp: case fp: return p; case sfpp: return pp; case sffz: return ff; } return mf; } }