1 package org.herac.tuxguitar.jack.sequencer; 2 3 import java.util.List; 4 5 import org.herac.tuxguitar.song.models.TGDuration; 6 7 public class JackTickController { 8 9 private int tempo; 10 private long frame; 11 private long lastFrame; 12 private long tickLength; 13 private double tick; 14 15 private Object lock; 16 private JackSequencer sequencer; 17 JackTickController(JackSequencer sequencer)18 public JackTickController(JackSequencer sequencer){ 19 this.lock = new Object(); 20 this.sequencer = sequencer; 21 } 22 process()23 public void process() { 24 synchronized (this.lock) { 25 long frameRate = this.sequencer.getJackClient().getTransportFrameRate(); 26 this.lastFrame = this.frame; 27 this.frame = this.sequencer.getJackClient().getTransportFrame(); 28 this.tick += ((double)TGDuration.QUARTER_TIME * ((double)getTempo() * (double)(this.frame - this.lastFrame) / 60.00) / (double)frameRate); 29 } 30 } 31 setTick(long tick , boolean updateTransport )32 public void setTick(long tick , boolean updateTransport ) { 33 synchronized (this.lock) { 34 long frameRate = this.sequencer.getJackClient().getTransportFrameRate(); 35 if( updateTransport ){ 36 this.sequencer.getJackClient().setTransportFrame( Math.round( tickToFrame(tick, frameRate )) ); 37 } 38 this.frame = this.sequencer.getJackClient().getTransportFrame(); 39 this.tick = this.frameToTick( this.frame , frameRate ); 40 } 41 } 42 getTick()43 public double getTick() { 44 return this.tick; 45 } 46 getTickLength()47 public long getTickLength() { 48 return this.tickLength; 49 } 50 clearTick()51 public void clearTick(){ 52 this.tickLength = 0; 53 } 54 notifyTick(long tick)55 public void notifyTick(long tick){ 56 this.tickLength = Math.max(this.tickLength,tick); 57 } 58 setTempo(int tempo)59 public void setTempo(int tempo) { 60 this.tempo = tempo; 61 } 62 getTempo()63 public int getTempo() { 64 return this.tempo; 65 } 66 frameToTick( long frame , long frameRate )67 public double frameToTick( long frame , long frameRate ){ 68 double framePos = 0; 69 double tempo = 120; 70 double tick = TGDuration.QUARTER_TIME; 71 72 List tempoChanges = this.sequencer.getJackEventController().getTempoChanges(); 73 for(int i = 0; i < tempoChanges.size(); i ++){ 74 long[] tc = (long[])tempoChanges.get(i); 75 double tcTick = tc[0]; 76 double tcValue = tc[1]; 77 78 double tickFrames = ( (((double)frameRate * (tcTick - tick)) / (double)TGDuration.QUARTER_TIME ) * (60.00 / tempo) ); 79 if( framePos + tickFrames <= frame ){ 80 framePos += tickFrames; 81 tempo = tcValue; 82 tick = tcTick; 83 }else{ 84 break; 85 } 86 } 87 if( frame > framePos ){ 88 double timeFrame = ( ( (double)(frame - framePos) / (double)frameRate ) * 1000.00 ); 89 double timeTick = ( ( timeFrame * (double)TGDuration.QUARTER_TIME ) / 1000.00 ); 90 91 tick += ( timeTick * ( tempo / 60.00 ) ); 92 } 93 94 return tick; 95 } 96 tickToFrame( long tick , long frameRate )97 public double tickToFrame( long tick , long frameRate ){ 98 double tickPos = TGDuration.QUARTER_TIME; 99 double tempo = 120; 100 double frame = 0; 101 102 List tempoChanges = this.sequencer.getJackEventController().getTempoChanges(); 103 for(int i = 0; i < tempoChanges.size(); i ++){ 104 long[] tc = (long[])tempoChanges.get(i); 105 double tcTick = tc[0]; 106 double tcValue = tc[1]; 107 108 double tickFrames = ((((double) frameRate * (tcTick - tickPos)) / (double)TGDuration.QUARTER_TIME ) * (60.00 / tempo)); 109 if( tcTick <= tick ){ 110 frame += tickFrames; 111 tempo = tcValue; 112 tickPos = tcTick; 113 }else{ 114 break; 115 } 116 } 117 if( tick > tickPos ){ 118 double timeTick = ( ( (double)( tick - tickPos ) / (double)TGDuration.QUARTER_TIME ) * 1000.00 ); 119 double timeFrame = ( ( timeTick * (double)frameRate ) / 1000.00 ); 120 121 frame += (timeFrame * ( 60.00 / tempo)); 122 } 123 124 return frame; 125 } 126 } 127