package org.herac.tuxguitar.song.managers; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import org.herac.tuxguitar.song.factory.TGFactory; import org.herac.tuxguitar.song.models.TGBeat; import org.herac.tuxguitar.song.models.TGChord; 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.TGString; import org.herac.tuxguitar.song.models.TGStroke; import org.herac.tuxguitar.song.models.TGText; import org.herac.tuxguitar.song.models.TGTrack; import org.herac.tuxguitar.song.models.TGVoice; import org.herac.tuxguitar.song.models.effects.TGEffectBend; import org.herac.tuxguitar.song.models.effects.TGEffectGrace; import org.herac.tuxguitar.song.models.effects.TGEffectHarmonic; import org.herac.tuxguitar.song.models.effects.TGEffectTremoloBar; import org.herac.tuxguitar.song.models.effects.TGEffectTremoloPicking; import org.herac.tuxguitar.song.models.effects.TGEffectTrill; public class TGMeasureManager { private TGSongManager songManager; public TGMeasureManager(TGSongManager songManager){ this.songManager = songManager; } public TGSongManager getSongManager(){ return this.songManager; } public void orderBeats(TGMeasure measure){ for(int i = 0;i < measure.countBeats();i++){ TGBeat minBeat = null; for(int j = i;j < measure.countBeats();j++){ TGBeat beat = measure.getBeat(j); if(minBeat == null || beat.getStart() < minBeat.getStart()){ minBeat = beat; } } measure.moveBeat(i, minBeat); } } /** * Agrega un beat al compas */ public void addBeat(TGMeasure measure,TGBeat beat){ //Verifico si entra en el compas //if(validateDuration(measure,beat,false,false)){ //Agrego el beat measure.addBeat(beat); //} } public void removeBeat(TGBeat beat){ beat.getMeasure().removeBeat(beat); } public void removeBeat(TGMeasure measure,long start,boolean moveNextComponents){ TGBeat beat = getBeat(measure, start); if(beat != null){ removeBeat(beat, moveNextComponents); } } /** * Elimina un silencio del compas. * si se asigna moveNextComponents = true. los componentes que le siguen * se moveran para completar el espacio vacio que dejo el silencio */ public void removeBeat(TGBeat beat,boolean moveNextBeats){ TGMeasure measure = beat.getMeasure(); removeBeat(beat); if(moveNextBeats){ TGDuration minimumDuration = getMinimumDuration(beat); long start = beat.getStart(); long length = (minimumDuration != null ? minimumDuration.getTime() : 0); TGBeat next = getNextBeat(measure.getBeats(),beat); if(next != null){ length = next.getStart() - start; } moveBeatsInMeasure(beat.getMeasure(),start + length,-length, minimumDuration); } } public void removeEmptyBeats(TGMeasure measure){ List beats = new ArrayList(); Iterator it = measure.getBeats().iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat)it.next(); boolean emptyBeat = true; for( int v = 0; v < beat.countVoices() ; v ++){ TGVoice voice = beat.getVoice( v ); if(!voice.isEmpty()){ emptyBeat = false; } } if( emptyBeat ){ beats.add( beat ); } } it = beats.iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat)it.next(); this.removeBeat( beat ); } } public void removeBeatsBeforeEnd(TGMeasure measure,long fromStart){ List beats = getBeatsBeforeEnd( measure.getBeats() , fromStart); Iterator it = beats.iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat) it.next(); removeBeat(beat); } } public void removeBeatsBeetween(TGMeasure measure,long p1, long p2){ List beats = getBeatsBeetween( measure.getBeats() , p1, p2 ); Iterator it = beats.iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat) it.next(); removeBeat(beat); } } public void addNote(TGMeasure measure,long start, TGNote note, TGDuration duration, int voice){ TGBeat beat = getBeat(measure, start); if(beat != null){ addNote(beat, note, duration, voice); } } public void addNote(TGBeat beat, TGNote note, TGDuration duration, int voice){ addNote(beat, note, duration, beat.getStart(),voice); } public void addNote(TGBeat beat, TGNote note, TGDuration duration, long start, int voice){ boolean emptyVoice = beat.getVoice( voice ).isEmpty(); if( emptyVoice ){ beat.getVoice( voice ).setEmpty( false ); } //Verifico si entra en el compas if(validateDuration(beat.getMeasure(),beat, voice, duration,true,true)){ //Borro lo que haya en la misma posicion for( int v = 0 ; v < beat.countVoices() ; v ++ ){ removeNote(beat.getMeasure(),beat.getStart(), v, note.getString(), false); } duration.copy(beat.getVoice(voice).getDuration()); //trato de agregar un silencio similar al lado tryChangeSilenceAfter(beat.getMeasure(),beat.getVoice(voice)); // Despues de cambiar la duracion, verifico si hay un beat mejor para agregar la nota. TGVoice realVoice = beat.getVoice(voice); if(realVoice.getBeat().getStart() != start){ TGVoice beatIn = getVoiceIn(realVoice.getBeat().getMeasure(), start, voice); if( beatIn != null ) { realVoice = beatIn; } } realVoice.addNote(note); }else{ beat.getVoice( voice ).setEmpty( emptyVoice ); } } public void removeNote(TGNote note, boolean checkRestBeat){ //note.getVoice().removeNote(note); TGVoice voice = note.getVoice(); if( voice != null ){ // Remove the note voice.removeNote(note); TGBeat beat = voice.getBeat(); if(checkRestBeat && beat.isRestBeat()){ //Anulo un posible stroke beat.getStroke().setDirection( TGStroke.STROKE_NONE ); //Borro un posible acorde if( beat.getMeasure() != null ){ removeChord(beat.getMeasure(), beat.getStart()); } } } } public void removeNote(TGNote note){ this.removeNote(note, true); } public void removeNote(TGMeasure measure,long start, int voiceIndex,int string){ this.removeNote(measure, start, voiceIndex, string, true); } /** * Elimina los Componentes que empiecen en Start y esten en la misma cuerda * Si hay un Silencio lo borra sin importar la cuerda */ public void removeNote(TGMeasure measure,long start, int voiceIndex,int string, boolean checkRestBeat){ TGBeat beat = getBeat(measure, start); if(beat != null){ TGVoice voice = beat.getVoice(voiceIndex); for( int i = 0; i < voice.countNotes(); i ++){ TGNote note = voice.getNote(i); if(note.getString() == string){ removeNote(note , checkRestBeat); return; } } } } public void removeNotesAfterString(TGMeasure measure,int string){ List notesToRemove = new ArrayList(); Iterator beats = measure.getBeats().iterator(); while(beats.hasNext()){ TGBeat beat = (TGBeat)beats.next(); for(int v = 0; v < beat.countVoices(); v ++){ TGVoice voice = beat.getVoice( v ); Iterator notes = voice.getNotes().iterator(); while(notes.hasNext()){ TGNote note = (TGNote)notes.next(); if(note.getString() > string){ notesToRemove.add(note); } } } } Iterator it = notesToRemove.iterator(); while(it.hasNext()){ TGNote note = (TGNote)it.next(); removeNote(note); } } /** * Retorna Todas las Notas en la posicion Start */ public List getNotes(TGMeasure measure,long start){ List notes = new ArrayList(); TGBeat beat = getBeat(measure, start); if(beat != null){ for(int v = 0 ; v < beat.countVoices(); v ++){ TGVoice voice = beat.getVoice( v ); Iterator it = voice.getNotes().iterator(); while(it.hasNext()){ TGNote note = (TGNote)it.next(); notes.add(note); } } } return notes; } /** * Retorna Todas las Notas en el pulso */ public List getNotes(TGBeat beat){ List notes = new ArrayList(); if(beat != null){ for(int v = 0 ; v < beat.countVoices(); v ++){ TGVoice voice = beat.getVoice( v ); if( !voice.isEmpty() && !voice.isRestVoice() ){ Iterator it = voice.getNotes().iterator(); while(it.hasNext()){ TGNote note = (TGNote)it.next(); notes.add(note); } } } } return notes; } /** * Retorna la Nota en la posicion y cuerda */ public TGNote getNote(TGMeasure measure,long start,int string) { TGBeat beat = getBeat(measure, start); if(beat != null){ return getNote(beat, string); } return null; } /** * Retorna la Nota en la cuerda */ public TGNote getNote(TGBeat beat,int string) { for( int v = 0; v < beat.countVoices(); v ++){ TGVoice voice = beat.getVoice(v); if(!voice.isEmpty()){ TGNote note = getNote(voice, string); if(note != null){ return note; } } } return null; } public TGNote getNote(TGVoice voice,int string) { Iterator it = voice.getNotes().iterator(); while(it.hasNext()){ TGNote note = (TGNote)it.next(); if (note.getString() == string) { return note; } } return null; } public TGNote getPreviousNote(TGMeasure measure,long start, int voiceIndex, int string) { TGBeat beat = getBeat(measure, start); if( beat != null ){ TGBeat previous = getPreviousBeat(measure.getBeats(),beat); while(previous != null){ TGVoice voice = previous.getVoice(voiceIndex); if(!voice.isEmpty()){ for (int i = 0; i < voice.countNotes(); i++) { TGNote current = voice.getNote(i); if (current.getString() == string) { return current; } } } previous = getPreviousBeat(measure.getBeats(),previous); } } return null; } public TGNote getNextNote(TGMeasure measure,long start, int voiceIndex, int string) { TGBeat beat = getBeat(measure, start); if( beat != null ){ TGBeat next = getNextBeat(measure.getBeats(),beat); while(next != null){ TGVoice voice = next.getVoice(voiceIndex); if(!voice.isEmpty()){ for (int i = 0; i < voice.countNotes(); i++) { TGNote current = voice.getNote(i); if (current.getString() == string) { return current; } } } next = getNextBeat(measure.getBeats(),next); } } return null; } public TGDuration getMinimumDuration(TGBeat beat){ TGDuration minimumDuration = null; for(int v = 0; v < beat.countVoices(); v ++){ TGVoice voice = beat.getVoice( v ); if( !voice.isEmpty() ){ if(minimumDuration == null || voice.getDuration().getTime() < minimumDuration.getTime()){ minimumDuration = voice.getDuration(); } } } return minimumDuration; } public TGBeat getBeat(TGTrack track,long start) { Iterator measures = track.getMeasures(); while( measures.hasNext() ){ TGMeasure measure = (TGMeasure)measures.next(); Iterator beats = measure.getBeats().iterator(); while(beats.hasNext()){ TGBeat beat = (TGBeat)beats.next(); if (beat.getStart() == start) { return beat; } } } return null; } /** * Retorna las Nota en la posicion y cuerda */ public TGBeat getBeat(TGMeasure measure,long start) { Iterator it = measure.getBeats().iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat)it.next(); if (beat.getStart() == start) { return beat; } } return null; } /** * Retorna las Nota en la posicion y cuerda */ public TGBeat getBeatIn(TGMeasure measure,long start) { TGBeat beatIn = null; Iterator it = measure.getBeats().iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat)it.next(); TGDuration duration = getMinimumDuration(beat); if (beat.getStart() <= start && (beat.getStart() + duration.getTime() > start)) { if(beatIn == null || beat.getStart() > beatIn.getStart()){ beatIn = beat; } } } return beatIn; } /** * Retorna las Nota en la posicion y cuerda */ public TGVoice getVoiceIn(TGMeasure measure,long start, int voiceIndex) { Iterator it = measure.getBeats().iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat)it.next(); TGVoice voice = beat.getVoice(voiceIndex); if (!voice.isEmpty() && beat.getStart() <= start && (beat.getStart() + voice.getDuration().getTime() > start)) { return voice; } } return null; } /** * Retorna el Siguiente Componente */ public TGBeat getNextBeat(List beats,TGBeat beat) { TGBeat next = null; for (int i = 0; i < beats.size(); i++) { TGBeat current = (TGBeat) beats.get(i); if (current.getStart() > beat.getStart()) { if (next == null) { next = current; } else if (current.getStart() < next.getStart()) { next = current; } /*else if (current.getStart() == next.getStart() && current.getDuration().getTime() <= next.getDuration().getTime()) { next = current; }*/ } } return next; } /** * Retorna el Componente Anterior */ public TGBeat getPreviousBeat(List beats,TGBeat beat) { TGBeat previous = null; for (int i = 0; i < beats.size(); i++) { TGBeat current = (TGBeat) beats.get(i); if (current.getStart() < beat.getStart()) { if (previous == null) { previous = current; } else if (current.getStart() > previous.getStart()) { previous = current; } /*else if (current.getStart() == previous.getStart() && current.getDuration().getTime() <= previous.getDuration().getTime()) { previous = current; }*/ } } return previous; } /** * Retorna el Primer Componente */ public TGBeat getFirstBeat(List components) { TGBeat first = null; for (int i = 0; i < components.size(); i++) { TGBeat component = (TGBeat) components.get(i); if (first == null || component.getStart() < first.getStart()) { first = component; } } return first; } /** * Retorna el Ultimo Componente */ public TGBeat getLastBeat(List components) { TGBeat last = null; for (int i = 0; i < components.size(); i++) { TGBeat component = (TGBeat) components.get(i); if (last == null || last.getStart() < component.getStart()) { last = component; } } return last; } /** * Retorna el Siguiente Componente */ /* public TGBeat getNextRestBeat(List beats,TGBeat component) { TGBeat next = getNextBeat(beats, component); while(next != null && !next.isRestBeat()){ next = getNextBeat(beats, next); } return next; } */ /** * Retorna Todos los desde Start hasta el final del compas */ public List getBeatsBeforeEnd(List beats,long fromStart) { List list = new ArrayList(); Iterator it = beats.iterator(); while(it.hasNext()){ TGBeat current = (TGBeat)it.next(); if (current.getStart() >= fromStart) { list.add(current); } } return list; } public List getBeatsBeetween(List beats,long p1, long p2) { List list = new ArrayList(); Iterator it = beats.iterator(); while(it.hasNext()){ TGBeat current = (TGBeat)it.next(); if (current.getStart() >= p1 && current.getStart() < p2 ) { list.add(current); } } return list; } public void locateBeat( TGBeat beat, TGTrack track , boolean newMeasureAlsoForRestBeats) { if( beat.getMeasure() != null ){ beat.getMeasure().removeBeat(beat); beat.setMeasure(null); } TGMeasure newMeasure = getSongManager().getTrackManager().getMeasureAt(track, beat.getStart() ); if( newMeasure == null ){ boolean createNewMeasure = newMeasureAlsoForRestBeats; if( !createNewMeasure ){ createNewMeasure = ( !beat.isRestBeat() || beat.isTextBeat() ); } if( createNewMeasure ){ while( newMeasure == null && beat.getStart() >= TGDuration.QUARTER_TIME){ getSongManager().addNewMeasureBeforeEnd(); newMeasure = getSongManager().getTrackManager().getMeasureAt(track, beat.getStart() ); } } } if( newMeasure != null ){ long mStart = newMeasure.getStart(); long mLength = newMeasure.getLength(); long bStart = beat.getStart(); for( int v = 0 ; v < beat.countVoices() ; v ++ ){ TGVoice voice = beat.getVoice( v ); long vDuration = voice.getDuration().getTime(); if(!voice.isEmpty() && (bStart + vDuration) > (mStart + mLength) ){ long vTiedDuration = ( (bStart + vDuration) - (mStart + mLength) ); vDuration -= vTiedDuration; if( vDuration > 0 ){ TGDuration duration = TGDuration.fromTime(getSongManager().getFactory(), vDuration); if( duration != null ){ duration.copy( voice.getDuration() ); } } if( vTiedDuration > 0 ) { TGDuration newVoiceDuration = TGDuration.fromTime(getSongManager().getFactory(), vTiedDuration); if( newVoiceDuration != null ){ long newBeatStart = (bStart + vDuration); TGBeat newBeat = getBeat(track, newBeatStart); if( newBeat == null ){ newBeat = getSongManager().getFactory().newBeat(); newBeat.setStart( (bStart + vDuration) ); } TGVoice newVoice = newBeat.getVoice( v ); for( int n = 0 ; n < voice.countNotes() ; n ++ ){ TGNote note = voice.getNote( n ); TGNote newNote = getSongManager().getFactory().newNote(); newNote.setTiedNote( true ); newNote.setValue( note.getValue() ); newNote.setString( note.getString() ); newNote.setVelocity( note.getVelocity() ); newVoice.addNote( newNote ); } newVoice.setEmpty( false ); newVoiceDuration.copy( newVoice.getDuration() ); locateBeat(newBeat, track, newMeasureAlsoForRestBeats); } } } } newMeasure.addBeat(beat); } } public void moveOutOfBoundsBeatsToNewMeasure(TGMeasure measure){ this.moveOutOfBoundsBeatsToNewMeasure(measure, true ); } public void moveOutOfBoundsBeatsToNewMeasure(TGMeasure measure, boolean newMeasureAlsoForRestBeats ){ List beats = new ArrayList(); long mStart = measure.getStart(); long mLength = measure.getLength(); for( int i = 0; i < measure.countBeats() ; i ++ ){ TGBeat beat = measure.getBeat( i ); if( beat.getStart() < mStart || beat.getStart() >= mStart + mLength ){ beats.add( beat ); } else{ long bStart = beat.getStart(); for( int v = 0 ; v < beat.countVoices() ; v ++ ){ TGVoice voice = beat.getVoice( v ); long vDuration = voice.getDuration().getTime(); if(!voice.isEmpty() && (bStart + vDuration) > (mStart + mLength) ){ beats.add( beat ); } } } } while( !beats.isEmpty() ){ TGBeat beat = (TGBeat)beats.get( 0 ); if( beat.getMeasure() != null ){ beat.getMeasure().removeBeat(beat); beat.setMeasure(null); } this.locateBeat(beat, measure.getTrack(), newMeasureAlsoForRestBeats); beats.remove(0); } } public boolean moveBeatsInMeasure(TGMeasure measure,long start,long theMove, TGDuration fillDuration){ if( theMove == 0 ){ return false; } boolean success = true; long measureStart = measure.getStart(); long measureEnd = (measureStart + measure.getLength()); // Muevo los componentes List beatsToMove = getBeatsBeforeEnd(measure.getBeats(),start); moveBeats(beatsToMove,theMove); if(success){ List beatsToRemove = new ArrayList(); List beats = new ArrayList(measure.getBeats()); // Verifica los silencios a eliminar al principio del compas TGBeat first = getFirstBeat( beats ); while(first != null && first.isRestBeat() && !first.isTextBeat() && first.getStart() < measureStart){ beats.remove(first); beatsToRemove.add(first); first = getNextBeat( beats,first); } // Verifica los silencios a eliminar al final del compas TGBeat last = getLastBeat(beats); TGDuration lastDuration = (last != null ? getMinimumDuration(last) : null); while(last != null && lastDuration != null && last.isRestBeat() && !last.isTextBeat() && (last.getStart() + lastDuration.getTime() ) > measureEnd ){ beats.remove(last); beatsToRemove.add(last); last = getPreviousBeat(beats,last); lastDuration = (last != null ? getMinimumDuration(last) : null); } // Si el primer o ultimo componente, quedan fuera del compas, entonces el movimiento no es satisfactorio if(first != null && last != null && lastDuration != null){ if(first.getStart() < measureStart || (last.getStart() + lastDuration.getTime()) > measureEnd){ success = false; } } if(success){ // Elimino los silencios que quedaron fuera del compas. Iterator it = beatsToRemove.iterator(); while( it.hasNext() ){ TGBeat beat = (TGBeat)it.next(); removeBeat(beat); } // Se crean silencios en los espacios vacios, si la duracion fue especificada. if( fillDuration != null ){ if( theMove < 0 ){ last = getLastBeat(measure.getBeats()); lastDuration = (last != null ? getMinimumDuration(last) : null); TGBeat beat = getSongManager().getFactory().newBeat(); beat.setStart( (last != null && lastDuration != null ? last.getStart() + lastDuration.getTime() : start ) ); if( (beat.getStart() + fillDuration.getTime()) <= measureEnd ){ for(int v = 0; v < beat.countVoices(); v ++){ TGVoice voice = beat.getVoice(v); voice.setEmpty(false); fillDuration.copy( voice.getDuration() ); } addBeat(measure, beat ); } } else{ first = getFirstBeat(getBeatsBeforeEnd(measure.getBeats(),start)); TGBeat beat = getSongManager().getFactory().newBeat(); beat.setStart( start ); if( (beat.getStart() + fillDuration.getTime()) <= (first != null ?first.getStart() : measureEnd ) ){ for(int v = 0; v < beat.countVoices(); v ++){ TGVoice voice = beat.getVoice(v); voice.setEmpty(false); fillDuration.copy( voice.getDuration() ); } addBeat(measure, beat ); } } } } } // Si el movimiento no es satisfactorio, regreso todo como estaba if(! success ){ moveBeats(beatsToMove,-theMove); } return success; } public void moveAllBeats(TGMeasure measure,long theMove){ moveBeats(measure.getBeats(),theMove); } public void moveBeats(TGMeasure measure, long start, long theMove){ moveBeats(getBeatsBeforeEnd(measure.getBeats(), start),theMove); } /** * Mueve los componentes */ private void moveBeats(List beats,long theMove){ Iterator it = beats.iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat)it.next(); moveBeat(beat,theMove); } } /** * Mueve el componente */ private void moveBeat(TGBeat beat,long theMove){ //obtengo el start viejo long start = beat.getStart(); //asigno el nuevo start beat.setStart(start + theMove); } public void cleanBeat(TGBeat beat){ beat.getStroke().setDirection( TGStroke.STROKE_NONE ); if( beat.getText() != null ){ beat.removeText(); } if( beat.getChord() != null){ beat.removeChord(); } this.cleanBeatNotes(beat); } public void cleanBeatNotes(TGBeat beat){ for(int v = 0; v < beat.countVoices(); v ++){ cleanVoiceNotes(beat.getVoice( v )); } } public void cleanBeatNotes(TGMeasure measure, long start){ TGBeat beat = getBeat(measure, start); if(beat != null){ cleanBeatNotes(beat); } } public void cleanVoiceNotes(TGVoice voice){ if(!voice.isEmpty()){ while(voice.countNotes() > 0 ){ TGNote note = voice.getNote(0); removeNote(note); } } } /** * Agrega el acorde al compas */ public void addChord(TGMeasure measure,long start, TGChord chord){ TGBeat beat = getBeat(measure, start); if(beat != null){ addChord(beat, chord); } } /** * Agrega el acorde al compas */ public void addChord(TGBeat beat,TGChord chord){ beat.removeChord(); beat.setChord(chord); } /** * Retorna el acorde en la position */ public TGChord getChord(TGMeasure measure,long start) { TGBeat beat = getBeat(measure, start); if(beat != null){ return beat.getChord(); } return null; } /** * Borra el acorde en la position */ public void removeChord(TGMeasure measure,long start) { TGBeat beat = getBeat(measure, start); if(beat != null){ beat.removeChord(); } } /** * Agrega el texto al compas */ public void addText(TGMeasure measure,long start, TGText text){ TGBeat beat = getBeat(measure, start); if(beat != null){ addText(beat, text); } } /** * Agrega el texto al compas */ public void addText(TGBeat beat,TGText text){ beat.removeText(); if(!text.isEmpty()){ beat.setText(text); } } /** * Retorna el texto en la position */ public TGText getText(TGMeasure measure,long start) { TGBeat beat = getBeat(measure, start); if(beat != null){ return beat.getText(); } return null; } /** * Borra el texto en el pulso */ public void removeText(TGBeat beat){ beat.removeText(); } /** * Borra el texto en la position */ public boolean removeText(TGMeasure measure,long start) { TGBeat beat = getBeat(measure, start); if(beat != null){ removeText(beat); return true; } return false; } public void cleanMeasure(TGMeasure measure){ while( measure.countBeats() > 0){ removeBeat( measure.getBeat(0)); } } /** * Mueve la nota a la cuerda de arriba */ public int shiftNoteUp(TGMeasure measure,long start,int string){ return shiftNote(measure, start, string,-1); } /** * Mueve la nota a la cuerda de abajo */ public int shiftNoteDown(TGMeasure measure,long start,int string){ return shiftNote(measure, start, string,1); } /** * Mueve la nota a la siguiente cuerda */ private int shiftNote(TGMeasure measure,long start,int string,int move){ TGNote note = getNote(measure,start,string); if(note != null){ int nextStringNumber = (note.getString() + move); while(getNote(measure,start,nextStringNumber) != null){ nextStringNumber += move; } if(nextStringNumber >= 1 && nextStringNumber <= measure.getTrack().stringCount()){ TGString currentString = measure.getTrack().getString(note.getString()); TGString nextString = measure.getTrack().getString(nextStringNumber); int noteValue = (note.getValue() + currentString.getValue()); if(noteValue >= nextString.getValue() && ((nextString.getValue() + 30 > noteValue) || measure.getTrack().isPercussionTrack()) ){ note.setValue(noteValue - nextString.getValue()); note.setString(nextString.getNumber()); return note.getString(); } } } return 0; } /** * Mueve la nota 1 semitono arriba */ public boolean moveSemitoneUp(TGMeasure measure,long start,int string){ return moveSemitone(measure, start, string,1); } /** * Mueve la nota 1 semitono abajo */ public boolean moveSemitoneDown(TGMeasure measure,long start,int string){ return moveSemitone(measure, start, string,-1); } /** * Mueve la nota los semitonos indicados */ private boolean moveSemitone(TGMeasure measure,long start,int string,int semitones){ TGNote note = getNote(measure,start,string); if(note != null){ int newValue = (note.getValue() + semitones); if(newValue >= 0 && (newValue < 30 || measure.getTrack().isPercussionTrack()) ){ note.setValue(newValue); return true; } } return false; } /** * Set the beat stroke */ public boolean setStroke(TGMeasure measure,long start,int value, int direction){ TGBeat beat = getBeat(measure, start); if( beat != null ){ beat.getStroke().setValue(value); beat.getStroke().setDirection(direction); return true; } return false; } /** * Verifica si el componente se puede insertar en el compas. * si no puede, con la opcion removeSilences, verifica si el motivo por el * cual no entra es que lo siguen silencios. de ser asi los borra. */ /* public boolean validateDuration(TGMeasure measure,TGBeat beat,boolean moveNextComponents, boolean setCurrentDuration){ return validateDuration(measure, beat, beat.getDuration(),moveNextComponents, setCurrentDuration); } public boolean validateDuration(TGMeasure measure,TGBeat beat,TGDuration duration,boolean moveNextBeats, boolean setCurrentDuration){ int errorMargin = 10; this.orderBeats(measure); long measureStart = measure.getStart(); long measureEnd = (measureStart + measure.getLength()); long beatStart = beat.getStart(); long beatLength = duration.getTime(); long beatEnd = (beatStart + beatLength); List beats = measure.getBeats(); //Verifico si hay un beat en el mismo lugar, y comparo las duraciones. TGBeat currentBeat = getBeat(measure,beatStart); if(currentBeat != null && beatLength <= currentBeat.getDuration().getTime()){ return true; } //Verifico si hay lugar para meter el beat TGBeat nextComponent = getNextBeat(beats,beat); if(currentBeat == null){ if(nextComponent == null && beatEnd < (measureEnd + errorMargin)){ return true; } if(nextComponent != null && beatEnd < (nextComponent.getStart() + errorMargin)){ return true; } } // Busca si hay espacio disponible de silencios entre el componente y el el que le sigue.. si encuentra lo borra if(nextComponent != null && nextComponent.isRestBeat()){ //Verifico si lo que sigue es un silencio. y lo borro long nextBeatEnd = 0; List nextBeats = new ArrayList(); while(nextComponent != null && nextComponent.isRestBeat() && !nextComponent.isTextBeat()){ nextBeats.add(nextComponent); nextBeatEnd = nextComponent.getStart() + nextComponent.getDuration().getTime(); nextComponent = getNextBeat(beats,nextComponent); } if(nextComponent == null){ nextBeatEnd = measureEnd; }else if(!nextComponent.isRestBeat() || nextComponent.isTextBeat()){ nextBeatEnd = nextComponent.getStart(); } if(beatEnd <= (nextBeatEnd + errorMargin)){ while(!nextBeats.isEmpty()){ TGBeat currBeat = (TGBeat)nextBeats.get(0); nextBeats.remove(currBeat); removeBeat(currBeat, false); } return true; } } // Busca si hay espacio disponible de silencios entre el componente y el final.. si encuentra mueve todo if(moveNextBeats){ nextComponent = getNextBeat(beats,beat); if(nextComponent != null){ long requiredLength = (beatLength - (nextComponent.getStart() - beatStart)); long nextSilenceLength = 0; TGBeat nextRestBeat = getNextRestBeat(beats, beat); while(nextRestBeat != null && !nextRestBeat.isTextBeat()){ nextSilenceLength += nextRestBeat.getDuration().getTime(); nextRestBeat = getNextRestBeat(beats, nextRestBeat); } if(requiredLength <= (nextSilenceLength + errorMargin)){ beats = getBeatsBeforeEnd(measure.getBeats(),nextComponent.getStart()); while(!beats.isEmpty()){ TGBeat current = (TGBeat)beats.get(0); if(current.isRestBeat() && !current.isTextBeat()){ requiredLength -= current.getDuration().getTime(); removeBeat(current, false); }else if(requiredLength > 0){ moveBeat(current,requiredLength); } beats.remove(0); } return true; } } } // como ultimo intento, asigno la duracion de cualquier componente existente en el lugar. if(setCurrentDuration && currentBeat != null){ currentBeat.getDuration().copy( duration ); return true; } return false; } */ /** * Cambia la Duracion del pulso. */ /* @Deprecated public void changeDuration(TGMeasure measure,TGBeat beat,TGDuration duration,boolean tryMove){ //obtengo la duracion vieja TGDuration oldDuration = beat.getDuration().clone(getSongManager().getFactory()); //si no entra vuelvo a dejar la vieja if(validateDuration(measure,beat, duration,tryMove,false)){ //se lo agrego a todas las notas en la posicion beat.setDuration(duration.clone(getSongManager().getFactory())); //trato de agregar un silencio similar al lado tryChangeSilenceAfter(measure,beat); }else{ oldDuration.copy( beat.getDuration() ); } } */ /* @Deprecated public void tryChangeSilenceAfter(TGMeasure measure,TGBeat beat){ autoCompleteSilences(measure); TGBeat nextBeat = getNextBeat(measure.getBeats(),beat); long beatEnd = (beat.getStart() + beat.getDuration().getTime()); long measureEnd = (measure.getStart() + measure.getLength()); if(nextBeat != null && nextBeat.isRestBeat() && beatEnd <= measureEnd){ long theMove = (getRealStart(measure,beatEnd)) - getRealStart(measure,nextBeat.getStart()); if((nextBeat.getStart() + theMove) < measureEnd && (nextBeat.getStart() + nextBeat.getDuration().getTime() + theMove) <= measureEnd){ moveBeat(nextBeat,theMove); changeDuration(measure,nextBeat,beat.getDuration().clone(getSongManager().getFactory()),false); } } } */ /** * Calcula si hay espacios libres. y crea nuevos silencios */ /* public void autoCompleteSilences(TGMeasure measure){ List components = measure.getBeats(); for( int i = 0; i < TGBeat.MAX_VOICES; i ++ ){ //TGBeat component = getFirstBeat(components); TGVoice component = getFirstVoice(components, i); long start = measure.getStart(); long end = 0; long diff = 0; while (component != null) { end = component.getBeat().getStart() + component.getDuration().getTime(); if(component.getBeat().getStart() > start){ diff = component.getBeat().getStart() - start; if(diff > 0){ createSilences(measure,start,diff, i); } } start = end; component = getNextVoice(components,component.getBeat(), i); } end = measure.getStart() + measure.getLength(); diff = end - start; if(diff > 0){ createSilences(measure,start,diff, i); } } } */ public void autoCompleteSilences(TGMeasure measure){ TGBeat beat = getFirstBeat( measure.getBeats() ); if( beat == null ){ createSilences(measure, measure.getStart(), measure.getLength(), 0); return; } for( int v = 0 ; v < TGBeat.MAX_VOICES ; v ++ ){ TGVoice voice = getFirstVoice( measure.getBeats() , v ); if( voice != null && voice.getBeat().getStart() > measure.getStart() ){ createSilences(measure, measure.getStart(), (voice.getBeat().getStart() - measure.getStart()), v); } } long[] start = new long[beat.countVoices()]; long[] uncompletedLength = new long[beat.countVoices()]; for( int v = 0; v < uncompletedLength.length; v ++ ){ start[v] = 0; uncompletedLength[v] = 0; } while (beat != null) { for( int v = 0; v < beat.countVoices(); v ++ ){ TGVoice voice = beat.getVoice( v ); if( !voice.isEmpty() ){ long voiceEnd = (beat.getStart() + voice.getDuration().getTime()); long nextPosition = (measure.getStart() + measure.getLength()); TGVoice nextVoice = getNextVoice(measure.getBeats(), beat, voice.getIndex()); if(nextVoice != null){ nextPosition = nextVoice.getBeat().getStart(); } if( voiceEnd < nextPosition ){ start[v] = voiceEnd; uncompletedLength[v] = (nextPosition - voiceEnd); } } } for( int v = 0; v < uncompletedLength.length; v ++ ){ if( uncompletedLength[v] > 0 ){ createSilences(measure,start[v],uncompletedLength[v], v); } start[v] = 0; uncompletedLength[v] = 0; } beat = getNextBeat(measure.getBeats(), beat ); } } /** * Crea Silencios temporarios en base a length */ private void createSilences(TGMeasure measure,long start,long length, int voiceIndex){ long nextStart = start; List durations = createDurations(getSongManager().getFactory(),length); Iterator it = durations.iterator(); while(it.hasNext()){ TGDuration duration = (TGDuration)it.next(); boolean isNew = false; long beatStart = getRealStart(measure, nextStart); TGBeat beat = getBeat(measure, beatStart); if( beat == null ){ beat = getSongManager().getFactory().newBeat(); beat.setStart( getRealStart(measure, nextStart) ); isNew = true; } //TGBeat beat = getSongManager().getFactory().newBeat(); //beat.setStart( getRealStart(measure, nextStart) ); TGVoice voice = beat.getVoice(voiceIndex); voice.setEmpty(false); duration.copy(voice.getDuration()); if( isNew ){ addBeat(measure,beat); } // temporal //beat.getVoice(0).setEmpty(false); //beat.getVoice(1).setEmpty(false); // /temporal nextStart += duration.getTime(); } } public long getRealStart(TGMeasure measure,long currStart){ long beatLength = TGSongManager.getDivisionLength(measure.getHeader()); long start = currStart; boolean startBeat = (start % beatLength == 0); if(!startBeat){ TGDuration minDuration = getSongManager().getFactory().newDuration(); minDuration.setValue(TGDuration.SIXTY_FOURTH); minDuration.getDivision().setEnters(3); minDuration.getDivision().setTimes(2); for(int i = 0;i < minDuration.getTime();i++){ start ++; startBeat = (start % beatLength == 0); if(startBeat){ break; } } if(!startBeat){ start = currStart; } } return start; } /** * Liga la nota */ public void changeTieNote(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ changeTieNote(note); } } /** * Liga la nota */ public void changeTieNote(TGNote note){ note.setTiedNote(!note.isTiedNote()); note.getEffect().setDeadNote(false); } /** * Agrega un vibrato */ public void changeVibratoNote(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setVibrato(!note.getEffect().isVibrato()); } } /** * Agrega una nota muerta */ public void changeDeadNote(TGNote note){ note.getEffect().setDeadNote(!note.getEffect().isDeadNote()); note.setTiedNote(false); } /** * Agrega un slide */ public void changeSlideNote(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setSlide(!note.getEffect().isSlide()); } } /** * Agrega un hammer */ public void changeHammerNote(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setHammer(!note.getEffect().isHammer()); } } /** * Agrega un palm-mute */ public void changePalmMute(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setPalmMute(!note.getEffect().isPalmMute()); } } /** * Agrega un staccato */ public void changeStaccato(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setStaccato(!note.getEffect().isStaccato()); } } /** * Agrega un tapping */ public void changeTapping(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setTapping(!note.getEffect().isTapping()); } } /** * Agrega un slapping */ public void changeSlapping(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setSlapping(!note.getEffect().isSlapping()); } } /** * Agrega un popping */ public void changePopping(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setPopping(!note.getEffect().isPopping()); } } /** * Agrega un bend */ public void changeBendNote(TGMeasure measure,long start,int string,TGEffectBend bend){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setBend(bend); } } /** * Agrega un tremoloBar */ public void changeTremoloBar(TGMeasure measure,long start,int string,TGEffectTremoloBar tremoloBar){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setTremoloBar(tremoloBar); } } /** * Agrega un GhostNote */ public void changeGhostNote(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setGhostNote(!note.getEffect().isGhostNote()); } } /** * Agrega un AccentuatedNote */ public void changeAccentuatedNote(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setAccentuatedNote(!note.getEffect().isAccentuatedNote()); } } /** * Agrega un GhostNote */ public void changeHeavyAccentuatedNote(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setHeavyAccentuatedNote(!note.getEffect().isHeavyAccentuatedNote()); } } /** * Agrega un harmonic */ public void changeHarmonicNote(TGMeasure measure,long start,int string,TGEffectHarmonic harmonic){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setHarmonic(harmonic); } } /** * Agrega un grace */ public void changeGraceNote(TGMeasure measure,long start,int string,TGEffectGrace grace){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setGrace(grace); } } /** * Agrega un trill */ public void changeTrillNote(TGMeasure measure,long start,int string,TGEffectTrill trill){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setTrill(trill); } } /** * Agrega un tremolo picking */ public void changeTremoloPicking(TGMeasure measure,long start,int string,TGEffectTremoloPicking tremoloPicking){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setTremoloPicking(tremoloPicking); } } /** * Agrega un fadeIn */ public void changeFadeIn(TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.getEffect().setFadeIn(!note.getEffect().isFadeIn()); } } /** * Cambia el Velocity */ public void changeVelocity(int velocity,TGMeasure measure,long start,int string){ TGNote note = getNote(measure,start,string); if(note != null){ note.setVelocity(velocity); } } /* public static List createDurations(TGFactory factory,long time){ List durations = new ArrayList(); TGDuration tempDuration = factory.newDuration(); tempDuration.setValue(TGDuration.WHOLE); tempDuration.setDotted(true); long tempTime = time; boolean finish = false; while(!finish){ long currentDurationTime = tempDuration.getTime(); if(currentDurationTime <= tempTime){ durations.add(tempDuration.clone(factory)); tempTime -= currentDurationTime; }else{ if(tempDuration.isDotted()){ tempDuration.setDotted(false); }else{ tempDuration.setValue(tempDuration.getValue() * 2); tempDuration.setDotted(true); } } if(tempDuration.getValue() > TGDuration.SIXTY_FOURTH){ finish = true; } } return durations; } */ public static List createDurations(TGFactory factory,long time){ List durations = new ArrayList(); TGDuration minimum = factory.newDuration(); minimum.setValue(TGDuration.SIXTY_FOURTH); minimum.setDotted(false); minimum.setDoubleDotted(false); minimum.getDivision().setEnters(3); minimum.getDivision().setTimes(2); long missingTime = time; while( missingTime > minimum.getTime() ){ TGDuration duration = TGDuration.fromTime(factory, missingTime, minimum , 10); durations.add( duration.clone(factory) ); missingTime -= duration.getTime(); } return durations; } /** * Retorna el Siguiente Componente */ public TGVoice getNextVoice(List beats,TGBeat beat, int index) { TGVoice next = null; for (int i = 0; i < beats.size(); i++) { TGBeat current = (TGBeat) beats.get(i); if (current.getStart() > beat.getStart() && !current.getVoice(index).isEmpty()) { if (next == null) { next = current.getVoice(index); } else if (current.getStart() < next.getBeat().getStart()) { next = current.getVoice(index); } /*else if (current.getStart() == next.getBeat().getStart() && current.getDuration().getTime() <= next.getDuration().getTime()) { next = current.getVoice(index); }*/ } } return next; } /** * Retorna el Componente Anterior */ public TGVoice getPreviousVoice(List beats,TGBeat beat, int index) { TGVoice previous = null; for (int i = 0; i < beats.size(); i++) { TGBeat current = (TGBeat) beats.get(i); if (current.getStart() < beat.getStart() && !current.getVoice(index).isEmpty()) { if (previous == null) { previous = current.getVoice(index); } else if (current.getStart() > previous.getBeat().getStart()) { previous = current.getVoice(index); } /*else if (current.getStart() == previous.getBeat().getStart() && current.getDuration().getTime() <= previous.getDuration().getTime()) { previous = current.getVoice(index); }*/ } } return previous; } /** * Retorna el Primer Componente */ public TGVoice getFirstVoice(List beats, int index) { TGVoice first = null; for (int i = 0; i < beats.size(); i++) { TGBeat current = (TGBeat) beats.get(i); if ( (first == null || current.getStart() < first.getBeat().getStart() ) && !current.getVoice(index).isEmpty()) { first = current.getVoice(index); } } return first; } /** * Retorna el Ultimo Componente */ public TGVoice getLastVoice(List beats, int index) { TGVoice last = null; for (int i = 0; i < beats.size(); i++) { TGBeat current = (TGBeat) beats.get(i); if ( (last == null || last.getBeat().getStart() < current.getStart()) && !current.getVoice(index).isEmpty() ) { last = current.getVoice(index); } } return last; } /** * Retorna el Siguiente Componente */ public TGVoice getNextRestVoice(List beats,TGVoice voice) { TGVoice next = getNextVoice(beats, voice.getBeat(), voice.getIndex()); while(next != null && !next.isRestVoice()){ next = getNextVoice(beats, next.getBeat(), next.getIndex()); } return next; } public List getVoicesBeforeEnd(List beats,long fromStart, int index) { List list = new ArrayList(); Iterator it = beats.iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat)it.next(); if (beat.getStart() >= fromStart) { TGVoice voice = beat.getVoice(index); if(!voice.isEmpty()){ list.add(voice); } } } return list; } public void addSilence(TGMeasure measure,long start, TGDuration duration, int voice){ TGBeat beat = getBeat(measure, start); if(beat != null){ addSilence(beat, duration, voice); } } public void addSilence(TGBeat beat, TGDuration duration, int voice){ addSilence(beat, duration, beat.getStart(),voice); } public void addSilence(TGBeat beat, TGDuration duration, long start, int voice){ boolean emptyVoice = beat.getVoice( voice ).isEmpty(); if( emptyVoice ){ beat.getVoice( voice ).setEmpty( false ); } //Verifico si entra en el compas if(validateDuration(beat.getMeasure(),beat, voice, duration,true,true)){ //Borro lo que haya en la misma posicion //removeNote(beat.getMeasure(),beat.getStart(),voice, note.getString()); duration.copy(beat.getVoice(voice).getDuration()); //trato de agregar un silencio similar al lado tryChangeSilenceAfter(beat.getMeasure(),beat.getVoice(voice)); // Despues de cambiar la duracion, verifico si hay un beat mejor para agregar el silencio. TGVoice realVoice = beat.getVoice(voice); if(realVoice.getBeat().getStart() != start){ TGVoice beatIn = getVoiceIn(realVoice.getBeat().getMeasure(), start, voice); if( beatIn != null ) { realVoice = beatIn; } } realVoice.setEmpty(false); }else{ beat.getVoice( voice ).setEmpty( emptyVoice ); } } public void removeVoice(TGVoice voice){ voice.setEmpty(true); // Remove the beat If all voices are empty TGBeat beat = voice.getBeat(); for(int i = 0; i < beat.countVoices(); i ++){ if( !beat.getVoice(i).isEmpty() ){ return; } } this.removeBeat(beat); } public void removeVoice(TGVoice voice,boolean moveNextVoices){ removeVoice(voice); if(moveNextVoices){ long start = voice.getBeat().getStart(); long length = voice.getDuration().getTime(); TGVoice next = getNextVoice(voice.getBeat().getMeasure().getBeats(),voice.getBeat(),voice.getIndex()); if(next != null){ length = next.getBeat().getStart() - start; } moveVoices(voice.getBeat().getMeasure(),start + length,-length, voice.getIndex(), voice.getDuration()); } } public void removeVoice(TGMeasure measure,long start,int index, boolean moveNextComponents){ TGBeat beat = getBeat(measure, start); if(beat != null){ removeVoice(beat.getVoice(index), moveNextComponents); } } public void removeVoicesOutOfTime(TGMeasure measure){ List voicesToRemove = new ArrayList(); long mStart = measure.getStart(); long mEnd = mStart + measure.getLength(); Iterator beats = measure.getBeats().iterator(); while(beats.hasNext()){ TGBeat beat = (TGBeat)beats.next(); for( int v = 0; v < beat.countVoices() ; v ++){ TGVoice voice = beat.getVoice( v ); if(!voice.isEmpty()){ if( beat.getStart() < mStart || (beat.getStart() + voice.getDuration().getTime()) > mEnd){ voicesToRemove.add( voice ); } } } } Iterator it = voicesToRemove.iterator(); while(it.hasNext()){ TGVoice voice = (TGVoice)it.next(); this.removeVoice( voice ); } } public void removeMeasureVoices(TGMeasure measure,int index){ boolean hasNotes = false; List voices = new ArrayList(); Iterator it = measure.getBeats().iterator(); while(it.hasNext()){ TGBeat beat = (TGBeat)it.next(); TGVoice voice = beat.getVoice(index); if(voice.isRestVoice()){ voices.add(voice); }else if(!voice.isEmpty()){ hasNotes = true; break; } } if( !hasNotes ){ it = voices.iterator(); while(it.hasNext()){ TGVoice voice = (TGVoice)it.next(); this.removeVoice( voice ); } } } public void changeVoiceDirection( TGVoice voice , int direction){ voice.setDirection( direction ); } public void changeDuration(TGMeasure measure,TGBeat beat,TGDuration duration,int voice, boolean tryMove){ //obtengo la duracion vieja TGDuration oldDuration = beat.getVoice(voice).getDuration().clone(getSongManager().getFactory()); //si no entra vuelvo a dejar la vieja if(validateDuration(measure,beat, voice, duration,tryMove,false)){ //se lo agrego a todas las notas en la posicion beat.getVoice(voice).setDuration(duration.clone(getSongManager().getFactory())); //trato de agregar un silencio similar al lado tryChangeSilenceAfter(measure,beat.getVoice(voice)); }else{ oldDuration.copy( beat.getVoice(voice).getDuration() ); } } public void tryChangeSilenceAfter(TGMeasure measure,TGVoice voice){ autoCompleteSilences(measure); TGVoice nextVoice = getNextVoice(measure.getBeats(),voice.getBeat(),voice.getIndex()); long beatEnd = (voice.getBeat().getStart() + voice.getDuration().getTime()); long measureEnd = (measure.getStart() + measure.getLength()); if(nextVoice != null && !nextVoice.isEmpty() && nextVoice.isRestVoice() && beatEnd <= measureEnd){ long theMove = (getRealStart(measure,beatEnd)) - getRealStart(measure,nextVoice.getBeat().getStart()); if((nextVoice.getBeat().getStart() + theMove) < measureEnd && (nextVoice.getBeat().getStart() + nextVoice.getDuration().getTime() + theMove) <= measureEnd){ moveVoice(nextVoice,theMove); changeDuration(measure,nextVoice.getBeat(),voice.getDuration().clone(getSongManager().getFactory()),nextVoice.getIndex(),false); } } } private void moveVoices(List voices,long theMove){ /* Iterator it = voices.iterator(); while(it.hasNext()){ TGVoice voice = (TGVoice)it.next(); moveVoice(voice,theMove); } */ int count = voices.size(); for( int i = 0 ; i < count ; i ++ ){ TGVoice voice = (TGVoice)voices.get( (theMove < 0 ? i : ( (count - 1) - i ) ) ); moveVoice(voice,theMove); } } public void moveVoice(TGVoice voice, long theMove){ long newStart = (voice.getBeat().getStart() + theMove); TGBeat newBeat = getBeat(voice.getBeat().getMeasure(),newStart); if( newBeat == null ){ newBeat = getSongManager().getFactory().newBeat(); newBeat.setStart( newStart ); addBeat(voice.getBeat().getMeasure(), newBeat); } this.moveVoice(voice, newBeat); } public void moveVoice(TGVoice voice, TGBeat beat){ TGBeat currentBeat = voice.getBeat(); if(!currentBeat.equals(beat)){ if(currentBeat.getVoice( voice.getIndex() ).equals( voice )){ if ( currentBeat.isTextBeat() && isUniqueVoice(voice, false) ){ beat.setText( currentBeat.getText() ); currentBeat.removeText(); } if( isUniqueVoice(voice, true) ){ if( currentBeat.isChordBeat() ){ beat.setChord( currentBeat.getChord() ); currentBeat.removeChord(); } if( currentBeat.getStroke().getDirection() != TGStroke.STROKE_NONE ){ currentBeat.getStroke().copy( beat.getStroke() ); currentBeat.getStroke().setDirection(TGStroke.STROKE_NONE); } } // Make sure to remove another voice instance from old beat. TGVoice newVoice = getSongManager().getFactory().newVoice(voice.getIndex()); currentBeat.setVoice( voice.getIndex(), newVoice); this.removeVoice(newVoice); } beat.setVoice( voice.getIndex() , voice); } } public boolean validateDuration(TGMeasure measure,TGBeat beat,int voice, TGDuration duration,boolean moveNextBeats, boolean setCurrentDuration){ int errorMargin = 10; this.orderBeats(measure); long measureStart = measure.getStart(); long measureEnd = (measureStart + measure.getLength()); long beatStart = beat.getStart(); long beatLength = duration.getTime(); long beatEnd = (beatStart + beatLength); List beats = measure.getBeats(); //Verifico si hay un beat en el mismo lugar, y comparo las duraciones. TGBeat currentBeat = getBeat(measure,beatStart); TGVoice currentVoice = null; if(currentBeat != null){ currentVoice = currentBeat.getVoice(voice); if(!currentVoice.isEmpty() && beatLength <= currentVoice.getDuration().getTime()){ return true; } } //Verifico si hay lugar para meter el beat TGVoice nextVoice = getNextVoice(beats,beat, voice); if(currentVoice == null || currentVoice.isEmpty()){ if((nextVoice == null || nextVoice.isEmpty()) && beatEnd < (measureEnd + errorMargin)){ return true; } if((nextVoice != null && !nextVoice.isEmpty()) && beatEnd < (nextVoice.getBeat().getStart() + errorMargin)){ return true; } } // Busca si hay espacio disponible de silencios entre el componente y el el que le sigue.. si encuentra lo borra if(nextVoice != null && !nextVoice.isEmpty() && nextVoice.isRestVoice()){ //Verifico si lo que sigue es un silencio. y lo borro long nextBeatEnd = 0; List nextBeats = new ArrayList(); while(nextVoice != null && !nextVoice.isEmpty() && nextVoice.isRestVoice() && !nextVoice.getBeat().isTextBeat()){ nextBeats.add(nextVoice); nextBeatEnd = nextVoice.getBeat().getStart() + nextVoice.getDuration().getTime(); nextVoice = getNextVoice(beats,nextVoice.getBeat(), voice); } if(nextVoice == null || nextVoice.isEmpty()){ nextBeatEnd = measureEnd; }else if(!nextVoice.isRestVoice() || nextVoice.getBeat().isTextBeat()){ nextBeatEnd = nextVoice.getBeat().getStart(); } if(beatEnd <= (nextBeatEnd + errorMargin)){ while(!nextBeats.isEmpty()){ TGVoice currVoice = (TGVoice)nextBeats.get(0); nextBeats.remove(currVoice); removeVoice(currVoice, false); } return true; } } // Busca si hay espacio disponible de silencios entre el componente y el final.. si encuentra mueve todo if(moveNextBeats){ nextVoice = getNextVoice(beats,beat, voice); if(nextVoice != null){ long requiredLength = (beatLength - (nextVoice.getBeat().getStart() - beatStart)); long nextSilenceLength = 0; TGVoice nextRestBeat = getNextRestVoice(beats, beat.getVoice(voice)); while(nextRestBeat != null){ nextSilenceLength += nextRestBeat.getDuration().getTime(); nextRestBeat = getNextRestVoice(beats, nextRestBeat); } if(requiredLength <= (nextSilenceLength + errorMargin)){ List voices = getVoicesBeforeEnd(measure.getBeats(),nextVoice.getBeat().getStart(), voice); while(!voices.isEmpty()){ TGVoice currentVocie = (TGVoice)voices.get(0); if(currentVocie.isRestVoice()){ requiredLength -= currentVocie.getDuration().getTime(); removeVoice(currentVocie, false); }else if(requiredLength > 0){ moveVoice(currentVocie,requiredLength); } voices.remove(0); } return true; } } } // como ultimo intento, asigno la duracion de cualquier componente existente en el lugar. if(setCurrentDuration && currentVoice != null && !currentVoice.isEmpty()){ currentVoice.getDuration().copy( duration ); return true; } return false; } /* public boolean moveVoices(TGMeasure measure,long start,long theMove, int voiceIndex, TGDuration fillDuration){ if( theMove == 0 ){ return false; } boolean success = true; long measureStart = measure.getStart(); long measureEnd = (measureStart + measure.getLength()); // Muevo los componentes List voicesToMove = getVoicesBeforeEnd(measure.getBeats(),start, voiceIndex); moveVoices(voicesToMove,theMove); if(success){ List voicesToRemove = new ArrayList(); List beats = new ArrayList(measure.getBeats()); // Verifica los silencios a eliminar al principio del compas TGVoice first = getFirstVoice( beats, voiceIndex ); while(first != null && first.isRestVoice() && first.getBeat().getStart() < measureStart){ beats.remove(first); voicesToRemove.add(first); first = getNextVoice( beats,first.getBeat(), voiceIndex); } // Verifica los silencios a eliminar al final del compas TGVoice last = getLastVoice(beats, voiceIndex); TGDuration lastDuration = (last != null ? last.getDuration() : null); while(last != null && lastDuration != null && last.isRestVoice() && (last.getBeat().getStart() + lastDuration.getTime() ) > measureEnd ){ beats.remove(last); voicesToRemove.add(last); last = getPreviousVoice(beats,last.getBeat(), voiceIndex); lastDuration = (last != null ? last.getDuration() : null); } // Si el primer o ultimo componente, quedan fuera del compas, entonces el movimiento no es satisfactorio if(first != null && last != null && lastDuration != null){ if(first.getBeat().getStart() < measureStart || (last.getBeat().getStart() + lastDuration.getTime()) > measureEnd){ success = false; } } if(success){ // Elimino los silencios que quedaron fuera del compas. Iterator it = voicesToRemove.iterator(); while( it.hasNext() ){ TGVoice beat = (TGVoice)it.next(); removeVoice(beat); } // Se crean silencios en los espacios vacios, si la duracion fue especificada. if( fillDuration != null ){ if( theMove < 0 ){ last = getLastVoice(measure.getBeats(), voiceIndex); lastDuration = (last != null ? last.getDuration() : null); long beatStart = ( (last != null && lastDuration != null ? last.getBeat().getStart() + lastDuration.getTime() : start ) ); if( (beatStart + fillDuration.getTime()) <= measureEnd ){ boolean beatNew = false; TGBeat beat = getBeat(measure, beatStart); if(beat == null){ beat = getSongManager().getFactory().newBeat(); beat.setStart( beatStart ); beatNew = true; } TGVoice voice = beat.getVoice(voiceIndex); voice.setEmpty(false); fillDuration.copy( voice.getDuration() ); if( beatNew ){ addBeat(measure, beat ); } } } else{ first = getFirstVoice(getBeatsBeforeEnd(measure.getBeats(),start), voiceIndex); if( (start + fillDuration.getTime()) <= (first != null ?first.getBeat().getStart() : measureEnd ) ){ boolean beatNew = false; TGBeat beat = getBeat(measure, start); if(beat == null){ beat = getSongManager().getFactory().newBeat(); beat.setStart( start ); beatNew = true; } TGVoice voice = beat.getVoice(voiceIndex); voice.setEmpty(false); fillDuration.copy( voice.getDuration() ); if( beatNew ){ addBeat(measure, beat ); } } } } } } // Si el movimiento no es satisfactorio, regreso todo como estaba if(! success ){ moveVoices(voicesToMove,-theMove); } this.removeEmptyBeats(measure); return success; } */ public boolean moveVoices(TGMeasure measure,long start,long theMove, int voiceIndex, TGDuration fillDuration){ if( theMove == 0 ){ return false; } boolean success = true; long measureStart = measure.getStart(); long measureEnd = (measureStart + measure.getLength()); List voicesToMove = getVoicesBeforeEnd(measure.getBeats(),start, voiceIndex); List voicesToRemove = new ArrayList(); List currentBeats = getBeatsBeforeEnd(measure.getBeats(), start); // Verifica los silencios a eliminar al principio del compas TGVoice first = getFirstVoice( currentBeats, voiceIndex ); while(first != null && first.isRestVoice() && (!first.getBeat().isTextBeat() || !isUniqueVoice(first,false)) && (first.getBeat().getStart() + theMove) < measureStart){ currentBeats.remove(first.getBeat()); voicesToRemove.add(first); first = getNextVoice( currentBeats,first.getBeat(), voiceIndex); } // Verifica los silencios a eliminar al final del compas TGVoice last = getLastVoice(currentBeats, voiceIndex); TGDuration lastDuration = (last != null ? last.getDuration() : null); while(last != null && lastDuration != null && last.isRestVoice() && (!last.getBeat().isTextBeat() || !isUniqueVoice(last,false)) && (last.getBeat().getStart() + lastDuration.getTime() + theMove) > measureEnd ){ currentBeats.remove(last.getBeat()); voicesToRemove.add(last); last = getPreviousVoice(currentBeats,last.getBeat(), voiceIndex); lastDuration = (last != null ? last.getDuration() : null); } // Si el primer o ultimo componente, quedan fuera del compas, entonces el movimiento no es satisfactorio if(first != null && last != null && lastDuration != null){ if((first.getBeat().getStart() + theMove) < measureStart || (last.getBeat().getStart() + lastDuration.getTime() + theMove) > measureEnd){ success = false; } } if(success){ this.moveVoices(voicesToMove,theMove); // Elimino los silencios que quedaron fuera del compas. Iterator it = voicesToRemove.iterator(); while( it.hasNext() ){ TGVoice beat = (TGVoice)it.next(); removeVoice(beat); } // Se crean silencios en los espacios vacios, si la duracion fue especificada. if( fillDuration != null ){ if( theMove < 0 ){ last = getLastVoice(measure.getBeats(), voiceIndex); lastDuration = (last != null ? last.getDuration() : null); long beatStart = ( (last != null && lastDuration != null ? last.getBeat().getStart() + lastDuration.getTime() : start ) ); if( (beatStart + fillDuration.getTime()) <= measureEnd ){ boolean beatNew = false; TGBeat beat = getBeat(measure, beatStart); if(beat == null){ beat = getSongManager().getFactory().newBeat(); beat.setStart( beatStart ); beatNew = true; } TGVoice voice = beat.getVoice(voiceIndex); voice.setEmpty(false); fillDuration.copy( voice.getDuration() ); if( beatNew ){ addBeat(measure, beat ); } } } else{ first = getFirstVoice(getBeatsBeforeEnd(measure.getBeats(),start), voiceIndex); if( (start + fillDuration.getTime()) <= (first != null ?first.getBeat().getStart() : measureEnd ) ){ boolean beatNew = false; TGBeat beat = getBeat(measure, start); if(beat == null){ beat = getSongManager().getFactory().newBeat(); beat.setStart( start ); beatNew = true; } TGVoice voice = beat.getVoice(voiceIndex); voice.setEmpty(false); fillDuration.copy( voice.getDuration() ); if( beatNew ){ addBeat(measure, beat ); } } } } // Borro todos los beats que quedaron vacios. this.removeEmptyBeats(measure); } return success; } public boolean isUniqueVoice(TGVoice voice, boolean ignoreRests){ TGBeat beat = voice.getBeat(); for( int v = 0 ; v < beat.countVoices() ; v ++ ){ if( v != voice.getIndex() ){ TGVoice currentVoice = beat.getVoice( v ); if( !currentVoice.isEmpty() && (!ignoreRests || !currentVoice.isRestVoice())){ return false; } } } return true; } public void transposeNotes( TGMeasure measure, int transposition , boolean tryKeepString, boolean applyToChords, int applyToString){ if( transposition != 0 ){ if( measure != null ){ TGTrack track = measure.getTrack(); if( track != null ){ List strings = getSortedStringsByValue(track, ( transposition > 0 ? 1 : -1 ) ) ; for( int i = 0 ; i < measure.countBeats() ; i ++ ){ TGBeat beat = measure.getBeat( i ); transposeNotes( beat, strings, transposition , tryKeepString, applyToChords, applyToString ); } } } } } public void transposeNotes( TGMeasure measure, int[] transpositionStrings , boolean tryKeepString , boolean applyToChords){ if( transpositionStrings != null && transpositionStrings.length > 0 ){ if( measure != null ){ TGTrack track = measure.getTrack(); if( track != null ){ TGNote[] notes = new TGNote[ transpositionStrings.length ]; for( int b = 0 ; b < measure.countBeats() ; b ++ ){ TGBeat beat = measure.getBeat( b ); for( int n = 0 ; n < notes.length ; n ++ ){ notes[ n ] = getNote( beat, (n + 1) ); } for( int i = 0 ; i < notes.length ; i ++ ){ if( notes[ i ] != null ){ int transposition = transpositionStrings[ i ]; if( transposition != 0 ){ int applyToString = notes[i].getString(); List strings = getSortedStringsByValue(track, ( transposition > 0 ? 1 : -1 ) ) ; transposeNotes( beat, strings, transposition , tryKeepString, applyToChords, applyToString ); } } } } } } } } public void transposeNotes( TGBeat beat, List strings, int transposition , boolean tryKeepString, boolean applyToChord, int applyToString){ if( transposition != 0 ){ List notes = getNotes(beat); int stringCount = strings.size(); for( int i = 0 ; i < stringCount ; i ++ ){ TGString string = (TGString)strings.get( (stringCount - i) - 1 ); if( applyToString == -1 || string.getNumber() == applyToString ){ TGNote note = null; for( int n = 0 ; n < notes.size() ; n ++ ){ TGNote current = (TGNote)notes.get( n ); if( current.getString() == string.getNumber() ){ note = current; } } if( note != null ){ transposeNote(note, notes, strings, transposition, tryKeepString, false ); } if( applyToChord && beat.isChordBeat() ){ TGChord chord = beat.getChord(); int chordString = ( string.getNumber() - 1 ); if( chord.getFretValue( chordString ) >= 0 ){ transposeChordNote(chord, chordString, strings, transposition, tryKeepString, false); } chord.setFirstFret( -1 ); } } } } } private boolean transposeNote( TGNote note, List notes, List strings , int transposition , boolean tryKeepString, boolean forceChangeString ){ boolean canTransposeFret = false; int maximumFret = 29; int transposedFret = ( note.getValue() + transposition ); // Check if transposition could be done without change the string if( transposedFret >= 0 && transposedFret <= maximumFret ){ // Do it now if keep string is the priority if( !forceChangeString && tryKeepString ){ note.setValue( transposedFret ); return true; } canTransposeFret = true; } // Check the current string index for this note int stringIndex = -1; for( int i = 0 ; i < strings.size() ; i ++ ){ TGString string = ( TGString ) strings.get( i ); if( string.getNumber() == note.getString() ){ stringIndex = i; break; } } // Try to change the string of the note TGString string = ( TGString ) strings.get( stringIndex ); int transposedValue = ( string.getValue() + note.getValue() + transposition ); int nextStringIndex = ( stringIndex + 1 ); while( nextStringIndex >= 0 && nextStringIndex < strings.size() ){ TGString nextString = ( TGString ) strings.get( nextStringIndex ); TGNote nextOwner = null; for( int i = 0 ; i < notes.size() ; i ++ ){ TGNote nextNote = (TGNote) notes.get( i ); if( nextNote.getString() == nextString.getNumber() ){ nextOwner = nextNote; } } int transposedStringFret = ( transposedValue - nextString.getValue() ); if( transposedStringFret >= 0 && transposedStringFret <= maximumFret ){ if( nextOwner != null ){ if( ! transposeNote(nextOwner, notes, strings, 0 , tryKeepString , !canTransposeFret ) ){ // Note was removed. nextOwner = null ; } } if( nextOwner == null || nextOwner.getString() != nextString.getNumber() ){ note.setValue( transposedStringFret ); note.setString( nextString.getNumber() ); return true; } } nextStringIndex ++; } // Keep using same string if it's possible if( !forceChangeString && canTransposeFret ){ note.setValue( transposedFret ); return true; } // If note can't be transposed, it must be removed. notes.remove( note ); removeNote(note); return false; } private boolean transposeChordNote( TGChord chord, int chordString, List strings , int transposition , boolean tryKeepString, boolean forceChangeString ){ boolean canTransposeFret = false; int maximumFret = 24; int noteValue = chord.getFretValue( chordString ); int noteString = (chordString + 1 ); int transposedFret = ( noteValue + transposition ); // Check if transposition could be done without change the string if( transposedFret >= 0 && transposedFret <= maximumFret ){ // Do it now if keep string is the priority if( !forceChangeString && tryKeepString ){ chord.addFretValue(chordString, transposedFret); return true; } canTransposeFret = true; } // Check the current string index for this note int stringIndex = -1; for( int i = 0 ; i < strings.size() ; i ++ ){ TGString string = ( TGString ) strings.get( i ); if( string.getNumber() == noteString ){ stringIndex = i; break; } } // Try to change the string of the note TGString string = ( TGString ) strings.get( stringIndex ); int transposedValue = ( string.getValue() + noteValue + transposition ); int nextStringIndex = ( stringIndex + 1 ); while( nextStringIndex >= 0 && nextStringIndex < strings.size() ){ TGString nextString = ( TGString ) strings.get( nextStringIndex ); int nextChordString = -1; for( int i = 0 ; i < chord.countStrings() ; i ++ ){ if( (i + 1) == nextString.getNumber() ){ if( chord.getFretValue( i ) >= 0 ){ nextChordString = i; } } } int transposedStringFret = ( transposedValue - nextString.getValue() ); if( transposedStringFret >= 0 && transposedStringFret <= maximumFret ){ if( nextChordString >= 0 ){ transposeChordNote(chord, nextChordString , strings, 0 , tryKeepString , !canTransposeFret ); } if( nextChordString < 0 || chord.getFretValue( nextChordString ) < 0 ){ chord.addFretValue( chordString , -1 ); chord.addFretValue( ( nextString.getNumber() - 1 ) , transposedStringFret ); return true; } } nextStringIndex ++; } // Keep using same string if it's possible if( !forceChangeString && canTransposeFret ){ chord.addFretValue( chordString , transposedFret ); return true; } // If note can't be transposed, it must be removed. chord.addFretValue( chordString , -1 ); return false; } public List getSortedStringsByValue( TGTrack track , final int direction ){ List strings = new ArrayList(); for( int number = 1 ; number <= track.stringCount() ; number ++ ){ strings.add( track.getString( number ) ); } Collections.sort( strings , new Comparator() { public int compare(Object o1, Object o2) { if( o1 != null && o2 != null && o1 instanceof TGString && o2 instanceof TGString ){ TGString s1 = (TGString)o1; TGString s2 = (TGString)o2; int status = ( s1.getValue() - s2.getValue() ); if( status == 0 ){ return 0; } return ( (status * direction) > 0 ? 1 : -1 ); } return 0; } }); return strings; } }