package org.herac.tuxguitar.player.base; import org.herac.tuxguitar.song.models.TGDuration; import org.herac.tuxguitar.song.models.TGMeasureHeader; import org.herac.tuxguitar.song.models.TGSong; public class MidiRepeatController { private TGSong song; private int count; private int index; private int lastIndex; private boolean shouldPlay; private boolean repeatOpen; private long repeatStart; private long repeatEnd; private long repeatMove; private int repeatStartIndex; private int repeatNumber; private int repeatAlternative; public MidiRepeatController(TGSong song){ this.song = song; this.count = song.countMeasureHeaders(); this.index = 0; this.lastIndex = -1; this.shouldPlay = true; this.repeatOpen = true; this.repeatAlternative = 0; this.repeatStart = TGDuration.QUARTER_TIME; this.repeatEnd = 0; this.repeatMove = 0; this.repeatStartIndex = 0; this.repeatNumber = 0; } public void process(){ TGMeasureHeader header = this.song.getMeasureHeader(this.index); //Por defecto el compas deberia sonar this.shouldPlay = true; //En caso de existir una repeticion nueva, //guardo el indice de el compas donde empieza una repeticion if (header.isRepeatOpen()) { this.repeatStartIndex = this.index; this.repeatStart = header.getStart(); this.repeatOpen = true; //Si es la primer vez que paso por este compas //Pongo numero de repeticion y final alternativo en cero if(this.index > this.lastIndex){ this.repeatNumber = 0; this.repeatAlternative = 0; } } else{ //verifico si hay un final alternativo abierto if(this.repeatAlternative == 0){ this.repeatAlternative = header.getRepeatAlternative(); } //Si estoy en un final alternativo. //el compas solo puede sonar si el numero de repeticion coincide con el numero de final alternativo. if (this.repeatOpen && (this.repeatAlternative > 0) && ((this.repeatAlternative & (1 << (this.repeatNumber))) == 0)){ this.repeatMove -= header.getLength(); if (header.getRepeatClose() >0){ this.repeatAlternative = 0; } this.shouldPlay = false; this.index ++; return; } } //antes de ejecutar una posible repeticion //guardo el indice del ultimo compas tocado this.lastIndex = Math.max(this.lastIndex,this.index); //si hay una repeticion la hago if (this.repeatOpen && header.getRepeatClose() > 0) { if (this.repeatNumber < header.getRepeatClose() || (this.repeatAlternative > 0)) { this.repeatEnd = header.getStart() + header.getLength(); this.repeatMove += this.repeatEnd - this.repeatStart; this.index = this.repeatStartIndex - 1; this.repeatNumber++; } else{ this.repeatStart = 0; this.repeatNumber = 0; this.repeatEnd = 0; this.repeatOpen = false; } this.repeatAlternative = 0; } this.index ++; } public boolean finished(){ return (this.index >= this.count); } public boolean shouldPlay(){ return this.shouldPlay; } public int getIndex(){ return this.index; } public long getRepeatMove(){ return this.repeatMove; } }