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

« back to all changes in this revision

Viewing changes to TuxGuitar-gtp/src/org/herac/tuxguitar/io/gtp/GP5OutputStream.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
/*
 
2
 * Created on 09-ene-2006
 
3
 *
 
4
 * TODO To change the template for this generated file go to
 
5
 * Window - Preferences - Java - Code Style - Code Templates
 
6
 */
 
7
package org.herac.tuxguitar.io.gtp;
 
8
 
 
9
import java.io.IOException;
 
10
import java.util.Iterator;
 
11
 
 
12
import org.herac.tuxguitar.io.base.TGFileFormat;
 
13
import org.herac.tuxguitar.io.base.TGFileFormatException;
 
14
import org.herac.tuxguitar.song.models.TGBeat;
 
15
import org.herac.tuxguitar.song.models.TGChannel;
 
16
import org.herac.tuxguitar.song.models.TGChord;
 
17
import org.herac.tuxguitar.song.models.TGColor;
 
18
import org.herac.tuxguitar.song.models.TGDuration;
 
19
import org.herac.tuxguitar.song.models.TGMarker;
 
20
import org.herac.tuxguitar.song.models.TGMeasure;
 
21
import org.herac.tuxguitar.song.models.TGMeasureHeader;
 
22
import org.herac.tuxguitar.song.models.TGNote;
 
23
import org.herac.tuxguitar.song.models.TGNoteEffect;
 
24
import org.herac.tuxguitar.song.models.TGSong;
 
25
import org.herac.tuxguitar.song.models.TGString;
 
26
import org.herac.tuxguitar.song.models.TGTempo;
 
27
import org.herac.tuxguitar.song.models.TGText;
 
28
import org.herac.tuxguitar.song.models.TGTimeSignature;
 
29
import org.herac.tuxguitar.song.models.TGTrack;
 
30
import org.herac.tuxguitar.song.models.TGTupleto;
 
31
import org.herac.tuxguitar.song.models.TGVelocities;
 
32
import org.herac.tuxguitar.song.models.effects.TGEffectBend;
 
33
import org.herac.tuxguitar.song.models.effects.TGEffectGrace;
 
34
import org.herac.tuxguitar.song.models.effects.TGEffectTremoloBar;
 
35
import org.herac.tuxguitar.song.models.effects.TGEffectTremoloPicking;
 
36
import org.herac.tuxguitar.song.models.effects.TGEffectTrill;
 
37
 
 
38
/**
 
39
 * @author julian
 
40
 * 
 
41
 * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
 
42
 */
 
43
public class GP5OutputStream extends GTPOutputStream {
 
44
        private static final String GP5_FORMAT_EXTENSION = ".gp5";
 
45
        private static final String GP5_VERSION = "FICHIER GUITAR PRO v5.00";
 
46
        private static final int GP_BEND_SEMITONE = 25;
 
47
        private static final int GP_BEND_POSITION = 60;
 
48
        
 
49
        private static final String[] PAGE_SETUP_LINES = {
 
50
                "%TITLE%",
 
51
                "%SUBTITLE%",
 
52
                "%ARTIST%",
 
53
                "%ALBUM%",
 
54
                "Words by %WORDS%",
 
55
                "Music by %MUSIC%",
 
56
                "Words & Music by %WORDSMUSIC%",
 
57
                "Copyright %COPYRIGHT%",
 
58
                "All Rights Reserved - International Copyright Secured",
 
59
                "Page %N%/%P%",
 
60
                "Moderate",
 
61
        };
 
62
        
 
63
        public GP5OutputStream() {
 
64
                super();
 
65
        }
 
66
        
 
67
        public TGFileFormat getFileFormat(){
 
68
                return new TGFileFormat("Guitar Pro 5","*.gp5");
 
69
        }
 
70
        
 
71
        public boolean isSupportedExtension(String extension) {
 
72
                return (extension.toLowerCase().equals(GP5_FORMAT_EXTENSION)) ;
 
73
        }
 
74
        
 
75
        public void writeSong(TGSong song){
 
76
                try {
 
77
                        if(song.isEmpty()){
 
78
                                throw new TGFileFormatException("Empty Song!!!");
 
79
                        }
 
80
                        TGMeasureHeader header = song.getMeasureHeader(0);
 
81
                        writeStringByte(GP5_VERSION, 30);
 
82
                        writeInfo(song);
 
83
                        writeLyrics(song);
 
84
                        writePageSetup();
 
85
                        writeInt(header.getTempo().getValue());
 
86
                        writeInt(0);
 
87
                        writeByte((byte)0);
 
88
                        writeChannels(song);
 
89
                        for(int i = 0; i < 42; i ++){
 
90
                                writeByte((byte)0xff);
 
91
                        }
 
92
                        writeInt(song.countMeasureHeaders());
 
93
                        writeInt(song.countTracks());
 
94
                        writeMeasureHeaders(song);
 
95
                        writeTracks(song);
 
96
                        skipBytes(2);
 
97
                        writeMeasures(song, header.getTempo().clone(getFactory()));
 
98
                        close();
 
99
                } catch (Exception e) {
 
100
                        e.printStackTrace();
 
101
                }
 
102
        }
 
103
        
 
104
        private void writeInfo(TGSong song) throws IOException{
 
105
                writeStringByteSizeOfInteger(song.getName());
 
106
                writeStringByteSizeOfInteger("");
 
107
                writeStringByteSizeOfInteger(song.getArtist());
 
108
                writeStringByteSizeOfInteger(song.getAlbum());
 
109
                writeStringByteSizeOfInteger(song.getAuthor());
 
110
                writeStringByteSizeOfInteger("");
 
111
                writeStringByteSizeOfInteger("");
 
112
                writeStringByteSizeOfInteger("");
 
113
                writeStringByteSizeOfInteger("");
 
114
                writeInt(0);
 
115
        }
 
116
        
 
117
        private void writeLyrics(TGSong song) throws IOException{
 
118
                TGTrack lyricTrack = null;
 
119
                Iterator it = song.getTracks();
 
120
                while(it.hasNext()){
 
121
                        TGTrack track = (TGTrack)it.next();
 
122
                        if(!track.getLyrics().isEmpty()){
 
123
                                lyricTrack = track;
 
124
                                break;
 
125
                        }
 
126
                }
 
127
                writeInt( (lyricTrack == null)?0:lyricTrack.getNumber() );
 
128
                writeInt((lyricTrack == null)?0:lyricTrack.getLyrics().getFrom());
 
129
                writeStringInteger((lyricTrack == null)?"":lyricTrack.getLyrics().getLyrics());
 
130
                for (int i = 0; i < 4; i++) {
 
131
                        writeInt(0);
 
132
                        writeStringInteger("");
 
133
                }
 
134
        }
 
135
        
 
136
        private void writePageSetup() throws IOException{
 
137
                writeInt( 210 ); // Page width
 
138
                writeInt( 297 ); // Page height
 
139
                writeInt( 10 );  // Margin left
 
140
                writeInt( 10 );  // Margin right
 
141
                writeInt( 15 );  // Margin top
 
142
                writeInt( 10 );  // Margin bottom
 
143
                writeInt( 100 ); // Score size percent
 
144
                
 
145
                writeByte( ( byte )0xff ); // View flags
 
146
                writeByte( ( byte )0x01 ); // View flags
 
147
                
 
148
                for (int i = 0; i < PAGE_SETUP_LINES.length; i++) {
 
149
                        writeInt( (PAGE_SETUP_LINES[i].length() + 1) );
 
150
                        writeStringByte(PAGE_SETUP_LINES[i],0);
 
151
                }
 
152
        }
 
153
        
 
154
        private void writeChannels(TGSong song) throws IOException{
 
155
                TGChannel[] channels = makeChannels(song);
 
156
                for (int i = 0; i < channels.length; i++) {
 
157
                        writeInt(channels[i].getInstrument());
 
158
                        writeByte(toChannelByte(channels[i].getVolume()));
 
159
                        writeByte(toChannelByte(channels[i].getBalance()));
 
160
                        writeByte(toChannelByte(channels[i].getChorus()));
 
161
                        writeByte(toChannelByte(channels[i].getReverb()));
 
162
                        writeByte(toChannelByte(channels[i].getPhaser()));
 
163
                        writeByte(toChannelByte(channels[i].getTremolo()));
 
164
                        writeBytes(new byte[]{0,0});
 
165
                }
 
166
        }
 
167
        
 
168
        private void writeMeasureHeaders(TGSong song) throws IOException {
 
169
                TGTimeSignature timeSignature = getFactory().newTimeSignature();
 
170
                if (song.countMeasureHeaders() > 0) {
 
171
                        for (int i = 0; i < song.countMeasureHeaders(); i++) {
 
172
                                if(i > 0 ){
 
173
                                        skipBytes(1);
 
174
                                }
 
175
                                TGMeasureHeader measure = song.getMeasureHeader(i);
 
176
                                writeMeasureHeader(measure, timeSignature);
 
177
                                
 
178
                                timeSignature.setNumerator(measure.getTimeSignature().getNumerator());
 
179
                                timeSignature.getDenominator().setValue(measure.getTimeSignature().getDenominator().getValue());
 
180
                        }
 
181
                }
 
182
        }
 
183
        
 
184
        private void writeMeasureHeader(TGMeasureHeader measure, TGTimeSignature timeSignature) throws IOException {
 
185
                int flags = 0;
 
186
                if(measure.getNumber() == 1){
 
187
                        flags |= 0x40;
 
188
                }
 
189
                if (measure.getNumber() == 1 || measure.getTimeSignature().getNumerator() != timeSignature.getNumerator()) {
 
190
                        flags |= 0x01;
 
191
                }
 
192
                if (measure.getNumber() == 1 || measure.getTimeSignature().getDenominator().getValue() != timeSignature.getDenominator().getValue()) {
 
193
                        flags |= 0x02;
 
194
                }
 
195
                if (measure.isRepeatOpen()) {
 
196
                        flags |= 0x04;
 
197
                }
 
198
                if (measure.getRepeatClose() > 0) {
 
199
                        flags |= 0x08;
 
200
                }
 
201
                if (measure.getRepeatAlternative() > 0) {
 
202
                        flags |= 0x10;
 
203
                }
 
204
                if (measure.hasMarker()) {
 
205
                        flags |= 0x20;
 
206
                }
 
207
                writeUnsignedByte(flags);
 
208
                
 
209
                if ((flags & 0x01) != 0) {
 
210
                        writeByte((byte) measure.getTimeSignature().getNumerator());
 
211
                }
 
212
                if ((flags & 0x02) != 0) {
 
213
                        writeByte((byte) measure.getTimeSignature().getDenominator().getValue());
 
214
                }
 
215
                if ((flags & 0x08) != 0) {
 
216
                        writeByte((byte) (measure.getRepeatClose() + 1));
 
217
                }
 
218
                if ((flags & 0x20) != 0) {
 
219
                        writeMarker(measure.getMarker());
 
220
                }
 
221
                if ((flags & 0x10) != 0) {
 
222
                        writeByte((byte)measure.getRepeatAlternative());
 
223
                }
 
224
                if ((flags & 0x40) != 0) {
 
225
                        skipBytes(2);
 
226
                }
 
227
                if((flags & 0x10) == 0){
 
228
                        writeByte((byte)0);
 
229
                }
 
230
                if ((flags & 0x01) != 0) {
 
231
                        skipBytes(4);
 
232
                }
 
233
                if(measure.getTripletFeel() == TGMeasureHeader.TRIPLET_FEEL_NONE){
 
234
                        writeByte((byte)0);
 
235
                }
 
236
                else if(measure.getTripletFeel() == TGMeasureHeader.TRIPLET_FEEL_EIGHTH){
 
237
                        writeByte((byte)1);
 
238
                }
 
239
                else if(measure.getTripletFeel() == TGMeasureHeader.TRIPLET_FEEL_SIXTEENTH){
 
240
                        writeByte((byte)2);
 
241
                }
 
242
        }
 
243
        
 
244
        private void writeTracks(TGSong song) throws IOException {
 
245
                for (int i = 0; i < song.countTracks(); i++) {
 
246
                        TGTrack track = song.getTrack(i);
 
247
                        writeTrack(track);
 
248
                }
 
249
        }
 
250
        
 
251
        private void writeTrack(TGTrack track) throws IOException {
 
252
                int flags = 0;
 
253
                if (track.isPercussionTrack()) {
 
254
                        flags |= 0x01;
 
255
                }
 
256
                writeUnsignedByte(flags);
 
257
                writeByte((byte)8);
 
258
                writeStringByte(track.getName(), 40);
 
259
                writeInt(track.getStrings().size());
 
260
                for (int i = 0; i < 7; i++) {
 
261
                        int value = 0;
 
262
                        if (track.getStrings().size() > i) {
 
263
                                TGString string = (TGString) track.getStrings().get(i);
 
264
                                value = string.getValue();
 
265
                        }
 
266
                        writeInt(value);
 
267
                }
 
268
                writeInt(1);
 
269
                writeInt(track.getChannel().getChannel() + 1);
 
270
                writeInt(track.getChannel().getEffectChannel() + 1);
 
271
                writeInt(24);
 
272
                writeInt(track.getOffset());
 
273
                writeColor(track.getColor());
 
274
                writeBytes(new byte[]{ 67, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1});
 
275
        }
 
276
        
 
277
        private void writeMeasures(TGSong song, TGTempo tempo) throws IOException{
 
278
                for (int i = 0; i < song.countMeasureHeaders(); i++) {
 
279
                        for (int j = 0; j < song.countTracks(); j++) {
 
280
                                TGTrack track = song.getTrack(j);
 
281
                                TGMeasure measure = track.getMeasure(i);
 
282
                                writeMeasure(measure, tempo);
 
283
                                skipBytes(1);
 
284
                        }
 
285
                }
 
286
        }
 
287
        
 
288
        private void writeMeasure(TGMeasure measure, TGTempo tempo) throws IOException {
 
289
                int beatCount = measure.countBeats();
 
290
                writeInt(beatCount);
 
291
                for (int i = 0; i < beatCount; i++) {
 
292
                        TGBeat beat = measure.getBeat( i );
 
293
                        writeBeat(beat, measure, tempo);
 
294
                }
 
295
                writeInt(0);
 
296
        }
 
297
        
 
298
        private void writeBeat(TGBeat beat, TGMeasure measure, TGTempo tempo) throws IOException {
 
299
                TGDuration duration = beat.getDuration();
 
300
                TGNoteEffect effect = getFactory().newEffect();
 
301
                for (int i = 0; i < beat.countNotes(); i++) {
 
302
                        TGNote playedNote = beat.getNote(i);
 
303
                        
 
304
                        if(playedNote.getEffect().isFadeIn()){
 
305
                                effect.setFadeIn(true);
 
306
                        }
 
307
                        if(playedNote.getEffect().isTremoloBar()){
 
308
                                effect.setTremoloBar(playedNote.getEffect().getTremoloBar().clone(getFactory()));
 
309
                        }
 
310
                        if(playedNote.getEffect().isTapping()){
 
311
                                effect.setTapping(true);
 
312
                        }
 
313
                        if(playedNote.getEffect().isSlapping()){
 
314
                                effect.setSlapping(true);
 
315
                        }
 
316
                        if(playedNote.getEffect().isPopping()){
 
317
                                effect.setPopping(true);
 
318
                        }
 
319
                }
 
320
                
 
321
                int flags = 0;
 
322
                if (duration.isDotted() || duration.isDoubleDotted()) {
 
323
                        flags |= 0x01;
 
324
                }
 
325
                if (beat.isChordBeat()) {
 
326
                        flags |= 0x02;
 
327
                }
 
328
                if (beat.isTextBeat()) {
 
329
                        flags |= 0x04;
 
330
                }
 
331
                if (effect.isTremoloBar() || effect.isTapping() || effect.isSlapping() || effect.isPopping() || effect.isFadeIn()) {
 
332
                        flags |= 0x08;
 
333
                }
 
334
                if (measure.getTempo().getValue() != tempo.getValue()) {
 
335
                        flags |= 0x10;
 
336
                }
 
337
                if (!duration.getTupleto().isEqual(TGTupleto.NORMAL)) {
 
338
                        flags |= 0x20;
 
339
                }
 
340
                if (beat.isRestBeat()) {
 
341
                        flags |= 0x40;
 
342
                }
 
343
                writeUnsignedByte(flags);
 
344
                
 
345
                if ((flags & 0x40) != 0) {
 
346
                        writeUnsignedByte(0x02);
 
347
                }
 
348
                writeByte(parseDuration(duration));
 
349
                if ((flags & 0x20) != 0) {
 
350
                        writeInt(duration.getTupleto().getEnters());
 
351
                }
 
352
                
 
353
                if ((flags & 0x02) != 0) {
 
354
                        writeChord(beat.getChord());
 
355
                }
 
356
                
 
357
                if ((flags & 0x04) != 0) {
 
358
                        writeText(beat.getText());
 
359
                }
 
360
                
 
361
                if ((flags & 0x08) != 0) {
 
362
                        writeBeatEffects(effect);
 
363
                }
 
364
                
 
365
                if ((flags & 0x10) != 0) {
 
366
                        writeMixChange(measure.getTempo());
 
367
                        tempo.setValue(measure.getTempo().getValue());
 
368
                }
 
369
                int stringFlags = 0;
 
370
                if (!beat.isRestBeat()) {
 
371
                        for (int i = 0; i < beat.countNotes(); i++) {
 
372
                                TGNote playedNote = beat.getNote(i);
 
373
                                int string = (7 - playedNote.getString());
 
374
                                stringFlags |= (1 << string);
 
375
                        }
 
376
                }
 
377
                writeUnsignedByte(stringFlags);
 
378
                for (int i = 6; i >= 0; i--) {
 
379
                        if ((stringFlags & (1 << i)) != 0 ) {
 
380
                                for( int n = 0; n < beat.countNotes(); n ++){
 
381
                                        TGNote playedNote = beat.getNote( n );
 
382
                                        if( playedNote.getString() == (6 - i + 1) ){
 
383
                                                writeNote(playedNote);
 
384
                                                break;
 
385
                                        }
 
386
                                }
 
387
                        }
 
388
                }
 
389
                
 
390
                skipBytes(2);
 
391
        }
 
392
        
 
393
        private void writeNote(TGNote note) throws IOException {
 
394
                //int flags = 0x20;
 
395
                int flags = ( 0x20 | 0x10 );
 
396
                
 
397
                if (note.getEffect().isVibrato()  ||
 
398
                    note.getEffect().isBend()     ||
 
399
                    note.getEffect().isSlide()    ||
 
400
                    note.getEffect().isHammer()   ||
 
401
                    note.getEffect().isPalmMute() ||
 
402
                    note.getEffect().isStaccato() ||
 
403
                    note.getEffect().isTrill()    ||
 
404
                    note.getEffect().isGrace()    ||
 
405
                    note.getEffect().isHarmonic() ||
 
406
                    note.getEffect().isTremoloPicking()) {
 
407
                    flags |= 0x08;
 
408
                }
 
409
                if( note.getEffect().isGhostNote() ){
 
410
                        flags |= 0x04;
 
411
                }
 
412
                if( note.getEffect().isHeavyAccentuatedNote() ){
 
413
                        flags |= 0x02;
 
414
                }
 
415
                if( note.getEffect().isAccentuatedNote() ){
 
416
                        flags |= 0x40;
 
417
                }
 
418
                writeUnsignedByte(flags);
 
419
                
 
420
                if ((flags & 0x20) != 0) {
 
421
                        int typeHeader = 0x01;
 
422
                        if (note.isTiedNote()) {
 
423
                                typeHeader = 0x02;
 
424
                        }else if(note.getEffect().isDeadNote()){
 
425
                                typeHeader = 0x03;
 
426
                        }
 
427
                        writeUnsignedByte(typeHeader);
 
428
                }
 
429
                if ((flags & 0x10) != 0) {
 
430
                        writeByte((byte)(((note.getVelocity() - TGVelocities.MIN_VELOCITY) / TGVelocities.VELOCITY_INCREMENT) + 1));
 
431
                }
 
432
                if ((flags & 0x20) != 0) {
 
433
                        writeByte((byte) note.getValue());
 
434
                }
 
435
                skipBytes(1);
 
436
                if ((flags & 0x08) != 0) {
 
437
                        writeNoteEffects(note.getEffect());
 
438
                }
 
439
        }
 
440
        
 
441
        private byte parseDuration(TGDuration duration) {
 
442
                byte value = 0;
 
443
                switch (duration.getValue()) {
 
444
                case TGDuration.WHOLE:
 
445
                        value = -2;
 
446
                        break;
 
447
                case TGDuration.HALF:
 
448
                        value = -1;
 
449
                        break;
 
450
                case TGDuration.QUARTER:
 
451
                        value = 0;
 
452
                        break;
 
453
                case TGDuration.EIGHTH:
 
454
                        value = 1;
 
455
                        break;
 
456
                case TGDuration.SIXTEENTH:
 
457
                        value = 2;
 
458
                        break;
 
459
                case TGDuration.THIRTY_SECOND:
 
460
                        value = 3;
 
461
                        break;
 
462
                case TGDuration.SIXTY_FOURTH:
 
463
                        value = 4;
 
464
                        break;
 
465
                }
 
466
                return value;
 
467
        }
 
468
        
 
469
        private void writeChord(TGChord chord) throws IOException{
 
470
                this.writeBytes( new byte[] {1,1,0,0,0,12,0,0,-1,-1,-1,-1,0,0,0,0,0} );
 
471
                writeStringByte( chord.getName(), 21);
 
472
                skipBytes(4);
 
473
                writeInt( chord.getFirstFret() );
 
474
                for (int i = 0; i < 7; i++) {
 
475
                        writeInt( (i < chord.countStrings() ? chord.getFretValue(i) : -1 ) ) ;
 
476
                }
 
477
                this.skipBytes(32);
 
478
        }
 
479
        
 
480
        private void writeBeatEffects(TGNoteEffect effect) throws IOException{
 
481
                int flags1 = 0;
 
482
                int flags2 = 0;
 
483
                
 
484
                if(effect.isFadeIn()){
 
485
                        flags1 |= 0x10;
 
486
                }
 
487
                if(effect.isTapping() || effect.isSlapping() || effect.isPopping()){
 
488
                        flags1 |= 0x20;
 
489
                }
 
490
                if(effect.isTremoloBar()){
 
491
                        flags2 |= 0x04;
 
492
                }
 
493
                writeUnsignedByte(flags1);
 
494
                writeUnsignedByte(flags2);
 
495
                
 
496
                if ((flags1 & 0x20) != 0) {
 
497
                        if(effect.isTapping()){
 
498
                                writeUnsignedByte(1);
 
499
                        }else if(effect.isSlapping()){
 
500
                                writeUnsignedByte(2);
 
501
                        }else if(effect.isPopping()){
 
502
                                writeUnsignedByte(3);
 
503
                        }
 
504
                }
 
505
                if ((flags2 & 0x04) != 0) {
 
506
                        writeTremoloBar(effect.getTremoloBar());
 
507
                }
 
508
        }
 
509
        
 
510
        private void writeNoteEffects(TGNoteEffect effect) throws IOException {
 
511
                int flags1 = 0;
 
512
                int flags2 = 0;
 
513
                if (effect.isBend()) {
 
514
                        flags1 |= 0x01;
 
515
                }
 
516
                if (effect.isHammer()) {
 
517
                        flags1 |= 0x02;
 
518
                }
 
519
                if (effect.isGrace()) {
 
520
                        flags1 |= 0x10;
 
521
                }
 
522
                if (effect.isStaccato()) {
 
523
                        flags2 |= 0x01;
 
524
                }
 
525
                if (effect.isPalmMute()) {
 
526
                        flags2 |= 0x02;
 
527
                }
 
528
                if (effect.isTremoloPicking()) {
 
529
                        flags2 |= 0x04;
 
530
                }
 
531
                if (effect.isSlide()) {
 
532
                        flags2 |= 0x08;
 
533
                }
 
534
                if (effect.isHarmonic()) {
 
535
                        flags2 |= 0x10;
 
536
                }
 
537
                if (effect.isTrill()) {
 
538
                        flags2 |= 0x20;
 
539
                }
 
540
                if (effect.isVibrato()) {
 
541
                        flags2 |= 0x40;
 
542
                }
 
543
                writeUnsignedByte(flags1);
 
544
                writeUnsignedByte(flags2);
 
545
                if ((flags1 & 0x01) != 0) {
 
546
                        writeBend(effect.getBend());
 
547
                }
 
548
                
 
549
                if ((flags1 & 0x10) != 0) {
 
550
                        writeGrace(effect.getGrace());
 
551
                }
 
552
                
 
553
                if ((flags2 & 0x04) != 0) {
 
554
                        writeTremoloPicking(effect.getTremoloPicking());
 
555
                }
 
556
                
 
557
                if ((flags2 & 0x08) != 0) {
 
558
                        writeByte((byte)1);
 
559
                }
 
560
                
 
561
                if ((flags2 & 0x10) != 0) {
 
562
                        writeByte((byte)1);
 
563
                }
 
564
                
 
565
                if ((flags2 & 0x20) != 0) {
 
566
                        writeTrill(effect.getTrill());
 
567
                }
 
568
                
 
569
        }
 
570
        
 
571
        private void writeBend(TGEffectBend bend) throws IOException {
 
572
                int points = bend.getPoints().size();
 
573
                writeByte((byte) 1);
 
574
                writeInt(0);
 
575
                writeInt(points);
 
576
                for (int i = 0; i < points; i++) {
 
577
                        TGEffectBend.BendPoint point = (TGEffectBend.BendPoint) bend.getPoints().get(i);
 
578
                        writeInt( (point.getPosition() * GP_BEND_POSITION / TGEffectBend.MAX_POSITION_LENGTH) );
 
579
                        writeInt( (point.getValue() * GP_BEND_SEMITONE / TGEffectBend.SEMITONE_LENGTH) );
 
580
                        writeByte((byte) 0);
 
581
                }
 
582
        }
 
583
        
 
584
        private void writeTremoloBar(TGEffectTremoloBar tremoloBar) throws IOException {
 
585
                int points = tremoloBar.getPoints().size();
 
586
                writeByte((byte) 1);
 
587
                writeInt(0);
 
588
                writeInt(points);
 
589
                for (int i = 0; i < points; i++) {
 
590
                        TGEffectTremoloBar.TremoloBarPoint point = (TGEffectTremoloBar.TremoloBarPoint) tremoloBar.getPoints().get(i);
 
591
                        writeInt( (point.getPosition() * GP_BEND_POSITION / TGEffectBend.MAX_POSITION_LENGTH) );
 
592
                        writeInt( (point.getValue() * (GP_BEND_SEMITONE * 2)) );
 
593
                        writeByte((byte) 0);
 
594
                }
 
595
        }
 
596
        
 
597
        private void writeGrace(TGEffectGrace grace) throws IOException {
 
598
                writeUnsignedByte(grace.getFret());
 
599
                writeUnsignedByte(((grace.getDynamic() - TGVelocities.MIN_VELOCITY) / TGVelocities.VELOCITY_INCREMENT) + 1);
 
600
                if(grace.getTransition() == TGEffectGrace.TRANSITION_NONE){
 
601
                        writeUnsignedByte(0);
 
602
                }
 
603
                else if(grace.getTransition() == TGEffectGrace.TRANSITION_SLIDE){
 
604
                        writeUnsignedByte(1);
 
605
                }
 
606
                else if(grace.getTransition() == TGEffectGrace.TRANSITION_BEND){
 
607
                        writeUnsignedByte(2);
 
608
                }
 
609
                else if(grace.getTransition() == TGEffectGrace.TRANSITION_HAMMER){
 
610
                        writeUnsignedByte(3);
 
611
                }
 
612
                writeUnsignedByte(grace.getDuration());
 
613
                writeUnsignedByte( (grace.isDead() ? 0x01 : 0) | (grace.isOnBeat() ? 0x02 : 0) );
 
614
        }
 
615
        
 
616
        private void writeTrill(TGEffectTrill trill) throws IOException {
 
617
                writeByte((byte)trill.getFret());
 
618
                if(trill.getDuration().getValue() == TGDuration.SIXTEENTH){
 
619
                        writeByte((byte)1);
 
620
                }else if(trill.getDuration().getValue() == TGDuration.THIRTY_SECOND){
 
621
                        writeByte((byte)2);
 
622
                }else if(trill.getDuration().getValue() == TGDuration.SIXTY_FOURTH){
 
623
                        writeByte((byte)3);
 
624
                }
 
625
        }
 
626
        
 
627
        private void writeTremoloPicking(TGEffectTremoloPicking tremoloPicking) throws IOException{
 
628
                if(tremoloPicking.getDuration().getValue() == TGDuration.EIGHTH){
 
629
                        writeByte((byte)1);
 
630
                }else if(tremoloPicking.getDuration().getValue() == TGDuration.SIXTEENTH){
 
631
                        writeByte((byte)2);
 
632
                }else if(tremoloPicking.getDuration().getValue() == TGDuration.THIRTY_SECOND){
 
633
                        writeByte((byte)3);
 
634
                }
 
635
        }
 
636
        
 
637
        private void writeText(TGText text) throws IOException {
 
638
                writeStringByteSizeOfInteger(text.getValue());
 
639
        }
 
640
        
 
641
        private void writeMixChange(TGTempo tempo) throws IOException {
 
642
                writeByte((byte) 0xff);
 
643
                for(int i = 0; i < 16; i++){
 
644
                        writeByte((byte) 0xff);
 
645
                }
 
646
                writeByte((byte) 0xff); //volume
 
647
                writeByte((byte) 0xff); //int pan
 
648
                writeByte((byte) 0xff); //int chorus
 
649
                writeByte((byte) 0xff); //int reverb
 
650
                writeByte((byte) 0xff); //int phaser
 
651
                writeByte((byte) 0xff); //int tremolo
 
652
                writeStringByteSizeOfInteger(""); //tempo name
 
653
                writeInt((tempo != null)?tempo.getValue():-1); //tempo value
 
654
                if((tempo != null)){
 
655
                        skipBytes(1);
 
656
                }
 
657
                writeByte((byte)1);
 
658
                writeByte((byte)0xff);
 
659
        }
 
660
        
 
661
        private void writeMarker(TGMarker marker) throws IOException {
 
662
                writeStringByteSizeOfInteger(marker.getTitle());
 
663
                writeColor(marker.getColor());
 
664
        }
 
665
        
 
666
        private void writeColor(TGColor color) throws IOException {
 
667
                writeUnsignedByte(color.getR());
 
668
                writeUnsignedByte(color.getG());
 
669
                writeUnsignedByte(color.getB());
 
670
                writeByte((byte)0);
 
671
        }
 
672
        
 
673
        private TGChannel[] makeChannels(TGSong song) {
 
674
                TGChannel[] channels = new TGChannel[64];
 
675
                for (int i = 0; i < channels.length; i++) {
 
676
                        channels[i] = getFactory().newChannel();
 
677
                        channels[i].setChannel((short)i);
 
678
                        channels[i].setEffectChannel((short)i);
 
679
                        channels[i].setInstrument((short)24);
 
680
                        channels[i].setVolume((short)13);
 
681
                        channels[i].setBalance((short)8);
 
682
                        channels[i].setChorus((short)0);
 
683
                        channels[i].setReverb((short)0);
 
684
                        channels[i].setPhaser((short)0);
 
685
                        channels[i].setTremolo((short)0);
 
686
                        channels[i].setSolo(false);
 
687
                        channels[i].setMute(false);
 
688
                }
 
689
                
 
690
                Iterator it = song.getTracks();
 
691
                while (it.hasNext()) {
 
692
                        TGTrack track = (TGTrack) it.next();
 
693
                        channels[track.getChannel().getChannel()].setInstrument(track.getChannel().getInstrument());
 
694
                        channels[track.getChannel().getChannel()].setVolume(track.getChannel().getVolume());
 
695
                        channels[track.getChannel().getChannel()].setBalance(track.getChannel().getBalance());
 
696
                        channels[track.getChannel().getEffectChannel()].setInstrument(track.getChannel().getInstrument());
 
697
                        channels[track.getChannel().getEffectChannel()].setVolume(track.getChannel().getVolume());
 
698
                        channels[track.getChannel().getEffectChannel()].setBalance(track.getChannel().getBalance());
 
699
                }
 
700
                
 
701
                return channels;
 
702
        }
 
703
        
 
704
        private byte toChannelByte(short s){
 
705
                return  (byte) ((s + 1) / 8);
 
706
        }
 
707
}
 
 
b'\\ No newline at end of file'