/* -*- 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.transcription; import java.util.ArrayList; import java.util.logging.Logger; import freedots.braille.BrailleKeySignature; import freedots.braille.BrailleList; import freedots.braille.BrailleSequence; import freedots.braille.BrailleTimeSignature; import freedots.braille.Dot; import freedots.braille.LeftHandPart; import freedots.braille.RightHandPart; import freedots.braille.Sign; import freedots.braille.SoloPart; import freedots.braille.Space; import freedots.braille.UpperDigits; import freedots.Options; import freedots.music.EndBar; import freedots.music.Event; import freedots.music.KeySignature; import freedots.music.MusicList; import freedots.music.Staff; import freedots.music.StartBar; import freedots.music.TimeSignature; import freedots.musicxml.Part; import freedots.musicxml.Score; /** Transcription in bar over bar format. */ class BarOverBar implements Strategy { private static final Logger LOG = Logger.getLogger(BarOverBar.class.getName()); private Transcriber transcriber; private Options options = null; private BrailleStaves brailleStaves = new BrailleStaves(); private KeySignature initialKeySignature = null; private TimeSignature initialTimeSignature = null; /** Run the format specific part of transcription. */ public void transcribe(Transcriber transcriber) { this.transcriber = transcriber; options = transcriber.getOptions(); createMeasuresInBrailleStaves(transcriber.getScore()); if (initialKeySignature != null && initialTimeSignature != null) { transcriber.printString(new BrailleKeySignature(initialKeySignature)); transcriber.printString(new BrailleTimeSignature(initialTimeSignature)); transcriber.newLine(); } int paragraph = 1; int startIndex = 0; while (startIndex < brailleStaves.getMeasureCount()) { BrailleSequence paragraphNumber = new UpperDigits(paragraph); final int indent = paragraphNumber.length() + 1; int endIndex = startIndex + 1; while (endIndex <= brailleStaves.getMeasureCount() && (brailleStaves.maxLength(startIndex, endIndex)+indent < transcriber.getRemainingColumns())) { endIndex++; } if (endIndex > startIndex + 1) endIndex--; /* Header? */ for (int staffIndex = 0; staffIndex < brailleStaves.size(); staffIndex++) { for (int i = startIndex; i < endIndex; i++) { int columnWidth = brailleStaves.maxLengthAt(i); BrailleMeasure measure = brailleStaves.get(staffIndex).get(i); if (i == startIndex) measure.unlinkPrevious(); BrailleList measureBraille = measure.head(1024, false); BrailleList braille = new BrailleList(); if (i == startIndex) { if (staffIndex == 0) { transcriber.printString(paragraphNumber); transcriber.printString(new Space()); } else { transcriber.indentTo(indent); } Sign introSymbol = brailleStaves.get(staffIndex).getIntro(); if (introSymbol != null) { braille.add((Sign)introSymbol.clone()); } } braille.add(measureBraille); transcriber.printString(braille); int skipColumns = columnWidth - braille.length(); if (skipColumns > 0) { transcriber.printString(new Space()); skipColumns--; } if (skipColumns > 2) { while (skipColumns > 0) { transcriber.printString(new Dot() { @Override public String getDescription() { return "Alignment dot"; } }); skipColumns--; } } while (skipColumns > 0) { transcriber.printString(new Space()); skipColumns--; } transcriber.printString(new Space()); } transcriber.newLine(); } paragraph++; startIndex = endIndex; } } private void createMeasuresInBrailleStaves(Score score) { brailleStaves.clear(); initialTimeSignature = null; initialKeySignature = null; for (Part part: score.getParts()) { if (initialKeySignature == null) { initialKeySignature = part.getKeySignature(); } else { if (!initialKeySignature.equals(part.getKeySignature())) { LOG.warning("Parts with different initial key signatures"); } } if (initialTimeSignature == null) { initialTimeSignature = part.getTimeSignature(); } else { if (!initialTimeSignature.equals(part.getTimeSignature())) { LOG.warning("Parts with different initial time signatures"); } } MusicList musicList = part.getMusicList(); int staffCount = musicList.getStaffCount(); for (int staffIndex = 0; staffIndex < staffCount; staffIndex++) { Staff staff = musicList.getStaff(staffIndex); BrailleStaff brailleStaff = new BrailleStaff(); BrailleMeasure measure = new BrailleMeasure(transcriber); boolean displayClefChange = false; int voiceDirection = -1; if (staffCount == 1) { brailleStaff.setIntro(new SoloPart()); if (staff.containsChords()) displayClefChange = true; } else if (staffCount == 2) { if (staffIndex == 0) { brailleStaff.setIntro(new RightHandPart()); voiceDirection = -1; } else if (staffIndex == 1) { brailleStaff.setIntro(new LeftHandPart()); voiceDirection = 1; } } measure.setChordDirection(voiceDirection); measure.setVoiceDirection(voiceDirection); StartBar startBar = null; for (int staffElementIndex = 0; staffElementIndex < staff.size(); staffElementIndex++) { Event event = staff.get(staffElementIndex); if (event instanceof StartBar) { startBar = (StartBar)event; measure.setTimeSignature(startBar.getTimeSignature()); } else if (event instanceof EndBar) { EndBar rightBar = (EndBar)event; measure.process(); brailleStaff.add(measure); measure = new BrailleMeasure(transcriber, measure); measure.setChordDirection(voiceDirection); measure.setVoiceDirection(voiceDirection); } else { measure.add(event); } } brailleStaves.add(brailleStaff); } } } private class BrailleStaff extends ArrayList<BrailleMeasure> { private Sign intro = null; void setIntro(Sign intro) { this.intro = intro; } Sign getIntro() { return intro; } } @SuppressWarnings("serial") private class BrailleStaves extends ArrayList<BrailleStaff> { int maxLength(int from, int to) { int length = 0; for (int i = from; i < to; i++) { length += maxLengthAt(i); } return length + (to - from); } int maxLengthAt(int index) { int maxLength = 0; for (BrailleStaff brailleStaff : this) { BrailleMeasure measure = brailleStaff.get(index); BrailleList braille = measure.head(1024, false); maxLength = Math.max(maxLength, braille.length()); } return maxLength; } int getMeasureCount() { if (isEmpty()) return 0; return get(0).size(); } } }