/* -*- 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.braille; import java.util.Iterator; import java.util.logging.Logger; import freedots.math.Fraction; import freedots.music.Accidental; import freedots.music.AugmentedPowerOfTwo; import freedots.musicxml.Harmony; /** Braille representation of a harmony chord. */ public class BrailleHarmony extends BrailleList { private static final Logger LOG = Logger.getLogger(BrailleHarmony.class.getName()); private final Harmony harmony; private final boolean withStems; public BrailleHarmony(final Harmony harmony, final boolean withStems, final Fraction duration) { this.harmony = harmony; this.withStems = withStems; for (Harmony.HarmonyChord chord: harmony.getChords()) { final String kind = chord.getKind(); if ("none".equals(kind)) { add(new UpcaseSign()); add(new Text("nc")); } else { add(new UpcaseSign()); add(new StepLetterSign(chord.getRootStep())); addAccidentalFromAlter(chord.getRootAlter()); if ("major".equals(kind)) ; else if ("minor".equals(kind)) add(new MinorSign()); else if ("augmented".equals(kind)) { add(new AccidentalSign(Accidental.SHARP)); add(new UpperNumber(5)); } else if ("diminished".equals(kind)) add(new Text("dim")); else if ("dominant".equals(kind)) add(new UpperNumber(7)); else if ("suspended-second".equals(kind)) { add(new Text("sus")); add(new UpperNumber(2)); } else if ("suspended-fourth".equals(kind)) { add(new Text("sus")); add(new UpperNumber(4)); } else if ("major-sixth".equals(kind)) add(new UpperNumber(6)); else if ("major-seventh".equals(kind)) { add(new Text("maj")); add(new UpperNumber(7)); } else if ("minor-seventh".equals(kind)) { add(new MinorSign()); add(new UpperNumber(7)); } else if ("diminished-seventh".equals(kind)) { add(new Text("dim")); add(new UpperNumber(7)); } else if ("augmented-seventh".equals(kind)) { add(new AccidentalSign(Accidental.SHARP)); add(new UpperNumber(5)); add(new UpperNumber(7)); } else if ("major-ninth".equals(kind)) { add(new Text("maj")); add(new UpperNumber(9)); } else if ("minor-ninth".equals(kind)) { add(new MinorSign()); add(new UpperNumber(9)); } else if ("dominant-ninth".equals(kind)) add(new UpperNumber(9)); else if ("major-11th".equals(kind)) { add(new Text("maj")); add(new UpperNumber(11)); } else if ("minor-11th".equals(kind)) { add(new MinorSign()); add(new UpperNumber(11)); } else if ("dominant-11th".equals(kind)) add(new UpperNumber(11)); else if ("dominant-13th".equals(kind)) add(new UpperNumber(13)); else LOG.warning("Unhandled harmony-chord kind '"+kind+"'"); for (Harmony.HarmonyChord.Degree degree: chord.getAlterations()) { addAccidentalFromAlter(degree.getAlter()); add(new UpperNumber(degree.getValue())); } if (chord.hasBass()) { add(new SlashSign()); add(new StepLetterSign(chord.getBassStep())); addAccidentalFromAlter(chord.getBassAlter()); } } } if (withStems && duration != null) { Iterator<AugmentedPowerOfTwo> iterator = AugmentedPowerOfTwo.decompose(duration, AugmentedPowerOfTwo.SEMIBREVE) .iterator(); while (iterator.hasNext()) { final AugmentedPowerOfTwo v = iterator.next(); switch (v.getPower()) { case 0: add(new WholeStemSign()); break; case -1: add(new HalfStemSign()); break; case -2: add(new QuarterStemSign()); break; case -3: add(new EighthStemSign()); break; case -4: add(new SixteenthStemSign()); break; case -5: add(new ThirtysecondthStemSign()); break; default: LOG.warning("Unmapped power of two: " + v); } for (int i = 0; i < v.dots(); i++) add(new Dot()); if (iterator.hasNext()) add(new SlurSign()); } } } static class UpcaseSign extends Sign { UpcaseSign() { super(braille(46)); } public String getDescription() { return "Upper case sign"; } } static class StepLetterSign extends Sign { StepLetterSign(final int step) { super(getSign(step)); } public String getDescription() { return "Symbol indicating a certain root step"; } private static String getSign(final int step) { return ENGLISH_STEP_LETTERS[step]; } private final static String[] ENGLISH_STEP_LETTERS = { braille(14), braille(145), braille(15), braille(124), braille(1245), braille(1), braille(12) }; } static class MinorSign extends Sign { MinorSign() { super(braille(134)); } public String getDescription() { return "Indicates this chord is minor"; } } static class SlashSign extends Sign { SlashSign() { super(braille(5, 2)); } public String getDescription() { return "A slash indicating that a bass note follows"; } } private void addAccidentalFromAlter(final float alter) { if (alter == 0) return; add(new AccidentalSign(Accidental.fromAlter(alter))); } static class StemSign extends Sign { StemSign(final String sign) { super(sign); } public String getDescription() { return "Indicates a certain durational value"; } } static class WholeStemSign extends StemSign { WholeStemSign() { super(braille(456, 3)); } } static class HalfStemSign extends StemSign { HalfStemSign() { super(braille(456, 13)); } } static class QuarterStemSign extends StemSign { QuarterStemSign() { super(braille(456, 1)); } } static class EighthStemSign extends StemSign { EighthStemSign() { super(braille(456, 12)); } } static class SixteenthStemSign extends StemSign { SixteenthStemSign() { super(braille(456, 123)); } } static class ThirtysecondthStemSign extends StemSign { ThirtysecondthStemSign() { super(braille(456, 2)); } } }