package org.herac.tuxguitar.jack.sequencer;
import java.util.List;
import org.herac.tuxguitar.song.models.TGDuration;
public class JackTickController {
private long frame;
private long lastFrame;
private Object lock;
private JackSequencer sequencer;
private int tempo;
private double tick;
private long tickLength;
public JackTickController(JackSequencer sequencer) {
this.lock = new Object();
this.sequencer = sequencer;
}
public void clearTick() {
this.tickLength = 0;
}
public double frameToTick(long frame, long frameRate) {
double framePos = 0;
double tempo = 120;
double tick = TGDuration.QUARTER_TIME;
List<long[]> tempoChanges = this.sequencer.getJackEventController()
.getTempoChanges();
for (int i = 0; i < tempoChanges.size(); i++) {
long[] tc = (long[]) tempoChanges.get(i);
double tcTick = tc[0];
double tcValue = tc[1];
double tickFrames = ((((double) frameRate * (tcTick - tick)) / (double) TGDuration.QUARTER_TIME) * (60.00 / tempo));
if (framePos + tickFrames <= frame) {
framePos += tickFrames;
tempo = tcValue;
tick = tcTick;
} else {
break;
}
}
if (frame > framePos) {
double timeFrame = (((double) (frame - framePos) / (double) frameRate) * 1000.00);
double timeTick = ((timeFrame * (double) TGDuration.QUARTER_TIME) / 1000.00);
tick += (timeTick * (tempo / 60.00));
}
return tick;
}
public int getTempo() {
return this.tempo;
}
public double getTick() {
return this.tick;
}
public long getTickLength() {
return this.tickLength;
}
public void notifyTick(long tick) {
this.tickLength = Math.max(this.tickLength, tick);
}
public void process() {
synchronized (this.lock) {
long frameRate = this.sequencer.getJackClient().getTransportFrameRate();
this.lastFrame = this.frame;
this.frame = this.sequencer.getJackClient().getTransportFrame();
this.tick += ((double) TGDuration.QUARTER_TIME
* ((double) getTempo() * (double) (this.frame - this.lastFrame) / 60.00) / (double) frameRate);
}
}
public void setTempo(int tempo) {
this.tempo = tempo;
}
public void setTick(long tick, boolean updateTransport) {
synchronized (this.lock) {
long frameRate = this.sequencer.getJackClient().getTransportFrameRate();
if (updateTransport) {
this.sequencer.getJackClient().setTransportFrame(
Math.round(tickToFrame(tick, frameRate)));
}
this.frame = this.sequencer.getJackClient().getTransportFrame();
this.tick = this.frameToTick(this.frame, frameRate);
}
}
public double tickToFrame(long tick, long frameRate) {
double tickPos = TGDuration.QUARTER_TIME;
double tempo = 120;
double frame = 0;
List<long[]> tempoChanges = this.sequencer.getJackEventController()
.getTempoChanges();
for (int i = 0; i < tempoChanges.size(); i++) {
long[] tc = (long[]) tempoChanges.get(i);
double tcTick = tc[0];
double tcValue = tc[1];
double tickFrames = ((((double) frameRate * (tcTick - tickPos)) / (double) TGDuration.QUARTER_TIME) * (60.00 / tempo));
if (tcTick <= tick) {
frame += tickFrames;
tempo = tcValue;
tickPos = tcTick;
} else {
break;
}
}
if (tick > tickPos) {
double timeTick = (((double) (tick - tickPos) / (double) TGDuration.QUARTER_TIME) * 1000.00);
double timeFrame = ((timeTick * (double) frameRate) / 1000.00);
frame += (timeFrame * (60.00 / tempo));
}
return frame;
}
}