package org.herac.tuxguitar.io.ptb; import org.herac.tuxguitar.gui.editors.tab.TGBeatImpl; import org.herac.tuxguitar.gui.editors.tab.TGNoteImpl; import org.herac.tuxguitar.io.ptb.base.PTBar; import org.herac.tuxguitar.io.ptb.base.PTBeat; import org.herac.tuxguitar.io.ptb.base.PTComponent; import org.herac.tuxguitar.io.ptb.base.PTGuitarIn; import org.herac.tuxguitar.io.ptb.base.PTNote; import org.herac.tuxguitar.io.ptb.base.PTPosition; import org.herac.tuxguitar.io.ptb.base.PTSection; import org.herac.tuxguitar.io.ptb.base.PTSong; import org.herac.tuxguitar.io.ptb.base.PTSongInfo; import org.herac.tuxguitar.io.ptb.base.PTTempo; import org.herac.tuxguitar.io.ptb.base.PTTrack; import org.herac.tuxguitar.io.ptb.base.PTTrackInfo; import org.herac.tuxguitar.io.ptb.helper.TrackHelper; import org.herac.tuxguitar.song.managers.TGSongManager; import org.herac.tuxguitar.song.models.Direction; import org.herac.tuxguitar.song.models.TGBeat; import org.herac.tuxguitar.song.models.TGDivisionType; import org.herac.tuxguitar.song.models.TGDuration; import org.herac.tuxguitar.song.models.TGMeasure; import org.herac.tuxguitar.song.models.TGNote; import org.herac.tuxguitar.song.models.TGSong; import org.herac.tuxguitar.song.models.TGString; import org.herac.tuxguitar.song.models.TGTrack; import org.herac.tuxguitar.song.models.TGVoice; import org.herac.tuxguitar.song.models.effects.BendingEffect; import org.herac.tuxguitar.song.models.effects.EffectPoint; public class PTSongParser { private TrackHelper helper; private TGSongManager manager; public PTSongParser() { this.manager = new TGSongManager(); this.helper = new TrackHelper(); } private TGTrack createTrack() { return createTrack(this.helper.getInfoHelper().getDefaultInfo()); } private TGTrack createTrack(PTTrackInfo info) { TGTrack track = this.manager.createTrack(); this.helper.getInfoHelper().addStaffTrack(track); this.setTrackInfo(track, info); return track; } private TGBeat getBeat(TGMeasure measure, long start) { int count = measure.countBeats(); for (int i = 0; i < count; i++) { TGBeat beat = measure.getBeat(i); if (beat.getStart() == start) { return beat; } } TGBeat beat = new TGBeatImpl(); beat.setStart(start); measure.addBeat(beat); return beat; } private TGMeasure getMeasure(int trackNumber, long start) { return getMeasure(getTrack(trackNumber), start); } private TGMeasure getMeasure(TGTrack track, long start) { TGMeasure measure = null; while ((measure = this.manager.getTrackManager().getMeasureAt(track, start)) == null) { this.manager.addNewMeasureBeforeEnd(); } return measure; } public TGTrack getStaffTrack(int staff) { TGTrack track = this.helper.getInfoHelper().getStaffTrack(staff); return (track != null ? track : createTrack()); } private TGTrack getTrack(int number) { TGTrack track = null; while ((track = this.manager.getTrack(number)) == null) { track = createTrack(); } return track; } private boolean hasSameInfo(TGTrack track, PTTrackInfo info) { if (!info.getName().equals(track.getName())) { return false; } if (info.getInstrument() != track.getChannel().getInstrument()) { return false; } if (info.getVolume() != track.getChannel().getVolume()) { return false; } if (info.getBalance() != track.getChannel().getBalance()) { return false; } if (info.getStrings().length != track.stringCount()) { return false; } for (int i = 0; i < info.getStrings().length; i++) { if (info.getStrings()[i] != track.getString((i + 1)).getValue()) { return false; } } return true; } private BendingEffect makeBend(int value) { if (value >= 1 && value <= 8) { BendingEffect bend = new BendingEffect(); if (value == 1) { bend.addPoint(0, 0); bend.addPoint(6, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(12, (EffectPoint.SEMITONE_LENGTH * 4)); } else if (value == 2) { bend.addPoint(0, 0); bend.addPoint(3, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(6, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(9, 0); bend.addPoint(12, 0); } else if (value == 3) { bend.addPoint(0, 0); bend.addPoint(6, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(12, (EffectPoint.SEMITONE_LENGTH * 4)); } else if (value == 4) { bend.addPoint(0, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(12, (EffectPoint.SEMITONE_LENGTH * 4)); } else if (value == 5) { bend.addPoint(0, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(4, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(8, 0); bend.addPoint(12, 0); } else if (value == 6) { bend.addPoint(0, 8); bend.addPoint(12, 8); } else if (value == 7) { bend.addPoint(0, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(4, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(8, 0); bend.addPoint(12, 0); } else if (value == 8) { bend.addPoint(0, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(4, (EffectPoint.SEMITONE_LENGTH * 4)); bend.addPoint(8, 0); bend.addPoint(12, 0); } return bend; } return null; } private void parseBar(PTBar bar) { this.helper.getStartHelper().initVoices( this.helper.getStartHelper().getMaxStart()); if (bar.getNumerator() > 0 && bar.getDenominator() > 0) { this.helper.getStartHelper().setBarStart( this.helper.getStartHelper().getMaxStart()); this.helper.getStartHelper().setBarLength( (long) (bar.getNumerator() * (TGDuration.QUARTER_TIME * (4.0f / bar .getDenominator())))); } } private void parseBeat(PTBeat beat) { if (beat.isGrace()) { // TODO: agrear el efecto a las notas del siguiente beat return; } if (beat.getMultiBarRest() > 1) { // Multibar Rests, must allways have measure duration. long start = this.helper.getStartHelper().getBarStart(); long duration = (beat.getMultiBarRest() * this.helper.getStartHelper() .getBarLength()); this.helper.getStartHelper().setVoiceStart(beat.getStaff(), beat.getVoice(), (start + duration)); return; } long start = this.helper.getStartHelper().getVoiceStart(beat.getStaff(), beat.getVoice()); TGMeasure measure = getMeasure(getStaffTrack(beat.getStaff()), start); TGBeat tgBeat = getBeat(measure, start); TGVoice tgVoice = tgBeat.getVoice(beat.getVoice()); tgVoice.setEmpty(false); tgVoice.getDuration().setValue(beat.getDuration()); tgVoice.getDuration().setDotted(beat.isDotted()); tgVoice.getDuration().setDoubleDotted(beat.isDoubleDotted()); tgVoice.getDuration().setDivision( new TGDivisionType(beat.getEnters(), beat.getTimes())); for (final PTNote ptNote : beat.getNotes()) { if (ptNote.getString() <= measure.getTrack().stringCount() && ptNote.getValue() >= 0) { TGNote note = new TGNoteImpl(); note.setString(ptNote.getString()); note.setValue(ptNote.getValue()); note.setTiedNote(ptNote.isTied()); note.getEffect().setVibrato(beat.isVibrato()); note.getEffect().setDeadNote(ptNote.isDead()); note.getEffect().setHammer(ptNote.isHammer()); note.getEffect().setSlide(ptNote.isSlide()); note.getEffect().setBend(makeBend(ptNote.getBend())); tgVoice.addNote(note); } } if (beat.isArpeggioUp()) { tgBeat.getStroke().setDirection(Direction.DOWN); tgBeat.getStroke().setValue(TGDuration.SIXTEENTH); } else if (beat.isArpeggioDown()) { tgBeat.getStroke().setDirection(Direction.UP); tgBeat.getStroke().setValue(TGDuration.SIXTEENTH); } this.helper.getStartHelper().checkBeat(tgVoice.isRestVoice()); // If it's a rest measure, duration must fill the measure. long duration = tgVoice.getDuration().getTime(); if (tgVoice.isRestVoice() && tgBeat.getStart() == this.helper.getStartHelper().getBarStart() && duration > this.helper.getStartHelper().getBarLength()) { duration = this.helper.getStartHelper().getBarLength(); } this.helper.getStartHelper().setVoiceStart(beat.getStaff(), beat.getVoice(), (tgBeat.getStart() + duration)); } private void parseGuitarIn(PTTrack track, PTGuitarIn guitarIn) { PTTrackInfo info = track.getInfo(guitarIn.getTrackInfo()); if (info != null) { // Remove used tracks after guitarIn staff. while (this.helper.getInfoHelper().countStaffTracks() > guitarIn .getStaff()) { this.helper.getInfoHelper().removeStaffTrack( this.helper.getInfoHelper().countStaffTracks() - 1); } // If track was already created, but it's not in use for (final TGTrack tgTrack : this.manager.getSong().getTracks()) { if (hasSameInfo(tgTrack, info)) { boolean exists = false; for (int i = 0; i < this.helper.getInfoHelper().countStaffTracks(); i++) { TGTrack existent = this.helper.getInfoHelper().getStaffTrack(i); if (existent != null && existent.getNumber() == tgTrack.getNumber()) { exists = true; } } if (!exists) { this.helper.getInfoHelper().addStaffTrack(tgTrack); return; } } } // Create track if not exists. this.createTrack(info); } } private void parsePosition(PTTrack track, PTPosition position/* ,int fromTrack */) { for (int i = 0; i < position.getComponents().size(); i++) { PTComponent component = (PTComponent) position.getComponents().get(i); if (component instanceof PTBar) { parseBar((PTBar) component); } else if (component instanceof PTGuitarIn) { parseGuitarIn(track, (PTGuitarIn) component); } else if (component instanceof PTTempo) { parseTempo((PTTempo) component); } else if (component instanceof PTBeat) { parseBeat((PTBeat) component); } } } private void parseProperties(PTSongInfo info) { if (info.getName() != null) { this.manager.getSong().setName(info.getName()); } if (info.getAlbum() != null) { this.manager.getSong().setAlbum(info.getAlbum()); } if (info.getAuthor() != null) { this.manager.getSong().setAuthor(info.getAuthor()); } if (info.getCopyright() != null) { this.manager.getSong().setCopyright(info.getCopyright()); } if (info.getArrenger() != null) { this.manager.getSong().setWriter(info.getArrenger()); } if (info.getGuitarTranscriber() != null || info.getBassTranscriber() != null) { String transcriber = new String(); if (info.getGuitarTranscriber() != null) { transcriber += info.getGuitarTranscriber(); } if (info.getBassTranscriber() != null) { if (transcriber.length() > 0) { transcriber += (" - "); } transcriber += info.getBassTranscriber(); } this.manager.getSong().setTranscriber(transcriber); } if (info.getGuitarInstructions() != null || info.getBassInstructions() != null) { String comments = new String(); if (info.getGuitarInstructions() != null) { comments += info.getGuitarInstructions(); } if (info.getBassInstructions() != null) { comments += info.getBassInstructions(); } this.manager.getSong().setComments(comments); } } public TGSong parseSong(PTSong src) { PTSong song = new PTSong(); PTSongSynchronizerUtil.synchronizeTracks(src, song); this.manager.setSong(new TGSong()); this.parseTrack(song.getTrack1()); this.parseTrack(song.getTrack2()); this.parseProperties(song.getInfo()); this.manager.orderBeats(); return this.manager.getSong(); } private void parseTempo(PTTempo tempo) { TGMeasure measure = getMeasure(1, this.helper.getStartHelper() .getMaxStart()); measure.getTempo().setValue(tempo.getTempo()); measure.getHeader().setTripletFeel(tempo.getTripletFeel()); } private void parseTrack(PTTrack track) { this.helper.reset(track.getDefaultInfo()); long start = TGDuration.QUARTER_TIME; for (int sIndex = 0; sIndex < track.getSections().size(); sIndex++) { PTSection section = (PTSection) track.getSections().get(sIndex); section.sort(); // calculo el siguiente start del compas this.helper.getStartHelper().init(section.getNumber(), section.getStaffs()); this.helper.getStartHelper().initVoices(start); // parseo las posiciones for (int pIndex = 0; pIndex < section.getPositions().size(); pIndex++) { PTPosition position = (PTPosition) section.getPositions().get(pIndex); parsePosition(track, position/* ,number */); } // Calculo el start para la proxima seccion start = this.helper.getStartHelper().getMaxStart(); } } private void setTrackInfo(TGTrack tgTrack, PTTrackInfo info) { tgTrack.setName(info.getName()); tgTrack.getChannel().setInstrument((short) info.getInstrument()); tgTrack.getChannel().setVolume((short) info.getVolume()); tgTrack.getChannel().setBalance((short) info.getBalance()); tgTrack.getStrings().clear(); for (int i = 0; i < info.getStrings().length; i++) { tgTrack.getStrings().add(new TGString(i + 1, info.getStrings()[i])); } } } /* * class TGSongAdjuster{ * * protected TGSongManager manager; * * public TGSongAdjuster(TGSongManager manager){ this.manager = manager; } * * public TGSong process(){ Iterator tracks = * this.manager.getSong().getTracks(); while(tracks.hasNext()){ TGTrack track = * (TGTrack)tracks.next(); Iterator measures = track.getMeasures(); * while(measures.hasNext()){ TGMeasure measure = (TGMeasure)measures.next(); * this.process(measure); } } return this.manager.getSong(); } * * public void process(TGMeasure measure){ * this.manager.getMeasureManager().orderBeats(measure); * * joinBeats(measure); } * * public void joinBeats(TGMeasure measure){ TGBeat previous = null; boolean * finish = true; * * long measureStart = measure.getStart(); long measureEnd = (measureStart + * measure.getLength()); for(int i = 0;i < measure.countBeats();i++){ TGBeat * beat = measure.getBeat( i ); long beatStart = beat.getStart(); long * beatLength = beat.getDuration().getTime(); if(previous != null){ long * previousStart = previous.getStart(); long previousLength = * previous.getDuration().getTime(); * * if(previousStart == beatStart){ // add beat notes to previous for(int n = 0;n * < beat.countNotes();n++){ TGNote note = beat.getNote( n ); previous.addNote( * note ); } * * // add beat chord to previous if(!previous.isChordBeat() && * beat.isChordBeat()){ previous.setChord( beat.getChord() ); } * * // add beat text to previous if(!previous.isTextBeat() && beat.isTextBeat()){ * previous.setText( beat.getText() ); } * * // set the best duration if(beatLength > previousLength && (beatStart + * beatLength) <= measureEnd){ beat.getDuration().copy(previous.getDuration()); * } * * measure.removeBeat(beat); finish = false; break; } * * else if(previousStart < beatStart && (previousStart + previousLength) > * beatStart){ if(beat.isRestBeat()){ measure.removeBeat(beat); finish = false; * break; } TGDuration duration = TGDuration.fromTime(this.manager.getFactory(), * (beatStart - previousStart) ); duration.copy( previous.getDuration() ); } } * if( (beatStart + beatLength) > measureEnd ){ if(beat.isRestBeat()){ * measure.removeBeat(beat); finish = false; break; } TGDuration duration = * TGDuration.fromTime(this.manager.getFactory(), (measureEnd - beatStart) ); * duration.copy( beat.getDuration() ); } previous = beat; } if(!finish){ * joinBeats(measure); } } } */