package org.herac.tuxguitar.io.ptb; import java.util.Iterator; 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.factory.TGFactory; import org.herac.tuxguitar.song.managers.TGSongManager; import org.herac.tuxguitar.song.models.TGBeat; import org.herac.tuxguitar.song.models.TGChannel; 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.TGStroke; import org.herac.tuxguitar.song.models.TGTrack; import org.herac.tuxguitar.song.models.TGVoice; import org.herac.tuxguitar.song.models.effects.TGEffectBend; public class PTSongParser { private TGSongManager manager; private TrackHelper helper; public PTSongParser(TGFactory factory){ this.manager = new TGSongManager(factory); this.helper = new TrackHelper(); } public TGSong parseSong(PTSong src){ PTSong song = new PTSong(); PTSongSynchronizerUtil.synchronizeTracks(src, song); this.manager.setSong(this.manager.getFactory().newSong()); this.parseTrack(song.getTrack1()); this.parseTrack(song.getTrack2()); this.parseProperties(song.getInfo()); this.manager.orderBeats(); return this.manager.getSong(); } 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 ); } } 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 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 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 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 Iterator it = this.manager.getSong().getTracks(); while( it.hasNext() ){ TGTrack tgTrack = (TGTrack )it.next(); 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 parseTempo(PTTempo tempo){ TGMeasure measure = getMeasure(1,this.helper.getStartHelper().getMaxStart()); measure.getTempo().setValue( tempo.getTempo() ); measure.getHeader().setTripletFeel(tempo.getTripletFeel()); } 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().getDivision().setTimes(beat.getTimes()); tgVoice.getDuration().getDivision().setEnters(beat.getEnters()); Iterator it = beat.getNotes().iterator(); while(it.hasNext()){ PTNote ptNote = (PTNote)it.next(); if( ptNote.getString() <= measure.getTrack().stringCount() && ptNote.getValue() >= 0 ){ TGNote note = this.manager.getFactory().newNote(); 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( TGStroke.STROKE_DOWN ); tgBeat.getStroke().setValue( TGDuration.SIXTEENTH ); }else if( beat.isArpeggioDown() ){ tgBeat.getStroke().setDirection( TGStroke.STROKE_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 TGEffectBend makeBend(int value){ if(value >= 1 && value <= 8){ TGEffectBend bend = this.manager.getFactory().newEffectBend(); if(value == 1){ bend.addPoint(0,0); bend.addPoint(6,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(12,(TGEffectBend.SEMITONE_LENGTH * 4)); } else if(value == 2){ bend.addPoint(0,0); bend.addPoint(3,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(6,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(9,0); bend.addPoint(12,0); } else if(value == 3){ bend.addPoint(0,0); bend.addPoint(6,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(12,(TGEffectBend.SEMITONE_LENGTH * 4)); } else if(value == 4){ bend.addPoint(0,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(12,(TGEffectBend.SEMITONE_LENGTH * 4)); } else if(value == 5){ bend.addPoint(0,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(4,(TGEffectBend.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,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(4,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(8,0); bend.addPoint(12,0); } else if(value == 8){ bend.addPoint(0,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(4,(TGEffectBend.SEMITONE_LENGTH * 4)); bend.addPoint(8,0); bend.addPoint(12,0); } return bend; } return null; } 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; } private TGTrack getTrack(int number){ TGTrack track = null; while( (track = this.manager.getTrack(number)) == null){ track = createTrack(); } return track; } public TGTrack getStaffTrack(int staff){ TGTrack track = this.helper.getInfoHelper().getStaffTrack( staff ); return ( track != null ? track : createTrack() ); } private TGTrack createTrack(){ return createTrack(this.helper.getInfoHelper().getDefaultInfo()); } private TGTrack createTrack(PTTrackInfo info){ TGTrack track = this.manager.addTrack(); this.helper.getInfoHelper().addStaffTrack( track ); this.setTrackInfo(track, info ); return track; } private void setTrackInfo(TGTrack tgTrack , PTTrackInfo info){ TGChannel tgChannel = this.manager.addChannel(); tgChannel.setProgram((short) info.getInstrument() ); tgChannel.setVolume((short) info.getVolume() ); tgChannel.setBalance((short) info.getBalance() ); tgTrack.setName( info.getName() ); tgTrack.setChannelId(tgChannel.getChannelId()); tgTrack.getStrings().clear(); for(int i = 0; i < info.getStrings().length; i ++){ TGString string = this.manager.getFactory().newString(); string.setNumber( (i + 1) ); string.setValue( info.getStrings()[i] ); tgTrack.getStrings().add(string); } } private boolean hasSameInfo(TGTrack track , PTTrackInfo info){ TGChannel tgChannel = this.manager.getChannel(track.getChannelId()); if( tgChannel == null ){ return false; } if( !info.getName().equals( track.getName() ) ){ return false; } if( info.getInstrument() != tgChannel.getProgram() ){ return false; } if( info.getVolume() != tgChannel.getVolume() ){ return false; } if( info.getBalance() != tgChannel.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 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 = this.manager.getFactory().newBeat(); beat.setStart(start); measure.addBeat(beat); return beat; } } /* 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); } } } */