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; }
*/
}