1 package org.herac.tuxguitar.io.gtp; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 import java.util.Iterator; 6 import java.util.List; 7 8 import org.herac.tuxguitar.io.base.TGFileFormat; 9 import org.herac.tuxguitar.song.models.TGBeat; 10 import org.herac.tuxguitar.song.models.TGChannel; 11 import org.herac.tuxguitar.song.models.TGChord; 12 import org.herac.tuxguitar.song.models.TGColor; 13 import org.herac.tuxguitar.song.models.TGDuration; 14 import org.herac.tuxguitar.song.models.TGLyric; 15 import org.herac.tuxguitar.song.models.TGMarker; 16 import org.herac.tuxguitar.song.models.TGMeasure; 17 import org.herac.tuxguitar.song.models.TGMeasureHeader; 18 import org.herac.tuxguitar.song.models.TGNote; 19 import org.herac.tuxguitar.song.models.TGNoteEffect; 20 import org.herac.tuxguitar.song.models.TGSong; 21 import org.herac.tuxguitar.song.models.TGString; 22 import org.herac.tuxguitar.song.models.TGStroke; 23 import org.herac.tuxguitar.song.models.TGTempo; 24 import org.herac.tuxguitar.song.models.TGText; 25 import org.herac.tuxguitar.song.models.TGTimeSignature; 26 import org.herac.tuxguitar.song.models.TGTrack; 27 import org.herac.tuxguitar.song.models.TGVelocities; 28 import org.herac.tuxguitar.song.models.TGVoice; 29 import org.herac.tuxguitar.song.models.effects.TGEffectBend; 30 import org.herac.tuxguitar.song.models.effects.TGEffectGrace; 31 import org.herac.tuxguitar.song.models.effects.TGEffectHarmonic; 32 import org.herac.tuxguitar.song.models.effects.TGEffectTremoloBar; 33 import org.herac.tuxguitar.song.models.effects.TGEffectTremoloPicking; 34 import org.herac.tuxguitar.song.models.effects.TGEffectTrill; 35 36 public class GP4InputStream extends GTPInputStream { 37 private static final String SUPPORTED_VERSIONS[] = { "FICHIER GUITAR PRO v4.00", "FICHIER GUITAR PRO v4.06", "FICHIER GUITAR PRO L4.06" }; 38 private static final float GP_BEND_SEMITONE = 25f; 39 private static final float GP_BEND_POSITION = 60f; 40 41 private int tripletFeel; 42 43 public GP4InputStream(GTPSettings settings){ 44 super(settings, SUPPORTED_VERSIONS); GP3InputStream(GTPSettings settings)45 } 46 47 public TGFileFormat getFileFormat(){ 48 return new TGFileFormat("Guitar Pro 4","*.gp4"); 49 } 50 51 public TGSong readSong() throws IOException, GTPFormatException { 52 readVersion(); readSong()53 if (!isSupportedVersion(getVersion())) { 54 this.close(); 55 throw new GTPFormatException("Unsupported Version"); 56 } 57 TGSong song = getFactory().newSong(); 58 59 readInfo(song); 60 61 this.tripletFeel = ((readBoolean())?TGMeasureHeader.TRIPLET_FEEL_EIGHTH:TGMeasureHeader.TRIPLET_FEEL_NONE); 62 63 int lyricTrack = readInt(); 64 TGLyric lyric = readLyrics(); 65 66 int tempoValue = readInt(); 67 68 readInt(); //key 69 70 readByte(); //octave 71 72 List channels = readChannels(); 73 74 int measures = readInt(); 75 int tracks = readInt(); 76 77 readMeasureHeaders(song, measures); 78 readTracks(song, tracks, channels, lyric, lyricTrack); 79 readMeasures(song, measures, tracks, tempoValue); 80 81 this.close(); 82 readChannels()83 return song; 84 } 85 86 private void readInfo(TGSong song) throws IOException{ 87 song.setName(readStringByteSizeOfInteger()); 88 readStringByteSizeOfInteger(); 89 song.setArtist(readStringByteSizeOfInteger()); 90 song.setAlbum(readStringByteSizeOfInteger()); 91 song.setAuthor(readStringByteSizeOfInteger()); 92 song.setCopyright(readStringByteSizeOfInteger()); 93 song.setWriter(readStringByteSizeOfInteger()); 94 readStringByteSizeOfInteger(); 95 int comments = readInt(); 96 for (int i = 0; i < comments; i++) { 97 song.setComments( song.getComments() + readStringByteSizeOfInteger() ); 98 } 99 } 100 101 private void readMeasureHeaders(TGSong song, int count) throws IOException{ readInfo(TGSong song)102 TGTimeSignature timeSignature = getFactory().newTimeSignature(); 103 for (int i = 0; i < count; i++) { 104 song.addMeasureHeader(readMeasureHeader((i + 1),song,timeSignature)); 105 } 106 } 107 108 private void readTracks(TGSong song, int count, List channels,TGLyric lyric, int lyricTrack) throws IOException{ 109 for (int number = 1; number <= count; number++) { 110 song.addTrack(readTrack(number, channels,(number == lyricTrack)?lyric:getFactory().newLyric())); 111 } 112 } 113 114 private void readMeasures(TGSong song, int measures, int tracks, int tempoValue) throws IOException{ 115 TGTempo tempo = getFactory().newTempo(); 116 tempo.setValue(tempoValue); readMeasureHeaders(TGSong song, int count)117 long start = TGDuration.QUARTER_TIME; 118 for (int i = 0; i < measures; i++) { 119 TGMeasureHeader header = song.getMeasureHeader(i); 120 header.setStart(start); 121 for (int j = 0; j < tracks; j++) { 122 TGTrack track = song.getTrack(j); 123 TGMeasure measure = getFactory().newMeasure(header); readTracks(TGSong song, int count, List channels)124 track.addMeasure(measure); 125 readMeasure(measure, track, tempo); 126 } 127 tempo.copy(header.getTempo()); 128 start += header.getLength(); 129 } readMeasures(TGSong song, int measures, int tracks, int tempoValue)130 } 131 132 private TGLyric readLyrics() throws IOException{ 133 TGLyric lyric = getFactory().newLyric(); 134 lyric.setFrom(readInt()); 135 lyric.setLyrics(readStringInteger()); 136 for (int i = 0; i < 4; i++) { 137 readInt(); 138 readStringInteger(); 139 } 140 return lyric; 141 } 142 143 private List readChannels() throws IOException{ 144 List channels = new ArrayList(); 145 for (int i = 0; i < 64; i++) { 146 TGChannel channel = getFactory().newChannel(); 147 channel.setChannel((short)i); readDuration(int flags)148 channel.setEffectChannel((short)i); 149 channel.setInstrument((short)readInt()); 150 channel.setVolume(toChannelShort(readByte())); 151 channel.setBalance(toChannelShort(readByte())); 152 channel.setChorus(toChannelShort(readByte())); 153 channel.setReverb(toChannelShort(readByte())); 154 channel.setPhaser(toChannelShort(readByte())); 155 channel.setTremolo(toChannelShort(readByte())); 156 channels.add(channel); 157 skip(2); 158 } 159 return channels; 160 } 161 162 private long readBeat(long start, TGMeasure measure,TGTrack track, TGTempo tempo) throws IOException { 163 int flags = readUnsignedByte(); 164 if((flags & 0x40) != 0){ 165 readUnsignedByte(); 166 } 167 168 TGBeat beat = getFactory().newBeat(); 169 TGVoice voice = beat.getVoice(0); 170 TGDuration duration = readDuration(flags); 171 TGNoteEffect effect = getFactory().newEffect(); 172 if ((flags & 0x02) != 0) { 173 readChord(track.stringCount(), beat); 174 } 175 if ((flags & 0x04) != 0) { 176 readText(beat); 177 } 178 if ((flags & 0x08) != 0) { 179 readBeatEffects(beat,effect); 180 } 181 if ((flags & 0x10) != 0) { 182 readMixChange(tempo); 183 } 184 int stringFlags = readUnsignedByte(); 185 for (int i = 6; i >= 0; i--) { 186 if ((stringFlags & (1 << i)) != 0 && (6 - i) < track.stringCount()) { 187 TGString string = track.getString( (6 - i) + 1 ).clone(getFactory()); 188 TGNote note = readNote(string, track,effect.clone(getFactory())); 189 voice.addNote(note); 190 } 191 } getTiedNoteValue(int string, TGTrack track)192 beat.setStart(start); 193 voice.setEmpty(false); 194 duration.copy(voice.getDuration()); 195 measure.addBeat(beat); 196 197 return duration.getTime(); 198 } 199 200 private void readText(TGBeat beat) throws IOException{ 201 TGText text = getFactory().newText(); 202 text.setValue(readStringByteSizeOfInteger()); 203 beat.setText(text); 204 } 205 206 private TGDuration readDuration(int flags) throws IOException { 207 TGDuration duration = getFactory().newDuration(); 208 duration.setValue( (int) (Math.pow( 2 , (readByte() + 4) ) / 4 ) ); 209 duration.setDotted(((flags & 0x01) != 0)); 210 if ((flags & 0x20) != 0) { 211 int divisionType = readInt(); readColor(TGColor color)212 switch (divisionType) { 213 case 3: 214 duration.getDivision().setEnters(3); 215 duration.getDivision().setTimes(2); 216 break; 217 case 5: 218 duration.getDivision().setEnters(5); 219 duration.getDivision().setTimes(4); 220 break; 221 case 6: 222 duration.getDivision().setEnters(6); 223 duration.getDivision().setTimes(4); 224 break; 225 case 7: 226 duration.getDivision().setEnters(7); 227 duration.getDivision().setTimes(4); 228 break; 229 case 9: 230 duration.getDivision().setEnters(9); 231 duration.getDivision().setTimes(8); 232 break; 233 case 10: 234 duration.getDivision().setEnters(10); 235 duration.getDivision().setTimes(8); 236 break; 237 case 11: 238 duration.getDivision().setEnters(11); 239 duration.getDivision().setTimes(8); 240 break; 241 case 12: 242 duration.getDivision().setEnters(12); 243 duration.getDivision().setTimes(8); 244 break; 245 } 246 } 247 return duration; 248 } 249 250 private int getTiedNoteValue(int string, TGTrack track) { 251 int measureCount = track.countMeasures(); 252 if (measureCount > 0) { 253 for (int m = measureCount - 1; m >= 0; m--) { 254 TGMeasure measure = track.getMeasure( m ); 255 for (int b = measure.countBeats() - 1; b >= 0; b--) { 256 TGBeat beat = measure.getBeat( b ); 257 TGVoice voice = beat.getVoice(0); 258 for (int n = 0; n < voice.countNotes(); n ++) { readMeasure(TGMeasure measure, TGTrack track, TGTempo tempo)259 TGNote note = voice.getNote( n ); 260 if (note.getString() == string) { 261 return note.getValue(); 262 } 263 } 264 } 265 } 266 } 267 return -1; readBeat(long start, TGMeasure measure,TGTrack track, TGTempo tempo)268 } 269 270 private void readColor(TGColor color) throws IOException { 271 color.setR(readUnsignedByte()); 272 color.setG(readUnsignedByte()); 273 color.setB(readUnsignedByte()); 274 read(); 275 } 276 277 private TGMarker readMarker(int measure) throws IOException { 278 TGMarker marker = getFactory().newMarker(); 279 marker.setMeasure(measure); 280 marker.setTitle(readStringByteSizeOfInteger()); 281 readColor(marker.getColor()); 282 return marker; 283 } 284 285 private TGMeasureHeader readMeasureHeader(int number,TGSong song,TGTimeSignature timeSignature) throws IOException { 286 int flags = readUnsignedByte(); 287 TGMeasureHeader header = getFactory().newHeader(); 288 header.setNumber(number); 289 header.setStart(0); 290 header.getTempo().setValue(120); 291 header.setTripletFeel(this.tripletFeel); 292 header.setRepeatOpen( ((flags & 0x04) != 0) ); 293 if ((flags & 0x01) != 0) { 294 timeSignature.setNumerator(readByte()); 295 } 296 if ((flags & 0x02) != 0) { 297 timeSignature.getDenominator().setValue(readByte()); 298 } 299 timeSignature.copy(header.getTimeSignature()); 300 if ((flags & 0x08) != 0) { 301 header.setRepeatClose(readByte()); 302 } 303 if ((flags & 0x10) != 0) { 304 header.setRepeatAlternative(parseRepeatAlternative(song, number, readUnsignedByte())); 305 } readText(TGBeat beat)306 if ((flags & 0x20) != 0) { 307 header.setMarker(readMarker(number)); 308 } 309 if ((flags & 0x40) != 0) { 310 readByte(); 311 readByte(); readNote(TGString string,TGTrack track,TGNoteEffect effect)312 } 313 return header; 314 } 315 316 private void readMeasure(TGMeasure measure,TGTrack track, TGTempo tempo) throws IOException{ 317 long nextNoteStart = measure.getStart(); 318 int numberOfBeats = readInt(); 319 for (int i = 0; i < numberOfBeats; i++) { 320 nextNoteStart += readBeat(nextNoteStart, measure, track, tempo); 321 } 322 measure.setClef( getClef(track) ); 323 } 324 325 private TGNote readNote(TGString string, TGTrack track,TGNoteEffect effect)throws IOException { 326 int flags = readUnsignedByte(); 327 TGNote note = getFactory().newNote(); 328 note.setString(string.getNumber()); 329 note.setEffect(effect); 330 note.getEffect().setAccentuatedNote(((flags & 0x40) != 0)); 331 note.getEffect().setGhostNote(((flags & 0x04) != 0)); 332 if ((flags & 0x20) != 0) { 333 int noteType = readUnsignedByte(); 334 note.setTiedNote( (noteType == 0x02) ); 335 note.getEffect().setDeadNote((noteType == 0x03)); 336 } 337 if ((flags & 0x01) != 0) { 338 skip(2); 339 } 340 if ((flags & 0x10) != 0) { 341 note.setVelocity((TGVelocities.MIN_VELOCITY + (TGVelocities.VELOCITY_INCREMENT * readByte())) - TGVelocities.VELOCITY_INCREMENT); 342 } readTrack(int number, List channels)343 if ((flags & 0x20) != 0) { 344 int fret = readByte(); 345 int value = ( note.isTiedNote() ? getTiedNoteValue(string.getNumber(), track) : fret ); 346 note.setValue( value >= 0 && value < 100 ? value : 0 ); 347 } 348 if ((flags & 0x80) != 0) { 349 skip(2); 350 } 351 if ((flags & 0x08) != 0) { 352 readNoteEffects(note.getEffect()); 353 } 354 return note; 355 } 356 357 private TGTrack readTrack(int number, List channels,TGLyric lyrics) throws IOException { 358 TGTrack track = getFactory().newTrack(); 359 track.setNumber(number); 360 track.setLyrics(lyrics); 361 readUnsignedByte(); 362 track.setName(readStringByte(40)); 363 int stringCount = readInt(); 364 for (int i = 0; i < 7; i++) { 365 int tuning = readInt(); readChannel(TGChannel channel,List channels)366 if (stringCount > i) { 367 TGString string = getFactory().newString(); 368 string.setNumber(i + 1); 369 string.setValue(tuning); 370 track.getStrings().add(string); 371 } 372 } 373 readInt(); 374 readChannel(track.getChannel(), channels); 375 readInt(); 376 track.setOffset(readInt()); 377 readColor(track.getColor()); 378 return track; 379 } parseRepeatAlternative(TGSong song,int measure,int value)380 381 private void readChannel(TGChannel channel,List channels) throws IOException { 382 int index = (readInt() - 1); 383 int effectChannel = (readInt() - 1); 384 if(index >= 0 && index < channels.size()){ 385 ((TGChannel) channels.get(index)).copy(channel); 386 if (channel.getInstrument() < 0) { 387 channel.setInstrument((short)0); 388 } 389 if(!channel.isPercussionChannel()){ 390 channel.setEffectChannel((short)effectChannel); 391 } 392 } 393 } 394 395 private int parseRepeatAlternative(TGSong song,int measure,int value){ 396 int repeatAlternative = 0; 397 int existentAlternatives = 0; 398 Iterator it = song.getMeasureHeaders(); 399 while(it.hasNext()){ 400 TGMeasureHeader header = (TGMeasureHeader)it.next(); 401 if(header.getNumber() == measure){ 402 break; readChord(int strings, TGBeat beat)403 } 404 if(header.isRepeatOpen()){ 405 existentAlternatives = 0; 406 } 407 existentAlternatives |= header.getRepeatAlternative(); 408 } 409 410 for(int i = 0; i < 8; i ++){ 411 if(value > i && (existentAlternatives & (1 << i)) == 0){ 412 repeatAlternative |= (1 << i); 413 } 414 } 415 return repeatAlternative; 416 } 417 418 private void readChord(int strings,TGBeat beat) throws IOException { 419 TGChord chord = getFactory().newChord(strings); 420 if ((readUnsignedByte() & 0x01) == 0) { 421 chord.setName( readStringByteSizeOfInteger() ); 422 chord.setFirstFret(readInt()); 423 if(chord.getFirstFret() != 0){ 424 for (int i = 0; i < 6; i++) { 425 int fret = readInt(); 426 if(i < chord.countStrings()){ 427 chord.addFretValue(i,fret); 428 } 429 } 430 } 431 } 432 else{ 433 skip(16); 434 chord.setName(readStringByte(21)); readGrace(TGNoteEffect effect)435 skip(4); 436 chord.setFirstFret(readInt()); 437 for (int i = 0; i < 7; i++) { 438 int fret = readInt(); 439 if(i < chord.countStrings()){ 440 chord.addFretValue(i,fret); 441 } 442 } 443 skip(32); 444 } 445 if(chord.countNotes() > 0){ 446 beat.setChord(chord); 447 } 448 } 449 450 private void readGrace(TGNoteEffect effect) throws IOException { 451 int fret = readUnsignedByte(); 452 TGEffectGrace grace = getFactory().newEffectGrace(); 453 grace.setOnBeat(false); 454 grace.setDead( (fret == 255) ); 455 grace.setFret( ((!grace.isDead())?fret:0) ); 456 grace.setDynamic( (TGVelocities.MIN_VELOCITY + (TGVelocities.VELOCITY_INCREMENT * readUnsignedByte())) - TGVelocities.VELOCITY_INCREMENT ); 457 int transition = readUnsignedByte(); 458 if(transition == 0){ readBend(TGNoteEffect effect)459 grace.setTransition( TGEffectGrace.TRANSITION_NONE ); 460 } 461 else if(transition == 1){ 462 grace.setTransition( TGEffectGrace.TRANSITION_SLIDE ); 463 } 464 else if(transition == 2){ 465 grace.setTransition( TGEffectGrace.TRANSITION_BEND ); 466 } 467 else if(transition == 3){ 468 grace.setTransition( TGEffectGrace.TRANSITION_HAMMER ); 469 } 470 grace.setDuration(readUnsignedByte()); 471 effect.setGrace(grace); 472 } 473 474 private void readBend(TGNoteEffect effect) throws IOException { 475 TGEffectBend bend = getFactory().newEffectBend(); 476 skip(5); readTremoloBar(TGNoteEffect noteEffect)477 int points = readInt(); 478 for (int i = 0; i < points; i++) { 479 int position = readInt(); 480 int value = readInt(); 481 readByte(); 482 483 int pointPosition = Math.round(position * TGEffectBend.MAX_POSITION_LENGTH / GP_BEND_POSITION); 484 int pointValue = Math.round(value * TGEffectBend.SEMITONE_LENGTH / GP_BEND_SEMITONE); 485 bend.addPoint(pointPosition,pointValue); readNoteEffects(TGNoteEffect effect)486 } 487 if(!bend.getPoints().isEmpty()){ 488 effect.setBend(bend); 489 } 490 } 491 492 private void readTremoloBar(TGNoteEffect effect) throws IOException { 493 TGEffectTremoloBar tremoloBar = getFactory().newEffectTremoloBar(); 494 skip(5); 495 int points = readInt(); 496 for (int i = 0; i < points; i++) { 497 int position = readInt(); readBeatEffects(TGBeat beat,TGNoteEffect effect)498 int value = readInt(); 499 readByte(); 500 501 int pointPosition = Math.round(position * TGEffectTremoloBar.MAX_POSITION_LENGTH / GP_BEND_POSITION); 502 int pointValue = Math.round(value / (GP_BEND_SEMITONE * 2f)); 503 tremoloBar.addPoint(pointPosition,pointValue); 504 } 505 if(!tremoloBar.getPoints().isEmpty()){ 506 effect.setTremoloBar(tremoloBar); 507 } 508 } 509 510 public void readTremoloPicking(TGNoteEffect effect) throws IOException{ 511 int value = readUnsignedByte(); 512 TGEffectTremoloPicking tp = getFactory().newEffectTremoloPicking(); 513 if(value == 1){ 514 tp.getDuration().setValue(TGDuration.EIGHTH); 515 effect.setTremoloPicking(tp); 516 }else if(value == 2){ 517 tp.getDuration().setValue(TGDuration.SIXTEENTH); 518 effect.setTremoloPicking(tp); 519 }else if(value == 3){ 520 tp.getDuration().setValue(TGDuration.THIRTY_SECOND); 521 effect.setTremoloPicking(tp); 522 } 523 } 524 525 private void readNoteEffects(TGNoteEffect noteEffect) throws IOException { 526 int flags1 = readUnsignedByte(); 527 int flags2 = readUnsignedByte(); 528 noteEffect.setHammer(((flags1 & 0x02) != 0)); 529 noteEffect.setVibrato(((flags2 & 0x40) != 0) || noteEffect.isVibrato()); 530 noteEffect.setPalmMute(((flags2 & 0x02) != 0)); 531 noteEffect.setStaccato(((flags2 & 0x01) != 0)); 532 if ((flags1 & 0x01) != 0) { 533 readBend(noteEffect); 534 } 535 if ((flags1 & 0x10) != 0) { 536 readGrace(noteEffect); readMixChange(TGTempo tempo)537 } 538 if ((flags2 & 0x04) != 0) { 539 readTremoloPicking(noteEffect); 540 } 541 if ((flags2 & 0x08) != 0) { 542 noteEffect.setSlide(true); 543 readByte(); 544 } 545 if ((flags2 & 0x10) != 0) { 546 TGEffectHarmonic harmonic = getFactory().newEffectHarmonic(); 547 int type = readByte(); 548 if(type == 1){ 549 harmonic.setType(TGEffectHarmonic.TYPE_NATURAL); 550 }else if(type == 3){ 551 harmonic.setType(TGEffectHarmonic.TYPE_TAPPED); 552 }else if(type == 4){ 553 harmonic.setType(TGEffectHarmonic.TYPE_PINCH); 554 }else if(type == 5){ 555 harmonic.setType(TGEffectHarmonic.TYPE_SEMI); 556 }else if(type == 15){ 557 harmonic.setType(TGEffectHarmonic.TYPE_ARTIFICIAL); 558 harmonic.setData(2); 559 }else if(type == 17){ 560 harmonic.setType(TGEffectHarmonic.TYPE_ARTIFICIAL); 561 harmonic.setData(3); 562 }else if(type == 22){ 563 harmonic.setType(TGEffectHarmonic.TYPE_ARTIFICIAL); 564 harmonic.setData(0); 565 } 566 noteEffect.setHarmonic(harmonic); 567 } 568 if ((flags2 & 0x20) != 0) { 569 byte fret = readByte(); toStrokeValue( int value )570 byte period = readByte(); 571 TGEffectTrill trill = getFactory().newEffectTrill(); 572 trill.setFret(fret); 573 if(period == 1){ 574 trill.getDuration().setValue(TGDuration.SIXTEENTH); 575 noteEffect.setTrill(trill); 576 }else if(period == 2){ 577 trill.getDuration().setValue(TGDuration.THIRTY_SECOND); 578 noteEffect.setTrill(trill); 579 }else if(period == 3){ 580 trill.getDuration().setValue(TGDuration.SIXTY_FOURTH); 581 noteEffect.setTrill(trill); 582 } 583 } 584 } 585 586 private void readBeatEffects(TGBeat beat,TGNoteEffect noteEffect) throws IOException { 587 int flags1 = readUnsignedByte(); 588 int flags2 = readUnsignedByte(); toChannelShort(byte b)589 noteEffect.setFadeIn(((flags1 & 0x10) != 0)); 590 noteEffect.setVibrato(((flags1 & 0x02) != 0)); 591 if ((flags1 & 0x20) != 0) { 592 int effect = readUnsignedByte(); 593 noteEffect.setTapping(effect == 1); getClef( TGTrack track )594 noteEffect.setSlapping(effect == 2); 595 noteEffect.setPopping(effect == 3); 596 } 597 if ((flags2 & 0x04) != 0) { 598 readTremoloBar(noteEffect); 599 } 600 if ((flags1 & 0x40) != 0) { 601 int strokeDown = readByte(); 602 int strokeUp = readByte(); 603 if( strokeDown > 0 ){ 604 beat.getStroke().setDirection( TGStroke.STROKE_DOWN ); 605 beat.getStroke().setValue( toStrokeValue(strokeDown) ); 606 }else if( strokeUp > 0 ){ 607 beat.getStroke().setDirection( TGStroke.STROKE_UP ); 608 beat.getStroke().setValue( toStrokeValue(strokeUp) ); 609 } 610 } 611 if ((flags2 & 0x02) != 0) { 612 readByte(); 613 } 614 } 615 616 private void readMixChange(TGTempo tempo) throws IOException { 617 readByte(); 618 int volume = readByte(); 619 int pan = readByte(); 620 int chorus = readByte(); 621 int reverb = readByte(); 622 int phaser = readByte(); 623 int tremolo = readByte(); 624 int tempoValue = readInt(); 625 if(volume >= 0){ 626 readByte(); 627 } 628 if(pan >= 0){ 629 readByte(); 630 } 631 if(chorus >= 0){ 632 readByte(); 633 } 634 if(reverb >= 0){ 635 readByte(); 636 } 637 if(phaser >= 0){ 638 readByte(); 639 } 640 if(tremolo >= 0){ 641 readByte(); 642 } 643 if(tempoValue >= 0){ 644 tempo.setValue(tempoValue); 645 readByte(); 646 } 647 readByte(); 648 } 649 650 private int toStrokeValue( int value ){ 651 if( value == 1 || value == 2){ 652 return TGDuration.SIXTY_FOURTH; 653 } 654 if( value == 3){ 655 return TGDuration.THIRTY_SECOND; 656 } 657 if( value == 4){ 658 return TGDuration.SIXTEENTH; 659 } 660 if( value == 5){ 661 return TGDuration.EIGHTH; 662 } 663 if( value == 6){ 664 return TGDuration.QUARTER; 665 } 666 return TGDuration.SIXTY_FOURTH; 667 } 668 669 private short toChannelShort(byte b){ 670 short value = (short)(( b * 8 ) - 1); 671 return (short)Math.max(value,0); 672 } 673 674 private int getClef( TGTrack track ){ 675 if( !track.isPercussionTrack() ){ 676 Iterator it = track.getStrings().iterator(); 677 while( it.hasNext() ){ 678 TGString string = (TGString) it.next(); 679 if( string.getValue() <= 34 ){ 680 return TGMeasure.CLEF_BASS; 681 } 682 } 683 } 684 return TGMeasure.CLEF_TREBLE; 685 } 686 } 687