~ubuntu-branches/ubuntu/oneiric/tuxguitar/oneiric

« back to all changes in this revision

Viewing changes to TuxGuitar-gtp/src/org/herac/tuxguitar/io/gtp/GP3InputStream.java

  • Committer: Bazaar Package Importer
  • Author(s): Philippe Coval
  • Date: 2008-06-19 00:30:30 UTC
  • mto: (5.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20080619003030-h719szrhsngou7c6
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.io.base.TGInputStreamBase;
 
10
import org.herac.tuxguitar.song.models.TGBeat;
 
11
import org.herac.tuxguitar.song.models.TGChannel;
 
12
import org.herac.tuxguitar.song.models.TGChord;
 
13
import org.herac.tuxguitar.song.models.TGColor;
 
14
import org.herac.tuxguitar.song.models.TGDuration;
 
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.TGTempo;
 
23
import org.herac.tuxguitar.song.models.TGText;
 
24
import org.herac.tuxguitar.song.models.TGTimeSignature;
 
25
import org.herac.tuxguitar.song.models.TGTrack;
 
26
import org.herac.tuxguitar.song.models.TGVelocities;
 
27
import org.herac.tuxguitar.song.models.effects.TGEffectBend;
 
28
import org.herac.tuxguitar.song.models.effects.TGEffectGrace;
 
29
import org.herac.tuxguitar.song.models.effects.TGEffectHarmonic;
 
30
import org.herac.tuxguitar.song.models.effects.TGEffectTremoloBar;
 
31
 
 
32
/**
 
33
 * @author julian
 
34
 * 
 
35
 * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
 
36
 */
 
37
public class GP3InputStream extends GTPInputStream implements TGInputStreamBase {
 
38
        private static final String SUPPORTED_VERSIONS[] = new String[]{ "FICHIER GUITAR PRO v3.00" };
 
39
        private static final float GP_BEND_SEMITONE = 25f;
 
40
        private static final float GP_BEND_POSITION = 60f;
 
41
        
 
42
        private int tripletFeel;
 
43
        
 
44
        public GP3InputStream(){
 
45
                super(SUPPORTED_VERSIONS);
 
46
        }
 
47
        
 
48
        public TGFileFormat getFileFormat(){
 
49
                return new TGFileFormat("Guitar Pro 3","*.gp3");
 
50
        }
 
51
        
 
52
        public TGSong readSong() throws GTPFormatException, IOException {
 
53
                readVersion();
 
54
                if (!isSupportedVersion(getVersion())) {
 
55
                        this.close();
 
56
                        throw new GTPFormatException("Unsuported Version");
 
57
                }
 
58
                TGSong song = getFactory().newSong();
 
59
                
 
60
                readInfo(song);
 
61
                
 
62
                this.tripletFeel = ((readBoolean())?TGMeasureHeader.TRIPLET_FEEL_EIGHTH:TGMeasureHeader.TRIPLET_FEEL_NONE);
 
63
                
 
64
                int tempoValue = readInt();
 
65
                
 
66
                readInt(); //key
 
67
                
 
68
                List channels = readChannels();
 
69
                
 
70
                int measures = readInt();
 
71
                int tracks = readInt();
 
72
                
 
73
                readMeasureHeaders(song, measures);
 
74
                readTracks(song, tracks, channels);
 
75
                readMeasures(song, measures, tracks, tempoValue);
 
76
                
 
77
                this.close();
 
78
                
 
79
                return song;
 
80
        }
 
81
        
 
82
        private List readChannels() throws IOException{
 
83
                List channels = new ArrayList();
 
84
                for (int i = 0; i < 64; i++) {
 
85
                        TGChannel channel = getFactory().newChannel();
 
86
                        channel.setChannel((short)i);
 
87
                        channel.setEffectChannel((short)i);
 
88
                        channel.setInstrument((short)readInt());
 
89
                        channel.setVolume(toChannelShort(readByte()));
 
90
                        channel.setBalance(toChannelShort(readByte()));
 
91
                        channel.setChorus(toChannelShort(readByte()));
 
92
                        channel.setReverb(toChannelShort(readByte()));
 
93
                        channel.setPhaser(toChannelShort(readByte()));
 
94
                        channel.setTremolo(toChannelShort(readByte()));
 
95
                        channel.setSolo(false);
 
96
                        channel.setMute(false);
 
97
                        channels.add(channel);
 
98
                        skip(2);
 
99
                }
 
100
                return channels;
 
101
        }
 
102
        
 
103
        private void readInfo(TGSong song) throws IOException{
 
104
                song.setName(readStringByteSizeOfInteger());
 
105
                readStringByteSizeOfInteger();
 
106
                song.setArtist(readStringByteSizeOfInteger());
 
107
                song.setAlbum(readStringByteSizeOfInteger());
 
108
                song.setAuthor(readStringByteSizeOfInteger());
 
109
                readStringByteSizeOfInteger();
 
110
                readStringByteSizeOfInteger();
 
111
                readStringByteSizeOfInteger();
 
112
                int notes = readInt();
 
113
                for (int i = 0; i < notes; i++) {
 
114
                        readStringByteSizeOfInteger();
 
115
                }
 
116
        }
 
117
        
 
118
        private void readMeasureHeaders(TGSong song, int count) throws IOException{
 
119
                TGTimeSignature timeSignature = getFactory().newTimeSignature();
 
120
                for (int i = 0; i < count; i++) {
 
121
                        song.addMeasureHeader(readMeasureHeader((i + 1),song,timeSignature));
 
122
                }
 
123
        }
 
124
        
 
125
        private void readTracks(TGSong song, int count, List channels) throws IOException{
 
126
                for (int number = 1; number <= count; number++) {
 
127
                        song.addTrack(readTrack(number, channels));
 
128
                }
 
129
        }
 
130
        
 
131
        private void readMeasures(TGSong song, int measures, int tracks, int tempoValue) throws IOException{
 
132
                TGTempo tempo = getFactory().newTempo();
 
133
                tempo.setValue(tempoValue);
 
134
                long start = TGDuration.QUARTER_TIME;
 
135
                for (int i = 0; i < measures; i++) {
 
136
                        TGMeasureHeader header = song.getMeasureHeader(i);
 
137
                        header.setStart(start);
 
138
                        for (int j = 0; j < tracks; j++) {
 
139
                                TGTrack track = song.getTrack(j);
 
140
                                TGMeasure measure = getFactory().newMeasure(header);
 
141
                                track.addMeasure(measure);
 
142
                                readMeasure(measure, track, tempo);
 
143
                        }
 
144
                        tempo.copy(header.getTempo());
 
145
                        start += header.getLength();
 
146
                }
 
147
        }
 
148
        
 
149
        private TGDuration readDuration(int flags) throws IOException {
 
150
                TGDuration duration = getFactory().newDuration();
 
151
                duration.setValue( (int) (Math.pow( 2 , (readByte() + 4) ) / 4 ) );
 
152
                duration.setDotted(((flags & 0x01) != 0));
 
153
                if ((flags & 0x20) != 0) {
 
154
                        int tuplet = readInt();
 
155
                        switch (tuplet) {
 
156
                        case 3:
 
157
                                duration.getTupleto().setEnters(3);
 
158
                                duration.getTupleto().setTimes(2);
 
159
                                break;
 
160
                        case 5:
 
161
                                duration.getTupleto().setEnters(5);
 
162
                                duration.getTupleto().setTimes(4);
 
163
                                break;
 
164
                        case 6:
 
165
                                duration.getTupleto().setEnters(6);
 
166
                                duration.getTupleto().setTimes(4);
 
167
                                break;
 
168
                        case 7:
 
169
                                duration.getTupleto().setEnters(7);
 
170
                                duration.getTupleto().setTimes(4);
 
171
                                break;
 
172
                        case 9:
 
173
                                duration.getTupleto().setEnters(9);
 
174
                                duration.getTupleto().setTimes(8);
 
175
                                break;
 
176
                        case 10:
 
177
                                duration.getTupleto().setEnters(10);
 
178
                                duration.getTupleto().setTimes(8);
 
179
                                break;
 
180
                        case 11:
 
181
                                duration.getTupleto().setEnters(11);
 
182
                                duration.getTupleto().setTimes(8);
 
183
                                break;
 
184
                        case 12:
 
185
                                duration.getTupleto().setEnters(12);
 
186
                                duration.getTupleto().setTimes(8);
 
187
                                break;
 
188
                        }
 
189
                }
 
190
                return duration;
 
191
        }
 
192
        
 
193
        private int getTiedNoteValue(int string, TGTrack track) {
 
194
                int measureCount = track.countMeasures();
 
195
                if (measureCount > 0) {
 
196
                        for (int m = measureCount - 1; m >= 0; m--) {
 
197
                                TGMeasure measure = track.getMeasure( m );
 
198
                                for (int b = measure.countBeats() - 1; b >= 0; b--) {
 
199
                                        TGBeat beat = measure.getBeat( b );
 
200
                                        for (int n = 0; n < beat.countNotes(); n ++) {
 
201
                                                TGNote note = beat.getNote( n );
 
202
                                                if (note.getString() == string) {
 
203
                                                        return note.getValue();
 
204
                                                }
 
205
                                        }
 
206
                                }
 
207
                        }
 
208
                }
 
209
                return -1;
 
210
        }
 
211
        
 
212
        private void readColor(TGColor color) throws IOException {
 
213
                color.setR(readUnsignedByte());
 
214
                color.setG(readUnsignedByte());
 
215
                color.setB(readUnsignedByte());
 
216
                read();
 
217
        }
 
218
        
 
219
        private TGMarker readMarker(int measure) throws IOException {
 
220
                TGMarker marker = getFactory().newMarker();
 
221
                marker.setMeasure(measure);
 
222
                marker.setTitle(readStringByteSizeOfInteger());
 
223
                readColor(marker.getColor());
 
224
                return marker;
 
225
        }
 
226
        
 
227
        private TGMeasureHeader readMeasureHeader(int number,TGSong song,TGTimeSignature timeSignature) throws IOException {
 
228
                int flags = readUnsignedByte();
 
229
                TGMeasureHeader header = getFactory().newHeader();
 
230
                header.setNumber(number);
 
231
                header.setStart(0);
 
232
                header.getTempo().setValue(120);
 
233
                header.setTripletFeel(this.tripletFeel);
 
234
                header.setRepeatOpen( ((flags & 0x04) != 0) );
 
235
                
 
236
                if ((flags & 0x01) != 0) {
 
237
                        timeSignature.setNumerator(readByte());
 
238
                }
 
239
                if ((flags & 0x02) != 0) {
 
240
                        timeSignature.getDenominator().setValue(readByte());
 
241
                }
 
242
                timeSignature.copy(header.getTimeSignature());
 
243
                if ((flags & 0x08) != 0) {
 
244
                        header.setRepeatClose(readByte());
 
245
                }
 
246
                if ((flags & 0x10) != 0) {
 
247
                        header.setRepeatAlternative( parseRepeatAlternative(song, number, readUnsignedByte()) );
 
248
                }
 
249
                if ((flags & 0x20) != 0) {
 
250
                        header.setMarker(readMarker(number));
 
251
                }
 
252
                if ((flags & 0x40) != 0) {
 
253
                        readByte();
 
254
                        readByte();
 
255
                }
 
256
                return header;
 
257
        }
 
258
        
 
259
        private void readMeasure(TGMeasure measure, TGTrack track, TGTempo tempo) throws IOException{
 
260
                long nextNoteStart = measure.getStart();
 
261
                int numberOfBeats = readInt();
 
262
                for (int i = 0; i < numberOfBeats; i++) {
 
263
                        nextNoteStart += readBeat(nextNoteStart, measure, track, tempo);
 
264
                }
 
265
        }
 
266
        
 
267
        private long readBeat(long start, TGMeasure measure,TGTrack track, TGTempo tempo) throws IOException{
 
268
                int flags = readUnsignedByte();
 
269
                if((flags & 0x40) != 0){
 
270
                        readUnsignedByte();
 
271
                }
 
272
                
 
273
                TGBeat beat = getFactory().newBeat();
 
274
                TGDuration duration = readDuration(flags);
 
275
                TGNoteEffect effect = getFactory().newEffect();
 
276
                if ((flags & 0x02) != 0) {
 
277
                        readChord(track.stringCount(),beat);
 
278
                }
 
279
                if ((flags & 0x04) != 0) {
 
280
                        readText(beat);
 
281
                }
 
282
                if ((flags & 0x08) != 0) {
 
283
                        readBeatEffects(effect);
 
284
                }
 
285
                if ((flags & 0x10) != 0) {
 
286
                        readMixChange(tempo);
 
287
                }
 
288
                int stringFlags = readUnsignedByte();
 
289
                for (int i = 6; i >= 0; i--) {
 
290
                        if ((stringFlags & (1 << i)) != 0 && (6 - i) < track.stringCount()) {
 
291
                                TGString string = track.getString( (6 - i) + 1 ).clone(getFactory());
 
292
                                TGNote note = readNote(string, track,effect.clone(getFactory()));
 
293
                                beat.addNote(note);
 
294
                        }
 
295
                }
 
296
                beat.setStart(start);
 
297
                duration.copy(beat.getDuration());
 
298
                measure.addBeat(beat);
 
299
                
 
300
                return duration.getTime();
 
301
        }
 
302
        
 
303
        private void readText(TGBeat beat) throws IOException{
 
304
                TGText text = getFactory().newText();
 
305
                text.setValue(readStringByteSizeOfInteger());
 
306
                beat.setText(text);
 
307
        }
 
308
        
 
309
        private TGNote readNote(TGString string,TGTrack track,TGNoteEffect effect) throws IOException {
 
310
                int flags = readUnsignedByte();
 
311
                TGNote note = getFactory().newNote();
 
312
                note.setString(string.getNumber());
 
313
                note.setEffect(effect);
 
314
                note.getEffect().setGhostNote(((flags & 0x04) != 0));
 
315
                if ((flags & 0x20) != 0) {
 
316
                        int noteType = readUnsignedByte();
 
317
                        note.setTiedNote( (noteType == 0x02) );
 
318
                        note.getEffect().setDeadNote((noteType == 0x03));
 
319
                }
 
320
                if ((flags & 0x01) != 0) {
 
321
                        skip(2);
 
322
                }
 
323
                if ((flags & 0x10) != 0) {
 
324
                        note.setVelocity( (TGVelocities.MIN_VELOCITY + (TGVelocities.VELOCITY_INCREMENT * readByte())) - TGVelocities.VELOCITY_INCREMENT );
 
325
                }
 
326
                if ((flags & 0x20) != 0) {
 
327
                        int fret = readByte();
 
328
                        int value = ( note.isTiedNote() ? getTiedNoteValue(string.getNumber(), track) : fret );
 
329
                        note.setValue( value >= 0 && value < 100 ? value : 0 );
 
330
                }
 
331
                if ((flags & 0x80) != 0) {
 
332
                        skip(2);
 
333
                }
 
334
                if ((flags & 0x08) != 0) {
 
335
                        readNoteEffects(note.getEffect());
 
336
                }
 
337
                return note;
 
338
        }
 
339
        
 
340
        private TGTrack readTrack(int number, List channels) throws IOException {
 
341
                TGTrack track = getFactory().newTrack();
 
342
                track.setNumber(number);
 
343
                readUnsignedByte();
 
344
                track.setName(readStringByte(40));
 
345
                int stringCount = readInt();
 
346
                for (int i = 0; i < 7; i++) {
 
347
                        int tuning = readInt();
 
348
                        if (stringCount > i) {
 
349
                                TGString string = getFactory().newString();
 
350
                                string.setNumber(i + 1);
 
351
                                string.setValue(tuning);
 
352
                                track.getStrings().add(string);
 
353
                        }
 
354
                }
 
355
                readInt();
 
356
                readChannel(track.getChannel(),channels);
 
357
                readInt();
 
358
                track.setOffset(readInt());
 
359
                readColor(track.getColor());
 
360
                return track;
 
361
        }
 
362
        
 
363
        private void readChannel(TGChannel channel,List channels) throws IOException {
 
364
                int index = (readInt() - 1);
 
365
                int effectChannel = (readInt() - 1);
 
366
                if(index >= 0 && index < channels.size()){
 
367
                        ((TGChannel) channels.get(index)).copy(channel);
 
368
                        if (channel.getInstrument() < 0) {
 
369
                                channel.setInstrument((short)0);
 
370
                        }
 
371
                        if(!channel.isPercussionChannel()){
 
372
                                channel.setEffectChannel((short)effectChannel);
 
373
                        }
 
374
                }
 
375
        }
 
376
        
 
377
        private int parseRepeatAlternative(TGSong song,int measure,int value){
 
378
                int repeatAlternative = 0;
 
379
                int existentAlternatives = 0;
 
380
                Iterator it = song.getMeasureHeaders();
 
381
                while(it.hasNext()){
 
382
                        TGMeasureHeader header = (TGMeasureHeader)it.next();
 
383
                        if(header.getNumber() == measure){
 
384
                                break;
 
385
                        }
 
386
                        if(header.isRepeatOpen()){
 
387
                                existentAlternatives = 0;
 
388
                        }
 
389
                        existentAlternatives |= header.getRepeatAlternative();
 
390
                }
 
391
                
 
392
                for(int i = 0; i < 8; i ++){
 
393
                        if(value > i && (existentAlternatives & (1 << i)) == 0){
 
394
                                repeatAlternative |= (1 << i);
 
395
                        }
 
396
                }
 
397
                return repeatAlternative;
 
398
        }
 
399
        
 
400
        private void readChord(int strings, TGBeat beat) throws IOException {
 
401
                TGChord chord = getFactory().newChord(strings);
 
402
                int header = readUnsignedByte();
 
403
                if ((header & 0x01) == 0) {
 
404
                        chord.setName(readStringByteSizeOfInteger());
 
405
                        chord.setFirstFret(readInt());
 
406
                        if (chord.getFirstFret() != 0) {
 
407
                                for (int i = 0; i < 6; i++) {
 
408
                                        int fret = readInt();
 
409
                                        if(i < chord.countStrings()){
 
410
                                                chord.addFretValue(i,fret);
 
411
                                        }
 
412
                                }
 
413
                        }
 
414
                }
 
415
                else{
 
416
                        skip(25);
 
417
                        chord.setName(readStringByte(34));
 
418
                        chord.setFirstFret(readInt());
 
419
                        for (int i = 0; i < 6; i++) {
 
420
                                int fret = readInt();
 
421
                                if(i < chord.countStrings()){
 
422
                                        chord.addFretValue(i,fret);
 
423
                                }
 
424
                        }
 
425
                        skip(36);
 
426
                }
 
427
                if(chord.countNotes() > 0){
 
428
                        beat.setChord(chord);
 
429
                }
 
430
        }
 
431
        
 
432
        private void readGrace(TGNoteEffect effect) throws IOException {
 
433
                int fret = readUnsignedByte();
 
434
                TGEffectGrace grace = getFactory().newEffectGrace();
 
435
                grace.setOnBeat(false);
 
436
                grace.setDead( (fret == 255) );
 
437
                grace.setFret( ((!grace.isDead())?fret:0) );
 
438
                grace.setDynamic( (TGVelocities.MIN_VELOCITY + (TGVelocities.VELOCITY_INCREMENT * readUnsignedByte())) - TGVelocities.VELOCITY_INCREMENT );
 
439
                int transition = readUnsignedByte();
 
440
                if(transition == 0){
 
441
                        grace.setTransition(TGEffectGrace.TRANSITION_NONE);
 
442
                }
 
443
                else if(transition == 1){
 
444
                        grace.setTransition(TGEffectGrace.TRANSITION_SLIDE);
 
445
                }
 
446
                else if(transition == 2){
 
447
                        grace.setTransition(TGEffectGrace.TRANSITION_BEND);
 
448
                }
 
449
                else if(transition == 3){
 
450
                        grace.setTransition(TGEffectGrace.TRANSITION_HAMMER);
 
451
                }
 
452
                grace.setDuration(readUnsignedByte());
 
453
                effect.setGrace(grace);
 
454
        }
 
455
        
 
456
        private void readBend(TGNoteEffect effect) throws IOException {
 
457
                TGEffectBend bend = getFactory().newEffectBend();
 
458
                skip(5);
 
459
                int points = readInt();
 
460
                for (int i = 0; i < points; i++) {
 
461
                        int bendPosition = readInt();
 
462
                        int bendValue = readInt();
 
463
                        readByte(); //vibrato
 
464
                        
 
465
                        int pointPosition = Math.round(bendPosition * TGEffectBend.MAX_POSITION_LENGTH / GP_BEND_POSITION);
 
466
                        int pointValue = Math.round(bendValue * TGEffectBend.SEMITONE_LENGTH / GP_BEND_SEMITONE);
 
467
                        bend.addPoint(pointPosition,pointValue);
 
468
                }
 
469
                if(!bend.getPoints().isEmpty()){
 
470
                        effect.setBend(bend);
 
471
                }
 
472
        }
 
473
        
 
474
        private void readTremoloBar(TGNoteEffect noteEffect) throws IOException {
 
475
                int value = readInt();
 
476
                TGEffectTremoloBar effect = getFactory().newEffectTremoloBar();
 
477
                effect.addPoint(0,0);
 
478
                effect.addPoint( Math.round(TGEffectTremoloBar.MAX_POSITION_LENGTH / 2f) ,Math.round( -(value / (GP_BEND_SEMITONE * 2f) ) ) );
 
479
                effect.addPoint(TGEffectTremoloBar.MAX_POSITION_LENGTH,0);
 
480
                noteEffect.setTremoloBar(effect);
 
481
        }
 
482
        
 
483
        private void readNoteEffects(TGNoteEffect effect) throws IOException {
 
484
                int flags = readUnsignedByte();
 
485
                effect.setSlide( ((flags & 0x04) != 0) );
 
486
                effect.setHammer( ((flags & 0x02) != 0) );
 
487
                if ((flags & 0x01) != 0) {
 
488
                        readBend(effect);
 
489
                }
 
490
                if ((flags & 0x10) != 0) {
 
491
                        readGrace(effect);
 
492
                }
 
493
        }
 
494
        
 
495
        private void readBeatEffects(TGNoteEffect effect) throws IOException {
 
496
                int flags = readUnsignedByte();
 
497
                effect.setVibrato(((flags & 0x01) != 0) || ((flags & 0x02) != 0));
 
498
                effect.setFadeIn(((flags & 0x10) != 0));
 
499
                if ((flags & 0x20) != 0) {
 
500
                        int type = readUnsignedByte();
 
501
                        if (type == 0) {
 
502
                                readTremoloBar(effect);
 
503
                        } else {
 
504
                                effect.setTapping(type == 1);
 
505
                                effect.setSlapping(type == 2);
 
506
                                effect.setPopping(type == 3);
 
507
                                readInt();
 
508
                        }
 
509
                }
 
510
                if ((flags & 0x40) != 0) {
 
511
                        readByte();
 
512
                        readByte();
 
513
                }
 
514
                if ((flags & 0x04) != 0) {
 
515
                        TGEffectHarmonic harmonic = getFactory().newEffectHarmonic();
 
516
                        harmonic.setType(TGEffectHarmonic.TYPE_NATURAL);
 
517
                        effect.setHarmonic(harmonic);
 
518
                }
 
519
                if ((flags & 0x08) != 0) {
 
520
                        TGEffectHarmonic harmonic = getFactory().newEffectHarmonic();
 
521
                        harmonic.setType(TGEffectHarmonic.TYPE_ARTIFICIAL);
 
522
                        harmonic.setData(0);
 
523
                        effect.setHarmonic(harmonic);
 
524
                }
 
525
        }
 
526
        
 
527
        private void readMixChange(TGTempo tempo) throws IOException {
 
528
                readByte(); //instrument
 
529
                int volume = readByte();
 
530
                int pan = readByte();
 
531
                int chorus = readByte();
 
532
                int reverb = readByte();
 
533
                int phaser = readByte();
 
534
                int tremolo = readByte();
 
535
                int tempoValue = readInt();
 
536
                if(volume >= 0){
 
537
                        readByte();
 
538
                }
 
539
                if(pan >= 0){
 
540
                        readByte();
 
541
                }
 
542
                if(chorus >= 0){
 
543
                        readByte();
 
544
                }
 
545
                if(reverb >= 0){
 
546
                        readByte();
 
547
                }
 
548
                if(phaser >= 0){
 
549
                        readByte();
 
550
                }
 
551
                if(tremolo >= 0){
 
552
                        readByte();
 
553
                }
 
554
                if(tempoValue >= 0){
 
555
                        tempo.setValue(tempoValue);
 
556
                        readByte();
 
557
                }
 
558
        }
 
559
        
 
560
        private short toChannelShort(byte b){
 
561
                short value = (short)(( b * 8 ) - 1);
 
562
                return (short)Math.max(value,0);
 
563
        }
 
564
}
 
 
b'\\ No newline at end of file'