1
package org.herac.tuxguitar.io.gp;
4
import java.io.FileInputStream;
5
import java.io.FileNotFoundException;
6
import java.io.IOException;
7
import java.io.InputStream;
8
import java.util.ArrayList;
9
import java.util.Iterator;
10
import java.util.List;
12
import org.herac.tuxguitar.io.gp.GPFormatException;
13
import org.herac.tuxguitar.song.models.Duration;
14
import org.herac.tuxguitar.song.models.InstrumentString;
15
import org.herac.tuxguitar.song.models.Lyric;
16
import org.herac.tuxguitar.song.models.Marker;
17
import org.herac.tuxguitar.song.models.Measure;
18
import org.herac.tuxguitar.song.models.MeasureHeader;
19
import org.herac.tuxguitar.song.models.Note;
20
import org.herac.tuxguitar.song.models.NoteEffect;
21
import org.herac.tuxguitar.song.models.Song;
22
import org.herac.tuxguitar.song.models.SongChannel;
23
import org.herac.tuxguitar.song.models.SongTrack;
24
import org.herac.tuxguitar.song.models.Tempo;
25
import org.herac.tuxguitar.song.models.TimeSignature;
26
import org.herac.tuxguitar.song.models.RGBColor;
27
import org.herac.tuxguitar.song.models.VelocityValues;
28
import org.herac.tuxguitar.song.models.effects.BendEffect;
29
import org.herac.tuxguitar.song.models.effects.GraceEffect;
30
import org.herac.tuxguitar.song.models.effects.HarmonicEffect;
31
import org.herac.tuxguitar.song.models.effects.TremoloBarEffect;
32
import org.herac.tuxguitar.song.models.effects.TremoloPickingEffect;
33
import org.herac.tuxguitar.song.models.effects.TrillEffect;
35
public class GP5InputStream extends InputStream {
36
private static final String supportedVersions[] = { "FICHIER GUITAR PRO v5.00"/*,"FICHIER GUITAR PRO v5.10" */};
37
private static final int GP_BEND_SEMITONE = 50;
38
private static final int GP_BEND_POSITION = 60;
40
private String version;
41
private InputStream inputStream;
44
public GP5InputStream(InputStream inputStream) {
46
this.inputStream = inputStream;
50
public GP5InputStream(String fileName) throws FileNotFoundException {
51
this(new FileInputStream(new File(fileName)));
54
public void close() throws IOException {
55
this.inputStream.close();
58
public int read() throws IOException {
60
return this.inputStream.read();
64
private void readVersion(){
66
if(this.version == null){
67
this.version = readStringByte(30);
69
} catch (IOException e) {
70
this.version = "NOT_SUPPORTED";
74
public static boolean isSupportedVersion(String version) {
75
for (int i = 0; i < supportedVersions.length; i++) {
76
if (version.equals(supportedVersions[i])) {
83
public boolean isSupportedVersion(){
86
return isSupportedVersion(version);
94
public Song readSong() throws IOException, GPFormatException {
96
if (!isSupportedVersion(version)) {
97
throw new GPFormatException("Unsuported Version");
100
String title = readStringIntegerPlusOne();
102
String subtitle = readStringIntegerPlusOne();
104
String interpret = readStringIntegerPlusOne();
106
String album = readStringIntegerPlusOne();
108
String songAuthor = readStringIntegerPlusOne();
110
String music = readStringIntegerPlusOne();
112
String copyright = readStringIntegerPlusOne();
114
String tab = readStringIntegerPlusOne();
116
String instructions = readStringIntegerPlusOne();
118
int nbNotes = readInt();
120
for (int i = 0; i < nbNotes; i++) {
121
note += readStringIntegerPlusOne();
126
int lyricTrack = readInt();
127
Lyric lyric = new Lyric(readInt(),readStringInteger());
128
for (int i = 0; i < 4; i++) {
129
int measureNumber = readInt();
130
String lines = readStringInteger();
135
for (int i = 0; i < 11; i++) {
141
int tempoValue = readInt();
142
int key = readByte();
143
int octave = readInt();
146
List channels = new ArrayList();
147
int[] instruments = new int[64];
148
for (int i = 0; i < 64; i++) {
149
channels.add(new SongChannel((short)i,
152
toChannelShort(readByte()),
153
toChannelShort(readByte()),
154
toChannelShort(readByte()),
155
toChannelShort(readByte()),
156
toChannelShort(readByte()),
157
toChannelShort(readByte()),
164
TimeSignature timeSignature = new TimeSignature(4, new Duration(4));
168
int numberOfMeasures = readInt();
169
int numberOfTracks = readInt();
171
List headers = new ArrayList();
172
if (numberOfMeasures > 0) {
173
for (int i = 0; i < numberOfMeasures; i++) {
177
MeasureHeader header = createMeasureHeader((i + 1),timeSignature);
182
List tracks = new ArrayList();
183
for (int number = 1; number <= numberOfTracks; number++) {
184
tracks.add(createTrack(number, channels,(number == lyricTrack)?lyric:new Lyric()));
189
long nextMeasureStart = 1000;
190
for (int i = 0; i < numberOfMeasures; i++) {
191
MeasureHeader currHeader = (MeasureHeader) headers.get(i);
192
Tempo tempo = new Tempo(tempoValue);
193
currHeader.setStart(nextMeasureStart);
194
for (int j = 0; j < numberOfTracks; j++) {
195
SongTrack track = (SongTrack) tracks.get(j);
196
Measure measure = new Measure(currHeader,new ArrayList(),new ArrayList(),1,0);
197
addMeasureComponents(track.getStrings(), measure, track.getMeasures(), tempo);
198
currHeader.setTempo(tempo);
199
track.getMeasures().add(measure);
202
tempoValue = tempo.getValue();
203
nextMeasureStart += currHeader.getLength();
206
return new Song(title,interpret,album,songAuthor,tracks,headers,Song.MAX_VOLUME);
209
private long addNotes(long start, List notes, List trackStrings, List currTrackMeasures, Tempo tempo) throws IOException,
211
NoteEffect effect = new NoteEffect();
213
int header = readUnsignedByte();
215
if ((header & 0x40) != 0) {
216
int beatStatus = readUnsignedByte();
217
boolean emptyBeat = (beatStatus == 0x00);
218
boolean restBeat = (beatStatus == 0x02);
221
boolean dottedNotes = ((header & 0x01) != 0);
223
Duration duration = parseDuration(readByte());
224
duration.setDotted(dottedNotes);
226
if ((header & 0x20) != 0) {
227
int tuplet = readInt();
228
//-------Verifico el tupleto--------------------
231
duration.getTupleto().setEnters(3);
232
duration.getTupleto().setTimes(2);
235
duration.getTupleto().setEnters(5);
236
duration.getTupleto().setTimes(4);
239
duration.getTupleto().setEnters(6);
240
duration.getTupleto().setTimes(4);
243
duration.getTupleto().setEnters(7);
244
duration.getTupleto().setTimes(4);
247
duration.getTupleto().setEnters(9);
248
duration.getTupleto().setTimes(8);
251
duration.getTupleto().setEnters(10);
252
duration.getTupleto().setTimes(8);
255
duration.getTupleto().setEnters(11);
256
duration.getTupleto().setTimes(8);
259
duration.getTupleto().setEnters(12);
260
duration.getTupleto().setTimes(8);
265
if ((header & 0x02) != 0) {
269
if ((header & 0x04) != 0) {
270
String text = readStringIntegerPlusOne();
273
if ((header & 0x08) != 0) {
274
readBeatEffects(effect,duration);
277
if ((header & 0x10) != 0) {
278
readMixChange(tempo);
281
int stringsPlayed = readUnsignedByte();
282
List strings = getPlayedStrings(stringsPlayed, trackStrings);
284
for (int i = strings.size() - 1; i >= 0; i--) {
285
InstrumentString string = (InstrumentString) strings.get(i);
286
Note note = parseNote(start, string, duration, notes, currTrackMeasures,(NoteEffect)effect.clone());
293
int read = readByte();
294
if (read >= 8 && read < 32) {
299
return duration.getTime();
302
private List getPlayedStrings(int stringsPlayed, List trackStrings) {
303
List strings = new ArrayList();
304
if ((stringsPlayed & (1 << 0)) != 0 && trackStrings.size() > 6) {
305
strings.add(((InstrumentString) trackStrings.get(6)).clone());
307
if ((stringsPlayed & (1 << 1)) != 0 && trackStrings.size() > 5) {
308
strings.add(((InstrumentString) trackStrings.get(5)).clone());
310
if ((stringsPlayed & (1 << 2)) != 0 && trackStrings.size() > 4) {
311
strings.add(((InstrumentString) trackStrings.get(4)).clone());
313
if ((stringsPlayed & (1 << 3)) != 0 && trackStrings.size() > 3) {
314
strings.add(((InstrumentString) trackStrings.get(3)).clone());
316
if ((stringsPlayed & (1 << 4)) != 0 && trackStrings.size() > 2) {
317
strings.add(((InstrumentString) trackStrings.get(2)).clone());
319
if ((stringsPlayed & (1 << 5)) != 0 && trackStrings.size() > 1) {
320
strings.add(((InstrumentString) trackStrings.get(1)).clone());
322
if ((stringsPlayed & (1 << 6)) != 0 && trackStrings.size() > 0) {
323
strings.add(((InstrumentString) trackStrings.get(0)).clone());
328
private Duration parseDuration(byte value) {
329
Duration duration = null;
332
duration = new Duration(Duration.WHOLE);
335
duration = new Duration(Duration.HALF);
338
duration = new Duration(Duration.QUARTER);
341
duration = new Duration(Duration.EIGHTH);
344
duration = new Duration(Duration.SIXTEENTH);
347
duration = new Duration(Duration.THIRTY_SECOND);
350
duration = new Duration(Duration.SIXTY_FOURTH);
353
if(duration == null){
354
duration = new Duration(Duration.QUARTER);
355
System.err.println("Incorrect Duration. Forcing duration Quarter as Default.");
360
private int getTiedNoteValue(int string, List notes, List measures) {
361
if (!notes.isEmpty()) {
362
for (int nIdx = notes.size() - 1; nIdx >= 0; nIdx--) {
363
Note note = (Note) notes.get(nIdx);
364
if (note.getString() == string) {
365
return note.getValue();
369
if (!measures.isEmpty()) {
370
for (int mIdx = measures.size() - 1; mIdx >= 0; mIdx--) {
371
Measure measure = (Measure) measures.get(mIdx);
372
for (int nIdx = measure.getNotes().size() - 1; nIdx >= 0; nIdx--) {
373
Note note = (Note) measure.getNotes().get(nIdx);
374
if (note.getString() == string) {
375
return note.getValue();
383
private boolean readBoolean() throws IOException {
384
return (read() == 1);
387
private byte readByte() throws IOException {
388
return (byte) read();
391
private RGBColor readColor() throws IOException {
392
int r = readUnsignedByte();
393
int g = readUnsignedByte();
394
int b = readUnsignedByte();
397
return new RGBColor(r,g,b);
400
private int readInt() throws IOException {
402
byte[] b = { 0, 0, 0, 0 };
405
integer = ((b[3] & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff);
410
private Marker readMarker(int measure) throws IOException {
411
String name = readStringIntegerPlusOne();
412
RGBColor color = readColor();
414
return new Marker(measure,name,color);
417
private MeasureHeader createMeasureHeader(int number,TimeSignature currTimeSignature) throws IOException {
418
int header = readUnsignedByte();
421
if ((header & 0x01) != 0) {
422
numerator = readByte();
426
if ((header & 0x02) != 0) {
427
denominator = readByte();
430
boolean repeatStart = ((header & 0x04) != 0);
432
int numberOfRepetitions = 0;
433
if ((header & 0x08) != 0) {
434
numberOfRepetitions = (readByte() - 1);
437
Marker marker = null;
438
if ((header & 0x20) != 0) {
439
marker = readMarker(number);
442
int NumberOfAlternateEnding = 0;
443
if ((header & 0x10) != 0) {
444
NumberOfAlternateEnding = readByte();
447
if ((header & 0x40) != 0) {
448
int type = readByte();
452
if ((header & 0x80) != 0) {
455
boolean doubleBar = ((header & 0x80) != 0);
458
currTimeSignature.setNumerator(numerator);
460
if (denominator > 0) {
461
currTimeSignature.setDenominator(new Duration(denominator));
464
//--------------------------------
465
if(NumberOfAlternateEnding == 0){
469
if ((header & 0x01) != 0) {
473
int tripletFeel = MeasureHeader.TRIPLET_FEEL_NONE;
474
int gpTripletFeel = readByte();
475
if(gpTripletFeel == 1){
476
tripletFeel = MeasureHeader.TRIPLET_FEEL_EIGHTH;
477
}else if(gpTripletFeel == 2){
478
tripletFeel = MeasureHeader.TRIPLET_FEEL_SIXTEENTH;
481
return new MeasureHeader(number,0,(TimeSignature) currTimeSignature.clone(), new Tempo(120),marker,tripletFeel,repeatStart,numberOfRepetitions);
484
private void addMeasureComponents(List trackStrings, Measure measure, List currTrackMeasures, Tempo tempo) throws IOException,GPFormatException {
486
long nextNoteStart = measure.getStart();
487
int numberOfBeats = readInt();
488
for (int i = 0; i < numberOfBeats; i++) {
489
nextNoteStart += addNotes(nextNoteStart, measure.getNotes(), trackStrings, currTrackMeasures, tempo);
491
int noteCount = measure.getNotes().size();
494
nextNoteStart = measure.getStart();
495
numberOfBeats = readInt();
496
for (int i = 0; i < numberOfBeats; i++) {
497
nextNoteStart += addNotes(nextNoteStart, measure.getNotes(), trackStrings, currTrackMeasures, tempo);
501
if(noteCount < measure.getNotes().size()){
502
new JoinVoicesHelper(measure).process();
506
private Note parseNote(long start, InstrumentString string, Duration currDuration, List currMeasureNotes, List currTrackMeasures,NoteEffect effect)
508
int header = readUnsignedByte();
510
effect.setAccentuatedNote(((header & 0x40) != 0));
511
effect.setHeavyAccentuatedNote(((header & 0x02) != 0));
512
effect.setGhostNote(((header & 0x04) != 0));
513
boolean tiedNote = false;
514
boolean deadNote = false;
515
if ((header & 0x20) != 0) {
516
int noteType = readUnsignedByte();
517
tiedNote = (noteType == 0x02);
518
effect.setDeadNote((noteType == 0x03));
521
if ((header & 0x01) != 0) {
522
//byte duration = readByte();
523
//byte tuplet = readByte();
526
int velocity = VelocityValues.DEFAULT;
527
if ((header & 0x10) != 0) {
528
velocity = (VelocityValues.MIN_VELOCITY + (VelocityValues.VELOCITY_INCREMENT * readByte())) - VelocityValues.VELOCITY_INCREMENT;
531
byte numberOfFret = 0;
532
if ((header & 0x20) != 0) {
533
numberOfFret = readByte();
536
if ((header & 0x80) != 0) {
537
byte fingeringLeftHand = readByte();
538
byte fingeringRightHand = readByte();
541
//cuando la duracion de la nota no es 100%
542
if ((header & 0x01) != 0) {
547
if ((header & 0x08) != 0) {
548
readNoteEffects(effect,currDuration);
551
int value = numberOfFret;
552
if (numberOfFret >= 0 || tiedNote) {
554
value = getTiedNoteValue(string.getNumber(), currMeasureNotes, currTrackMeasures);
557
return new Note(value, start, (Duration) currDuration.clone(), velocity, string.getNumber(),tiedNote,effect);
563
private String readStringByte(int expectedLength) throws IOException {
565
int realLength = readUnsignedByte();
567
if (expectedLength != 0) {
568
bytes = new byte[expectedLength];
570
bytes = new byte[realLength];
574
realLength = (realLength >= 0)?realLength:expectedLength;
575
return new String(bytes, 0, realLength);
578
private String readStringInteger() throws IOException {
581
int length = readInt();
583
b = new byte[length];
590
private String readStringIntegerPlusOne() throws IOException {
593
int lengthPlusOne = readInt();
594
int length = lengthPlusOne - 1;
596
if (length != read()) {
597
throw new IOException();
600
b = new byte[length];
607
private SongTrack createTrack(int number, List channels,Lyric lyrics) throws IOException {
611
int header = readUnsignedByte();
613
boolean isDrumsTrack = ((header & 0x01) != 0);
614
boolean is12StringedGuitarTrack = ((header & 0x02) != 0);
615
boolean isBanjoTrack = ((header & 0x04) != 0);
618
String name = readStringByte(40);
621
int numberOfStrings = readInt();
623
List strings = new ArrayList(numberOfStrings);
625
for (int i = 0; i < 7; i++) {
626
int tunning = readInt();
627
if (numberOfStrings > i) {
628
strings.add(new InstrumentString(i + 1, tunning));
632
int port = readInt();
634
int channelIndex = readInt();
636
int effects = readInt();
638
int numberOfFrets = readInt();
640
int capo = readInt();
642
RGBColor color = readColor();
646
return new SongTrack(number,name,parseChannel(channels,channelIndex,effects), new ArrayList(), strings,capo,color,lyrics);
649
private SongChannel parseChannel(List channels, int channelIndex,int effectChannel) {
650
SongChannel channel = (SongChannel) channels.get(channelIndex - 1);
652
int instrument = channel.getInstrument();
653
if (instrument == -1) {
654
channel.setInstrument((short)0);
656
if(!channel.isPercusionChannel()){
657
channel.setEffectChannel((short)(effectChannel - 1));
664
private int readUnsignedByte() throws IOException {
668
private void readChordType() throws IOException {
672
private void readRoot() throws IOException {
676
private void readTonalityType(int numBytes) throws IOException {
678
int type = readUnsignedByte();
679
} else if (numBytes == 4) {
680
int type = readInt();
684
private String readChordName() throws IOException {
690
nameB = new byte[21];
691
nameC = new char[20];
694
if (nameB[0] < max) {
698
for (i = 1; i <= max; i++) {
699
nameC[i - 1] = (char) nameB[i];
701
return (String.valueOf(nameC, 0, max));
704
private void readChordDiagram() throws IOException, GPFormatException {
710
header = readUnsignedByte();
712
if ((header & 0x01) == 0) {
713
throw new GPFormatException("Cannot Read Chord Diagram");
716
boolean sharp = readBoolean();
724
int nineElevenThirteen = readUnsignedByte();
726
int bass = readInt();
730
int addedNote = readUnsignedByte();
732
String name = readChordName();
742
int baseFret = readInt();
744
for (i = 1; i <= 7; i++) {
745
int fret = readInt();
748
int numBarres = readUnsignedByte();
750
for (i = 1; i <= 5; i++) {
751
int fretOfBarre = readUnsignedByte();
753
for (i = 1; i <= 5; i++) {
754
int barreStart = readUnsignedByte();
756
for (i = 1; i <= 5; i++) {
757
int barreEnd = readUnsignedByte();
762
for (i = 1; i <= 7; i++) {
763
int fingering = readByte();
765
boolean chordFingeringDisplayed = readBoolean();
768
private void readGraceNote() throws IOException {
772
private void readGraceNote(NoteEffect effect) throws IOException {
773
int fret = readByte();
774
int velocity = readByte();
775
int transition = readByte();
776
int duration = readByte();
777
int onBeat = readByte();
781
boolean dead = (fret == 255);
784
fret = ((!dead)?fret:0);
787
velocity = (VelocityValues.MIN_VELOCITY + (VelocityValues.VELOCITY_INCREMENT * velocity)) - VelocityValues.VELOCITY_INCREMENT;
791
transition = GraceEffect.TRANSITION_NONE;
793
else if(transition == 1){
794
transition = GraceEffect.TRANSITION_SLIDE;
796
else if(transition == 2){
797
transition = GraceEffect.TRANSITION_BEND;
799
else if(transition == 3){
800
transition = GraceEffect.TRANSITION_HAMMER;
803
effect.setGrace(new GraceEffect(fret,duration,velocity,transition,(onBeat > 0),dead));
806
private void readBend(NoteEffect effect) throws IOException {
807
byte type = readByte();
808
int value = readInt();
810
BendEffect bend = new BendEffect();
811
int numPoints = readInt();
812
for (int i = 0; i < numPoints; i++) {
814
int bendPosition = readInt();
815
int bendValue = readInt();
816
byte bendVibrato = readByte();
818
bend.addPoint((int)(bendPosition * BendEffect.MAX_POSITION_LENGTH / GP_BEND_POSITION),(bendValue * BendEffect.SEMITONE_LENGTH / GP_BEND_SEMITONE));
820
if(!bend.getPoints().isEmpty()){
821
effect.setBend(bend);
825
private void readTremoloBar(NoteEffect effect) throws IOException {
826
byte type = readByte();
827
int value = readInt();
829
TremoloBarEffect tremoloBar = new TremoloBarEffect();
830
int numPoints = readInt();
831
for (int i = 0; i < numPoints; i++) {
832
int bendPosition = readInt();
833
int bendValue = readInt();
834
byte bendVibrato = readByte();
836
tremoloBar.addPoint((int)(bendPosition * TremoloBarEffect.MAX_POSITION_LENGTH / GP_BEND_POSITION),(bendValue * TremoloBarEffect.SEMITONE_LENGTH / GP_BEND_SEMITONE));
838
if(!tremoloBar.getPoints().isEmpty()){
839
effect.setTremoloBar(tremoloBar);
843
private void readNoteEffects(NoteEffect noteEffect,Duration duration) throws IOException {
848
header1 = readUnsignedByte();
849
header2 = readUnsignedByte();
852
if ((header1 & 0x01) != 0) {
853
readBend(noteEffect);
857
if ((header1 & 0x10) != 0) {
858
readGraceNote(noteEffect);
862
if ((header2 & 0x04) != 0) {
863
readTremoloPicking(noteEffect);
867
if ((header2 & 0x08) != 0) {
868
noteEffect.setSlide(true);
873
if ((header2 & 0x10) != 0) {
874
readArtificialHarmonic(noteEffect);
878
if ((header2 & 0x20) != 0) {
879
byte fret = readByte();
880
byte period = readByte();
882
noteEffect.setTrill(new TrillEffect(fret,new Duration(Duration.SIXTEENTH)));
883
}else if(period == 2){
884
noteEffect.setTrill(new TrillEffect(fret,new Duration(Duration.THIRTY_SECOND)));
885
}else if(period == 3){
886
noteEffect.setTrill(new TrillEffect(fret,new Duration(Duration.SIXTY_FOURTH)));
891
noteEffect.setHammer(((header1 & 0x02) != 0));
894
noteEffect.setVibrato(((header2 & 0x40) != 0) || noteEffect.isVibrato());
897
noteEffect.setPalmMute(((header2 & 0x02) != 0));
900
noteEffect.setStaccato(((header2 & 0x01) != 0));
903
private void readBeatEffects(NoteEffect noteEffect,Duration currDuration) throws IOException {
904
int header[] = { 0, 0 };
906
header[0] = readUnsignedByte();
907
header[1] = readUnsignedByte();
909
noteEffect.setFadeIn(((header[0] & 0x10) != 0));
910
noteEffect.setVibrato(((header[0] & 0x02) != 0));
912
if ((header[0] & 0x20) != 0) {
913
int effect = readUnsignedByte();
914
noteEffect.setTapping(effect == 1);
915
noteEffect.setSlapping(effect == 2);
916
noteEffect.setPopping(effect == 3);
919
if ((header[1] & 0x04) != 0) {
920
readTremoloBar(noteEffect);
923
if ((header[0] & 0x40) != 0) {
924
//Upstroke - Downstroke
929
if ((header[1] & 0x01) != 0) {
933
if ((header[1] & 0x02) != 0) {
939
private void readMixChange(Tempo currentTempo) throws IOException {
940
int instrument = readByte();
943
int volume = readByte();
944
int pan = readByte();
945
int chorus = readByte();
946
int reverb = readByte();
947
int phaser = readByte();
948
int tremolo = readByte();
949
String tempoName = readStringInteger();
950
int tempo = readInt();
952
int type = readByte();
955
int type = readByte();
958
int type = readByte();
961
int type = readByte();
964
int type = readByte();
967
int type = readByte();
970
currentTempo.setValue(tempo);
971
int type = readByte();
973
int applyToAllTracks = readByte();
977
private void readArtificialHarmonic(NoteEffect effect) throws IOException{
978
int harmonic = readByte();
980
effect.setHarmonic(new HarmonicEffect(HarmonicEffect.TYPE_NATURAL));
982
else if(harmonic == 2){
983
int note = readByte();
984
int natural = readByte();
985
int type = readByte();
986
effect.setHarmonic(new HarmonicEffect(HarmonicEffect.TYPE_ARTIFICIAL,0));
987
}else if(harmonic == 3){
988
effect.setHarmonic(new HarmonicEffect(HarmonicEffect.TYPE_TAPPED,readByte()));
989
}else if(harmonic == 4){
990
effect.setHarmonic(new HarmonicEffect(HarmonicEffect.TYPE_PINCH));
991
}else if(harmonic == 5){
992
effect.setHarmonic(new HarmonicEffect(HarmonicEffect.TYPE_SEMI));
1000
public void readTremoloPicking(NoteEffect effect) throws IOException{
1001
int duration = readUnsignedByte();
1003
effect.setTremoloPicking(new TremoloPickingEffect(new Duration(Duration.EIGHTH)));
1004
}else if(duration == 2){
1005
effect.setTremoloPicking(new TremoloPickingEffect(new Duration(Duration.SIXTEENTH)));
1006
}else if(duration == 3){
1007
effect.setTremoloPicking(new TremoloPickingEffect(new Duration(Duration.THIRTY_SECOND)));
1011
private short toChannelShort(byte b){
1013
s = (short)((s * (short)127) / (short)16);
1014
return (s <= 127)?s:127;
1017
private void skipBytes(int count) throws IOException{
1018
for(int i = 0;i < count;i ++){
1024
private void skipBytes(int count,boolean debug) throws IOException{
1025
System.out.println("---------");
1026
for(int i = 0;i < count;i ++){
1028
System.out.println(b);
1030
System.out.println("---------");
1033
class JoinVoicesHelper{
1034
private Measure measure;
1036
public JoinVoicesHelper(Measure measure){
1037
this.measure = measure;
1040
public void process(){
1041
if(!measure.getNotes().isEmpty()){
1044
long start = ((Note)measure.getNotes().get(0)).getStart();
1045
long measureStart = measure.getStart();
1046
long measureLength = measure.getLength();
1047
while(start < (measureStart + measureLength)){
1048
List notesAtBeat = getNotesAtBeat(start);
1049
long maxLength = getMaxLength(start);
1050
normalizeNotes(notesAtBeat,maxLength);
1056
private void normalizeNotes(List notes,long maxLength){
1057
Duration beatDuration = null;
1059
Iterator it = notes.iterator();
1060
while(it.hasNext()){
1061
Note note = (Note)it.next();
1062
long noteDuration = note.getDuration().getTime();
1063
if(noteDuration <= maxLength && (beatDuration == null || noteDuration > beatDuration.getTime())){
1064
beatDuration = note.getDuration();
1067
if(beatDuration == null){
1068
beatDuration = Duration.fromTime(maxLength);
1070
if(beatDuration != null){
1071
it = notes.iterator();
1072
while(it.hasNext()){
1073
Note note = (Note)it.next();
1074
note.setDuration((Duration)beatDuration.clone());
1079
private List getNotesAtBeat(long start){
1080
List notes = new ArrayList();
1081
Iterator it = measure.getNotes().iterator();
1082
while(it.hasNext()){
1083
Note note = (Note)it.next();
1084
if(note.getStart() == start){
1091
private long getMaxLength(long start){
1092
long nextStart = -1;
1093
Iterator it = measure.getNotes().iterator();
1094
while(it.hasNext()){
1095
Note note = (Note)it.next();
1096
if(note.getStart() > start && (nextStart < 0 || note.getStart() < nextStart)){
1097
nextStart = note.getStart();
1101
nextStart = (measure.getStart() + measure.getLength());
1103
return (nextStart - start);
1106
private void orderNotes(){
1107
int noteCount = measure.getNotes().size();
1108
for(int i = 0;i < noteCount;i++){
1109
Note minNote = null;
1110
for(int noteIdx = i;noteIdx < noteCount;noteIdx++){
1111
Note note = (Note)measure.getNotes().get(noteIdx);
1112
if(minNote == null){
1114
}else if(note.getStart() < minNote.getStart()){
1116
}else if(note.getStart() == minNote.getStart() && note.getString() < minNote.getString()){
1120
measure.getNotes().remove(minNote);
1121
measure.getNotes().add(i,minNote);