package org.herac.tuxguitar.song.managers; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.herac.tuxguitar.gui.editors.tab.TGBeatImpl; import org.herac.tuxguitar.gui.editors.tab.TGNoteImpl; import org.herac.tuxguitar.gui.editors.tab.TGVoiceImpl; import org.herac.tuxguitar.song.models.Direction; import org.herac.tuxguitar.song.models.TGBeat; import org.herac.tuxguitar.song.models.TGChord; 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.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.BendingEffect; import org.herac.tuxguitar.song.models.effects.HarmonicEffect; import org.herac.tuxguitar.song.models.effects.TGEffectGrace; import org.herac.tuxguitar.song.models.effects.TGEffectTremoloPicking; import org.herac.tuxguitar.song.models.effects.TGEffectTrill; public class TGMeasureManager { public static List<TGDuration> createDurations(long time) { List<TGDuration> durations = new ArrayList<TGDuration>(); TGDuration minimum = new TGDuration(); minimum.setValue(TGDuration.SIXTY_FOURTH); minimum.setDotted(false); minimum.setDoubleDotted(false); minimum.setDivision(TGDivisionType.DEFAULT); long missingTime = time; while (missingTime > minimum.getTime()) { TGDuration duration = TGDuration.fromTime(missingTime, minimum, 10); durations.add(duration.clone()); missingTime -= duration.getTime(); } return durations; } private TGSongManager songManager; public TGMeasureManager(TGSongManager songManager) { this.songManager = songManager; } /** * 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); // } } /** * Agrega el acorde al compas */ public void addChord(TGBeat beat, TGChord chord) { beat.removeChord(); beat.setChord(chord); } /** * 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); } } 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); } beat.getVoice(voice).setDuration(duration.clone()); // 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 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 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()); beat.getVoice(voice).setDuration(duration.clone()); // 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 addSilence(TGMeasure measure, long start, TGDuration duration, int voice) { TGBeat beat = getBeat(measure, start); if (beat != null) { addSilence(beat, duration, voice); } } /** * Agrega el texto al compas */ public void addText(TGBeat beat, TGText text) { beat.removeText(); if (!text.isEmpty()) { beat.setText(text); } } /** * 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); } } /** * 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); } } /** * 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 bend */ public void changeBendNote(TGMeasure measure, long start, int string, BendingEffect bend) { TGNote note = getNote(measure, start, string); if (note != null) { note.getEffect().setBend(bend); } } /** * Agrega una nota muerta */ public void changeDeadNote(TGNote note) { note.getEffect().setDeadNote(!note.getEffect().isDeadNote()); note.setTiedNote(false); } public void changeDuration(TGMeasure measure, TGBeat beat, TGDuration duration, int voice, boolean tryMove) { // obtengo la duracion vieja TGDuration oldDuration = beat.getVoice(voice).getDuration().clone(); // 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()); // trato de agregar un silencio similar al lado tryChangeSilenceAfter(measure, beat.getVoice(voice)); } else { beat.getVoice(voice).setDuration(oldDuration.clone()); } } /** * 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()); } } /** * 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 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 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 harmonic */ public void changeHarmonicNote(TGMeasure measure, long start, int string, HarmonicEffect harmonic) { TGNote note = getNote(measure, start, string); if (note != null) { note.getEffect().setHarmonic(harmonic); } } /** * 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 let-ring */ public void changeLetRing(TGMeasure measure, long start, int string) { TGNote note = getNote(measure, start, string); if (note != null) { note.getEffect().setLetRing(!note.getEffect().isLetRing()); } } /** * 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 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 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 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 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()); } } /** * 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 tremoloBar */ public void changeTremoloBar(TGMeasure measure, long start, int string, BendingEffect tremoloBar) { TGNote note = getNote(measure, start, string); if (note != null) { note.getEffect().setTremoloBar(tremoloBar); } } /** * 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; } */ /** * 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 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); } } /** * 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; } */ /** * 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()); } } public void changeVoiceDirection(TGVoice voice, Direction direction) { voice.setDirection(direction); } public void cleanBeat(TGBeat beat) { beat.getStroke().setDirection(Direction.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 cleanMeasure(TGMeasure measure) { while (measure.countBeats() > 0) { removeBeat(measure.getBeat(0)); } } public void cleanVoiceNotes(TGVoice voice) { if (!voice.isEmpty()) { while (voice.getNotes().size() > 0) { TGNote note = voice.getNote(0); removeNote(note); } } } /** * Crea Silencios temporarios en base a length */ private void createSilences(TGMeasure measure, long start, long length, int voiceIndex) { long nextStart = start; List<TGDuration> durations = createDurations(length); for (final TGDuration duration : durations) { boolean isNew = false; long beatStart = getRealStart(measure, nextStart); TGBeat beat = getBeat(measure, beatStart); if (beat == null) { beat = new TGBeatImpl(); 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); voice.setDuration(duration.clone()); if (isNew) { addBeat(measure, beat); } // temporal // beat.getVoice(0).setEmpty(false); // beat.getVoice(1).setEmpty(false); // /temporal nextStart += duration.getTime(); } } /** * Retorna las Nota en la posicion y cuerda */ public TGBeat getBeat(TGMeasure measure, long start) { for (final TGBeat beat : measure.getBeats()) { if (beat.getStart() == start) { return beat; } } return null; } public TGBeat getBeat(TGTrack track, long start) { for (final TGMeasure measure : track.getMeasures()) { for (final TGBeat beat : measure.getBeats()) { 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; for (final TGBeat beat : measure.getBeats()) { TGDuration duration = getMinimumDuration(beat); if (beat.getStart() <= start && (beat.getStart() + duration.getTime() > start)) { if (beatIn == null || beat.getStart() > beatIn.getStart()) { beatIn = beat; } } } return beatIn; } public List<TGBeat> getBeatsBeetween(List<TGBeat> beats, long p1, long p2) { List<TGBeat> list = new ArrayList<TGBeat>(); for (final TGBeat current : beats) { if (current.getStart() >= p1 && current.getStart() < p2) { list.add(current); } } return list; } /** * Retorna Todos los desde Start hasta el final del compas */ public List<TGBeat> getBeatsBeforeEnd(List<TGBeat> beats, long fromStart) { List<TGBeat> list = new ArrayList<TGBeat>(); for (final TGBeat current : beats) { if (current.getStart() >= fromStart) { list.add(current); } } return list; } /** * 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; } /** * Retorna el Primer Componente */ public TGBeat getFirstBeat(List<TGBeat> 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 Primer Componente */ public TGVoice getFirstVoice(List<TGBeat> 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 TGBeat getLastBeat(List<TGBeat> 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 Ultimo Componente */ public TGVoice getLastVoice(List<TGBeat> 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; } 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; } /** * Retorna el Siguiente Componente */ public TGBeat getNextBeat(List<TGBeat> 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; } 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.getNotes().size(); i++) { TGNote current = voice.getNote(i); if (current.getString() == string) { return current; } } } next = getNextBeat(measure.getBeats(), next); } } return null; } /** * Retorna el Siguiente Componente */ public TGVoice getNextRestVoice(List<TGBeat> 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; } /** * Retorna el Siguiente Componente */ public TGVoice getNextVoice(List<TGBeat> 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 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; } /** * 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; } public TGNote getNote(TGVoice voice, int string) { for (final TGNote note : voice.getNotes()) { if (note.getString() == string) { return note; } } return null; } /** * Retorna Todas las Notas en el pulso */ public List<TGNote> getNotes(TGBeat beat) { List<TGNote> notes = new ArrayList<TGNote>(); if (beat != null) { for (int v = 0; v < beat.countVoices(); v++) { TGVoice voice = beat.getVoice(v); if (!voice.isEmpty() && !voice.isRestVoice()) { for (final TGNote note : voice.getNotes()) { notes.add(note); } } } } return notes; } /** * Retorna Todas las Notas en la posicion Start */ public List<TGNote> getNotes(TGMeasure measure, long start) { List<TGNote> notes = new ArrayList<TGNote>(); TGBeat beat = getBeat(measure, start); if (beat != null) { for (int v = 0; v < beat.countVoices(); v++) { TGVoice voice = beat.getVoice(v); for (final TGNote note : voice.getNotes()) { notes.add(note); } } } return notes; } /** * Retorna el Componente Anterior */ public TGBeat getPreviousBeat(List<TGBeat> 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; } 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.getNotes().size(); i++) { TGNote current = voice.getNote(i); if (current.getString() == string) { return current; } } } previous = getPreviousBeat(measure.getBeats(), previous); } } return null; } /** * Retorna el Componente Anterior */ public TGVoice getPreviousVoice(List<TGBeat> 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; } 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 = new TGDuration(); minDuration.setValue(TGDuration.SIXTY_FOURTH); minDuration.setDivision(TGDivisionType.DEFAULT); for (int i = 0; i < minDuration.getTime(); i++) { start++; startBeat = (start % beatLength == 0); if (startBeat) { break; } } if (!startBeat) { start = currStart; } } return start; } public TGSongManager getSongManager() { return this.songManager; } public List<TGString> getSortedStringsByValue(TGTrack track, final int direction) { List<TGString> strings = new ArrayList<TGString>(); for (int number = 1; number <= track.stringCount(); number++) { strings.add(track.getString(number)); } Collections.sort(strings, new Comparator<TGString>() { public int compare(TGString o1, TGString o2) { if (o1 != null && o2 != null) { int status = o1.getValue() - o2.getValue(); if (status == 0) { return 0; } return ((status * direction) > 0 ? 1 : -1); } return 0; } }); return strings; } /** * 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; } /** * Retorna las Nota en la posicion y cuerda */ public TGVoice getVoiceIn(TGMeasure measure, long start, int voiceIndex) { for (final TGBeat beat : measure.getBeats()) { TGVoice voice = beat.getVoice(voiceIndex); if (!voice.isEmpty() && beat.getStart() <= start && (beat.getStart() + voice.getDuration().getTime() > start)) { return voice; } } return null; } public List<TGVoice> getVoicesBeforeEnd(List<TGBeat> beats, long fromStart, int index) { List<TGVoice> list = new ArrayList<TGVoice>(); for (final TGBeat beat : beats) { if (beat.getStart() >= fromStart) { TGVoice voice = beat.getVoice(index); if (!voice.isEmpty()) { list.add(voice); } } } return list; } 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 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(vDuration); if (duration != null) { voice.setDuration(duration.clone()); } } if (vTiedDuration > 0) { TGDuration newVoiceDuration = TGDuration.fromTime(vTiedDuration); if (newVoiceDuration != null) { long newBeatStart = (bStart + vDuration); TGBeat newBeat = getBeat(track, newBeatStart); if (newBeat == null) { newBeat = new TGBeatImpl(); newBeat.setStart((bStart + vDuration)); } TGVoice newVoice = newBeat.getVoice(v); for (int n = 0; n < voice.getNotes().size(); n++) { TGNote note = voice.getNote(n); TGNote newNote = new TGNoteImpl(); newNote.setTiedNote(true); newNote.setValue(note.getValue()); newNote.setString(note.getString()); newNote.setVelocity(note.getVelocity()); newVoice.addNote(newNote); } newVoice.setEmpty(false); newVoice.setDuration(newVoiceDuration.clone()); locateBeat(newBeat, track, newMeasureAlsoForRestBeats); } } } } newMeasure.addBeat(beat); } } public void moveAllBeats(TGMeasure measure, long theMove) { moveBeats(measure.getBeats(), 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); } /** * Mueve los componentes */ private void moveBeats(List<TGBeat> beats, long theMove) { for (final TGBeat beat : beats) { moveBeat(beat, theMove); } } public void moveBeats(TGMeasure measure, long start, long theMove) { moveBeats(getBeatsBeforeEnd(measure.getBeats(), start), theMove); } 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<TGBeat> beatsToMove = getBeatsBeforeEnd(measure.getBeats(), start); moveBeats(beatsToMove, theMove); if (success) { List<TGBeat> beatsToRemove = new ArrayList<TGBeat>(); List<TGBeat> beats = new ArrayList<TGBeat>(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. for (final TGBeat beat : beatsToRemove) { 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 = new TGBeatImpl(); 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); voice.setDuration(fillDuration.clone()); } addBeat(measure, beat); } } else { first = getFirstBeat(getBeatsBeforeEnd(measure.getBeats(), start)); TGBeat beat = new TGBeatImpl(); 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); voice.setDuration(fillDuration.clone()); } addBeat(measure, beat); } } } } } // Si el movimiento no es satisfactorio, regreso todo como estaba if (!success) { moveBeats(beatsToMove, -theMove); } return success; } public void moveOutOfBoundsBeatsToNewMeasure(TGMeasure measure) { this.moveOutOfBoundsBeatsToNewMeasure(measure, true); } public void moveOutOfBoundsBeatsToNewMeasure(TGMeasure measure, boolean newMeasureAlsoForRestBeats) { List<TGBeat> beats = new ArrayList<TGBeat>(); 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); } } /** * 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; } /** * Mueve la nota 1 semitono abajo */ public boolean moveSemitoneDown(TGMeasure measure, long start, int string) { return moveSemitone(measure, start, string, -1); } /** * Mueve la nota 1 semitono arriba */ public boolean moveSemitoneUp(TGMeasure measure, long start, int string) { return moveSemitone(measure, start, string, 1); } public void moveVoice(TGVoice voice, long theMove) { long newStart = (voice.getBeat().getStart() + theMove); TGBeat newBeat = getBeat(voice.getBeat().getMeasure(), newStart); if (newBeat == null) { newBeat = new TGBeatImpl(); 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() != Direction.NONE) { beat.setStroke(currentBeat.getStroke().clone()); } } // Make sure to remove another voice instance from old beat. TGVoice newVoice = new TGVoiceImpl(voice.getIndex()); currentBeat.setVoice(voice.getIndex(), newVoice); this.removeVoice(newVoice); } beat.setVoice(voice.getIndex(), voice); } } private void moveVoices(List<TGVoice> 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 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<TGVoice> voicesToMove = getVoicesBeforeEnd(measure.getBeats(), start, voiceIndex); List<TGVoice> voicesToRemove = new ArrayList<TGVoice>(); List<TGBeat> 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. for (final TGVoice voice : voicesToRemove) { removeVoice(voice); } // 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 = new TGBeatImpl(); beat.setStart(beatStart); beatNew = true; } TGVoice voice = beat.getVoice(voiceIndex); voice.setEmpty(false); voice.setDuration(fillDuration.clone()); 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 = new TGBeatImpl(); beat.setStart(start); beatNew = true; } TGVoice voice = beat.getVoice(voiceIndex); voice.setEmpty(false); voice.setDuration(fillDuration.clone()); if (beatNew) { addBeat(measure, beat); } } } } // Borro todos los beats que quedaron vacios. this.removeEmptyBeats(measure); } return success; } 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); } } public void removeBeat(TGBeat beat) { beat.getMeasure().removeBeat(beat); } /** * 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 removeBeat(TGMeasure measure, long start, boolean moveNextComponents) { TGBeat beat = getBeat(measure, start); if (beat != null) { removeBeat(beat, moveNextComponents); } } public void removeBeatsBeetween(TGMeasure measure, long p1, long p2) { List<TGBeat> beats = getBeatsBeetween(measure.getBeats(), p1, p2); for (final TGBeat beat : beats) { removeBeat(beat); } } public void removeBeatsBeforeEnd(TGMeasure measure, long fromStart) { List<TGBeat> beats = getBeatsBeforeEnd(measure.getBeats(), fromStart); for (final TGBeat beat : beats) { removeBeat(beat); } } /** * Borra el acorde en la position */ public void removeChord(TGMeasure measure, long start) { TGBeat beat = getBeat(measure, start); if (beat != null) { beat.removeChord(); } } public void removeEmptyBeats(TGMeasure measure) { List<TGBeat> beats = new ArrayList<TGBeat>(); for (final TGBeat beat : measure.getBeats()) { 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); } } for (final TGBeat beat : beats) { this.removeBeat(beat); } } public void removeMeasureVoices(TGMeasure measure, int index) { boolean hasNotes = false; List<TGVoice> voices = new ArrayList<TGVoice>(); for (final TGBeat beat : measure.getBeats()) { TGVoice voice = beat.getVoice(index); if (voice.isRestVoice()) { voices.add(voice); } else if (!voice.isEmpty()) { hasNotes = true; break; } } if (!hasNotes) { for (final TGVoice voice : voices) { this.removeVoice(voice); } } } 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.getNotes().size(); i++) { TGNote note = voice.getNote(i); if (note.getString() == string) { removeNote(note, checkRestBeat); return; } } } } public void removeNote(TGNote note) { this.removeNote(note, true); } 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(Direction.NONE); // Borro un posible acorde if (beat.getMeasure() != null) { removeChord(beat.getMeasure(), beat.getStart()); } } } } public void removeNotesAfterString(TGMeasure measure, int string) { List<TGNote> notesToRemove = new ArrayList<TGNote>(); for (final TGBeat beat : measure.getBeats()) { for (int v = 0; v < beat.countVoices(); v++) { TGVoice voice = beat.getVoice(v); for (final TGNote note : voice.getNotes()) { if (note.getString() > string) { notesToRemove.add(note); } } } } for (final TGNote note : notesToRemove) { removeNote(note); } } /** * 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 removeVoice(TGMeasure measure, long start, int index, boolean moveNextComponents) { TGBeat beat = getBeat(measure, start); if (beat != null) { removeVoice(beat.getVoice(index), moveNextComponents); } } 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 removeVoicesOutOfTime(TGMeasure measure) { List<TGVoice> voicesToRemove = new ArrayList<TGVoice>(); long mStart = measure.getStart(); long mEnd = mStart + measure.getLength(); for (final TGBeat beat : measure.getBeats()) { 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); } } } } for (final TGVoice voice : voicesToRemove) { this.removeVoice(voice); } } /** * Set the beat stroke */ public boolean setStroke(TGMeasure measure, long start, int value, Direction direction) { TGBeat beat = getBeat(measure, start); if (beat != null) { beat.setStroke(new TGStroke(direction, value)); return true; } return false; } /** * 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 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 cuerda de arriba */ public int shiftNoteUp(TGMeasure measure, long start, int string) { return shiftNote(measure, start, string, -1); } private boolean transposeChordNote(TGChord chord, int chordString, List<TGString> 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; } private boolean transposeNote(TGNote note, List<TGNote> notes, List<TGString> 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; } public void transposeNotes(TGBeat beat, List<TGString> strings, int transposition, boolean tryKeepString, boolean applyToChord, int applyToString) { if (transposition != 0) { List<TGNote> 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); } } } } } 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<TGString> 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<TGString> strings = getSortedStringsByValue(track, (transposition > 0 ? 1 : -1)); transposeNotes(beat, strings, transposition, tryKeepString, applyToChords, applyToString); } } } } } } } } 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(), nextVoice.getIndex(), false); } } } 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<TGBeat> 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<TGVoice> nextBeats = new ArrayList<TGVoice>(); 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<TGVoice> 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()) { duration = currentVoice.getDuration().clone(); // 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; } */ }