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

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Philippe Coval
  • Date: 2008-06-19 00:30:30 UTC
  • mfrom: (1.1.1 upstream) (2.1.3 hardy)
  • Revision ID: james.westby@ubuntu.com-20080619003030-agens2gvd5m4dacu
New upstream release (Closes: #481728) also (LP: #176979, #212207)

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.TGColor;
 
17
import org.herac.tuxguitar.song.models.TGDuration;
 
18
import org.herac.tuxguitar.song.models.TGMarker;
 
19
import org.herac.tuxguitar.song.models.TGMeasure;
 
20
import org.herac.tuxguitar.song.models.TGMeasureHeader;
 
21
import org.herac.tuxguitar.song.models.TGNote;
 
22
import org.herac.tuxguitar.song.models.TGNoteEffect;
 
23
import org.herac.tuxguitar.song.models.TGSong;
 
24
import org.herac.tuxguitar.song.models.TGString;
 
25
import org.herac.tuxguitar.song.models.TGTempo;
 
26
import org.herac.tuxguitar.song.models.TGText;
 
27
import org.herac.tuxguitar.song.models.TGTimeSignature;
 
28
import org.herac.tuxguitar.song.models.TGTrack;
 
29
import org.herac.tuxguitar.song.models.TGTupleto;
 
30
import org.herac.tuxguitar.song.models.TGVelocities;
 
31
import org.herac.tuxguitar.song.models.effects.TGEffectBend;
 
32
import org.herac.tuxguitar.song.models.effects.TGEffectGrace;
 
33
import org.herac.tuxguitar.song.models.effects.TGEffectHarmonic;
 
34
 
 
35
/**
 
36
 * @author julian
 
37
 * 
 
38
 * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
 
39
 */
 
40
public class GP3OutputStream extends GTPOutputStream{
 
41
        private static final String GP3_FORMAT_EXTENSION = ".gp3";
 
42
        private static final String GP3_VERSION = "FICHIER GUITAR PRO v3.00";
 
43
        private static final int GP_BEND_SEMITONE = 25;
 
44
        private static final int GP_BEND_POSITION = 60;
 
45
        
 
46
        public GP3OutputStream(){
 
47
                super();
 
48
        }
 
49
        
 
50
        public TGFileFormat getFileFormat(){
 
51
                return new TGFileFormat("Guitar Pro 3",("*" + GP3_FORMAT_EXTENSION));
 
52
        }
 
53
        
 
54
        public boolean isSupportedExtension(String extension) {
 
55
                return (extension.toLowerCase().equals(GP3_FORMAT_EXTENSION)) ;
 
56
        }
 
57
        
 
58
        public void writeSong(TGSong song){
 
59
                try {
 
60
                        if(song.isEmpty()){
 
61
                                throw new TGFileFormatException("Empty Song!!!");
 
62
                        }
 
63
                        TGMeasureHeader header = song.getMeasureHeader(0);
 
64
                        writeStringByte(GP3_VERSION, 30);
 
65
                        writeInfo(song);
 
66
                        writeBoolean( (header.getTripletFeel() == TGMeasureHeader.TRIPLET_FEEL_EIGHTH) );
 
67
                        writeInt(header.getTempo().getValue());
 
68
                        writeInt(0);
 
69
                        writeChannels(song);
 
70
                        writeInt(song.countMeasureHeaders());
 
71
                        writeInt(song.countTracks());
 
72
                        writeMeasureHeaders(song);
 
73
                        writeTracks(song);
 
74
                        writeMeasures(song,header.getTempo().clone(getFactory()));
 
75
                        close();
 
76
                } catch (Exception e) {
 
77
                        e.printStackTrace();
 
78
                }
 
79
        }
 
80
        
 
81
        private void writeInfo(TGSong song) throws IOException{
 
82
                writeStringByteSizeOfInteger(song.getName());
 
83
                writeStringByteSizeOfInteger("");
 
84
                writeStringByteSizeOfInteger(song.getArtist());
 
85
                writeStringByteSizeOfInteger(song.getAlbum());
 
86
                writeStringByteSizeOfInteger(song.getAuthor());
 
87
                writeStringByteSizeOfInteger("");
 
88
                writeStringByteSizeOfInteger("");
 
89
                writeStringByteSizeOfInteger("");
 
90
                writeInt(0);
 
91
        }
 
92
        
 
93
        private void writeChannels(TGSong song) throws IOException{
 
94
                TGChannel[] channels = makeChannels(song);
 
95
                for (int i = 0; i < channels.length; i++) {
 
96
                        writeInt(channels[i].getInstrument());
 
97
                        writeByte(toChannelByte(channels[i].getVolume()));
 
98
                        writeByte(toChannelByte(channels[i].getBalance()));
 
99
                        writeByte(toChannelByte(channels[i].getChorus()));
 
100
                        writeByte(toChannelByte(channels[i].getReverb()));
 
101
                        writeByte(toChannelByte(channels[i].getPhaser()));
 
102
                        writeByte(toChannelByte(channels[i].getTremolo()));
 
103
                        writeBytes(new byte[]{0,0});
 
104
                }
 
105
        }
 
106
        
 
107
        private void writeMeasureHeaders(TGSong song) throws IOException {
 
108
                TGTimeSignature timeSignature = getFactory().newTimeSignature();
 
109
                if (song.countMeasureHeaders() > 0) {
 
110
                        for (int i = 0; i < song.countMeasureHeaders(); i++) {
 
111
                                TGMeasureHeader measure = song.getMeasureHeader(i);
 
112
                                writeMeasureHeader(measure, timeSignature);
 
113
                                timeSignature.setNumerator(measure.getTimeSignature().getNumerator());
 
114
                                timeSignature.getDenominator().setValue(measure.getTimeSignature().getDenominator().getValue());
 
115
                        }
 
116
                }
 
117
        }
 
118
        
 
119
        private void writeMeasures(TGSong song,TGTempo tempo) throws IOException{
 
120
                for (int i = 0; i < song.countMeasureHeaders(); i++) {
 
121
                        for (int j = 0; j < song.countTracks(); j++) {
 
122
                                TGTrack track = song.getTrack(j);
 
123
                                TGMeasure measure = track.getMeasure(i);
 
124
                                writeMeasure(measure, tempo);
 
125
                        }
 
126
                }
 
127
        }
 
128
        
 
129
        private void writeMeasureHeader(TGMeasureHeader measure, TGTimeSignature timeSignature) throws IOException {
 
130
                int flags = 0;
 
131
                if (measure.getNumber() == 1 || measure.getTimeSignature().getNumerator() != timeSignature.getNumerator()) {
 
132
                        flags |= 0x01;
 
133
                }
 
134
                if (measure.getNumber() == 1 || measure.getTimeSignature().getDenominator().getValue() != timeSignature.getDenominator().getValue()) {
 
135
                        flags |= 0x02;
 
136
                }
 
137
                if (measure.isRepeatOpen()) {
 
138
                        flags |= 0x04;
 
139
                }
 
140
                if (measure.getRepeatClose() > 0) {
 
141
                        flags |= 0x08;
 
142
                }
 
143
                if (measure.hasMarker()) {
 
144
                        flags |= 0x20;
 
145
                }
 
146
                writeUnsignedByte(flags);
 
147
                
 
148
                if ((flags & 0x01) != 0) {
 
149
                        writeByte((byte) measure.getTimeSignature().getNumerator());
 
150
                }
 
151
                if ((flags & 0x02) != 0) {
 
152
                        writeByte((byte) measure.getTimeSignature().getDenominator().getValue());
 
153
                }
 
154
                if ((flags & 0x08) != 0) {
 
155
                        writeByte((byte) measure.getRepeatClose());
 
156
                }
 
157
                if ((flags & 0x20) != 0) {
 
158
                        writeMarker(measure.getMarker());
 
159
                }
 
160
        }
 
161
        
 
162
        private void writeTracks(TGSong song) throws IOException {
 
163
                for (int i = 0; i < song.countTracks(); i++) {
 
164
                        TGTrack track = song.getTrack(i);
 
165
                        createTrack(track);
 
166
                }
 
167
        }
 
168
        
 
169
        private void createTrack(TGTrack track) throws IOException {
 
170
                int flags = 0;
 
171
                if (track.isPercussionTrack()) {
 
172
                        flags |= 0x01;
 
173
                }
 
174
                writeUnsignedByte(flags);
 
175
                
 
176
                writeStringByte(track.getName(), 40);
 
177
                writeInt(track.getStrings().size());
 
178
                for (int i = 0; i < 7; i++) {
 
179
                        int value = 0;
 
180
                        if (track.getStrings().size() > i) {
 
181
                                TGString string = (TGString) track.getStrings().get(i);
 
182
                                value = string.getValue();
 
183
                        }
 
184
                        writeInt(value);
 
185
                }
 
186
                writeInt(1);
 
187
                writeInt(track.getChannel().getChannel() + 1);
 
188
                writeInt(track.getChannel().getEffectChannel() + 1);
 
189
                writeInt(24);
 
190
                writeInt(Math.min(Math.max(track.getOffset(),0),12));
 
191
                writeColor(track.getColor());
 
192
        }
 
193
        
 
194
        private void writeMeasure(TGMeasure measure, TGTempo tempo) throws IOException {
 
195
                int beatCount = measure.countBeats();
 
196
                writeInt(beatCount);
 
197
                for (int i = 0; i < beatCount; i++) {
 
198
                        TGBeat beat = measure.getBeat( i );
 
199
                        writeBeat(beat, measure, tempo);
 
200
                }
 
201
        }
 
202
        
 
203
        private void writeBeat(TGBeat beat,TGMeasure measure, TGTempo songTempo) throws IOException {
 
204
                TGDuration duration = beat.getDuration();
 
205
                int flags = 0;
 
206
                if (duration.isDotted() || duration.isDoubleDotted() ) {
 
207
                        flags |= 0x01;
 
208
                }
 
209
                if (!duration.getTupleto().isEqual(TGTupleto.NORMAL)) {
 
210
                        flags |= 0x20;
 
211
                }
 
212
                if(beat.isTextBeat()){
 
213
                        flags |= 0x04;
 
214
                }
 
215
                if (measure.getTempo().getValue() != songTempo.getValue()) {
 
216
                        flags |= 0x10;
 
217
                }
 
218
                TGNoteEffect effect = null;
 
219
                if (beat.isRestBeat()) {
 
220
                        flags |= 0x40;
 
221
                } else if(beat.countNotes() > 0){
 
222
                        TGNote note = beat.getNote(0);
 
223
                        effect = note.getEffect();
 
224
                        if (effect.isVibrato() ||
 
225
                                effect.isTremoloBar() ||
 
226
                                effect.isTapping() ||
 
227
                                effect.isSlapping() ||
 
228
                                effect.isPopping() ||
 
229
                                effect.isHarmonic() ||
 
230
                                effect.isFadeIn()) {
 
231
                                flags |= 0x08;
 
232
                        }
 
233
                }
 
234
                writeUnsignedByte(flags);
 
235
                
 
236
                if ((flags & 0x40) != 0) {
 
237
                        writeUnsignedByte(2);
 
238
                }
 
239
                writeByte(parseDuration(duration));
 
240
                if ((flags & 0x20) != 0) {
 
241
                        writeInt(duration.getTupleto().getEnters());
 
242
                }
 
243
                if ((flags & 0x04) != 0) {
 
244
                        writeText(beat.getText());
 
245
                }
 
246
                if ((flags & 0x08) != 0) {
 
247
                        writeBeatEffects(effect);
 
248
                }
 
249
                if ((flags & 0x10) != 0) {
 
250
                        writeMixChange(measure.getTempo());
 
251
                }
 
252
                int stringFlags = 0;
 
253
                if (!beat.isRestBeat()) {
 
254
                        for (int i = 0; i < beat.countNotes(); i++) {
 
255
                                TGNote playedNote = beat.getNote(i);
 
256
                                int string = (7 - playedNote.getString());
 
257
                                stringFlags |= (1 << string);
 
258
                        }
 
259
                }
 
260
                writeUnsignedByte(stringFlags);
 
261
                for (int i = 6; i >= 0; i--) {
 
262
                        if ((stringFlags & (1 << i)) != 0 ) {
 
263
                                for( int n = 0; n < beat.countNotes(); n ++){
 
264
                                        TGNote playedNote = beat.getNote( n );
 
265
                                        if( playedNote.getString() == (6 - i + 1) ){
 
266
                                                writeNote(playedNote);
 
267
                                                break;
 
268
                                        }
 
269
                                }
 
270
                        }
 
271
                }
 
272
        }
 
273
        
 
274
        private void writeNote(TGNote note) throws IOException {
 
275
                int flags = ( 0x20 | 0x10 );
 
276
                if(note.getEffect().isGhostNote()){
 
277
                        flags |= 0x04;
 
278
                } 
 
279
                if (note.getEffect().isBend() || note.getEffect().isGrace() || note.getEffect().isSlide() || note.getEffect().isHammer()) {
 
280
                        flags |= 0x08;
 
281
                }
 
282
                writeUnsignedByte(flags);
 
283
                if ((flags & 0x20) != 0) {
 
284
                        int typeHeader = 0x01;
 
285
                        if (note.isTiedNote()) {
 
286
                                typeHeader = 0x02;
 
287
                        }else if(note.getEffect().isDeadNote()){
 
288
                                typeHeader = 0x03;
 
289
                        }
 
290
                        writeUnsignedByte(typeHeader);
 
291
                }
 
292
                if ((flags & 0x10) != 0) {
 
293
                        writeByte((byte)(((note.getVelocity() - TGVelocities.MIN_VELOCITY) / TGVelocities.VELOCITY_INCREMENT) + 1));
 
294
                }
 
295
                if ((flags & 0x20) != 0) {
 
296
                        writeByte((byte) note.getValue());
 
297
                }
 
298
                if ((flags & 0x08) != 0) {
 
299
                        writeNoteEffects(note.getEffect());
 
300
                }
 
301
        }
 
302
        
 
303
        private byte parseDuration(TGDuration duration) {
 
304
                byte value = 0;
 
305
                switch (duration.getValue()) {
 
306
                case TGDuration.WHOLE:
 
307
                        value = -2;
 
308
                        break;
 
309
                case TGDuration.HALF:
 
310
                        value = -1;
 
311
                        break;
 
312
                case TGDuration.QUARTER:
 
313
                        value = 0;
 
314
                        break;
 
315
                case TGDuration.EIGHTH:
 
316
                        value = 1;
 
317
                        break;
 
318
                case TGDuration.SIXTEENTH:
 
319
                        value = 2;
 
320
                        break;
 
321
                case TGDuration.THIRTY_SECOND:
 
322
                        value = 3;
 
323
                        break;
 
324
                case TGDuration.SIXTY_FOURTH:
 
325
                        value = 4;
 
326
                        break;
 
327
                }
 
328
                return value;
 
329
        }
 
330
        
 
331
        private void writeText(TGText text) throws IOException {
 
332
                writeStringByteSizeOfInteger(text.getValue());
 
333
        }
 
334
        
 
335
        private void writeBeatEffects(TGNoteEffect noteEffect) throws IOException {
 
336
                int flags = 0;
 
337
                if (noteEffect.isVibrato()) {
 
338
                        flags += 0x01;
 
339
                }
 
340
                if (noteEffect.isTremoloBar() || noteEffect.isTapping() || noteEffect.isSlapping() || noteEffect.isPopping()) {
 
341
                        flags += 0x20;
 
342
                }
 
343
                if (noteEffect.isHarmonic() && noteEffect.getHarmonic().getType() == TGEffectHarmonic.TYPE_NATURAL) {
 
344
                        flags += 0x04;
 
345
                }
 
346
                if (noteEffect.isHarmonic() && noteEffect.getHarmonic().getType() != TGEffectHarmonic.TYPE_NATURAL) {
 
347
                        flags += 0x08;
 
348
                }
 
349
                if (noteEffect.isFadeIn()) {
 
350
                        flags += 0x10;
 
351
                }
 
352
                writeUnsignedByte(flags);
 
353
                
 
354
                if ((flags & 0x20) != 0) {
 
355
                        if (noteEffect.isTremoloBar()){
 
356
                                writeUnsignedByte(0);
 
357
                                writeInt(100);
 
358
                        }
 
359
                        else if (noteEffect.isTapping()){
 
360
                                writeUnsignedByte(1);
 
361
                                writeInt(0);
 
362
                        }
 
363
                        else if (noteEffect.isSlapping()){
 
364
                                writeUnsignedByte(2);
 
365
                                writeInt(0);
 
366
                        }
 
367
                        else if (noteEffect.isPopping()){
 
368
                                writeUnsignedByte(3);
 
369
                                writeInt(0);
 
370
                        }
 
371
                }
 
372
        }
 
373
        
 
374
        private void writeNoteEffects(TGNoteEffect effect) throws IOException {
 
375
                int flags = 0;
 
376
                if (effect.isBend()) {
 
377
                        flags |= 0x01;
 
378
                }
 
379
                if (effect.isHammer()) {
 
380
                        flags |= 0x02;
 
381
                }
 
382
                if (effect.isSlide()) {
 
383
                        flags |= 0x04;
 
384
                }
 
385
                if (effect.isGrace()) {
 
386
                        flags |= 0x10;
 
387
                }
 
388
                writeUnsignedByte(flags);
 
389
                
 
390
                if ((flags & 0x01) != 0) {
 
391
                        writeBend(effect.getBend());
 
392
                }
 
393
                if ((flags & 0x10) != 0) {
 
394
                        writeGrace(effect.getGrace());
 
395
                }
 
396
        }
 
397
        
 
398
        private void writeBend(TGEffectBend bend) throws IOException {
 
399
                int points = bend.getPoints().size();
 
400
                writeByte((byte) 1);
 
401
                writeInt(0);
 
402
                writeInt(points);
 
403
                for (int i = 0; i < points; i++) {
 
404
                        TGEffectBend.BendPoint point = (TGEffectBend.BendPoint) bend.getPoints().get(i);
 
405
                        writeInt( (point.getPosition() * GP_BEND_POSITION / TGEffectBend.MAX_POSITION_LENGTH) );
 
406
                        writeInt( (point.getValue() * GP_BEND_SEMITONE / TGEffectBend.SEMITONE_LENGTH) );
 
407
                        writeByte((byte) 0);
 
408
                }
 
409
        }
 
410
        
 
411
        private void writeGrace(TGEffectGrace grace) throws IOException {
 
412
                if(grace.isDead()){
 
413
                        writeUnsignedByte(0xff);
 
414
                }else{
 
415
                        writeUnsignedByte(grace.getFret());
 
416
                }
 
417
                writeUnsignedByte(((grace.getDynamic() - TGVelocities.MIN_VELOCITY) / TGVelocities.VELOCITY_INCREMENT) + 1);
 
418
                if(grace.getTransition() == TGEffectGrace.TRANSITION_NONE){
 
419
                        writeUnsignedByte(0);
 
420
                }
 
421
                else if(grace.getTransition() == TGEffectGrace.TRANSITION_SLIDE){
 
422
                        writeUnsignedByte(1);
 
423
                }
 
424
                else if(grace.getTransition() == TGEffectGrace.TRANSITION_BEND){
 
425
                        writeUnsignedByte(2);
 
426
                }
 
427
                else if(grace.getTransition() == TGEffectGrace.TRANSITION_HAMMER){
 
428
                        writeUnsignedByte(3);
 
429
                }
 
430
                writeUnsignedByte(grace.getDuration());
 
431
        }
 
432
        
 
433
        private void writeMixChange(TGTempo tempo) throws IOException {
 
434
                for (int i = 0; i < 7; i++) {
 
435
                        writeByte((byte) -1);
 
436
                }
 
437
                writeInt(tempo.getValue());
 
438
                writeByte((byte) 0);
 
439
        }
 
440
        
 
441
        private void writeMarker(TGMarker marker) throws IOException {
 
442
                writeStringByteSizeOfInteger(marker.getTitle());
 
443
                writeColor(marker.getColor());
 
444
        }
 
445
        
 
446
        private void writeColor(TGColor color) throws IOException {
 
447
                writeUnsignedByte(color.getR());
 
448
                writeUnsignedByte(color.getG());
 
449
                writeUnsignedByte(color.getB());
 
450
                writeByte((byte)0);
 
451
        }
 
452
        
 
453
        private TGChannel[] makeChannels(TGSong song) {
 
454
                TGChannel[] channels = new TGChannel[64];
 
455
                for (int i = 0; i < channels.length; i++) {
 
456
                        channels[i] = getFactory().newChannel();
 
457
                        channels[i].setChannel((short)i);
 
458
                        channels[i].setEffectChannel((short)i);
 
459
                        channels[i].setInstrument((short)24);
 
460
                        channels[i].setVolume((short)13);
 
461
                        channels[i].setBalance((short)8);
 
462
                        channels[i].setChorus((short)0);
 
463
                        channels[i].setReverb((short)0);
 
464
                        channels[i].setPhaser((short)0);
 
465
                        channels[i].setTremolo((short)0);
 
466
                        channels[i].setSolo(false);
 
467
                        channels[i].setMute(false);
 
468
                }
 
469
                
 
470
                Iterator it = song.getTracks();
 
471
                while (it.hasNext()) {
 
472
                        TGTrack track = (TGTrack) it.next();
 
473
                        channels[track.getChannel().getChannel()].setInstrument(track.getChannel().getInstrument());
 
474
                        channels[track.getChannel().getChannel()].setVolume(track.getChannel().getVolume());
 
475
                        channels[track.getChannel().getChannel()].setBalance(track.getChannel().getBalance());
 
476
                        channels[track.getChannel().getEffectChannel()].setInstrument(track.getChannel().getInstrument());
 
477
                        channels[track.getChannel().getEffectChannel()].setVolume(track.getChannel().getVolume());
 
478
                        channels[track.getChannel().getEffectChannel()].setBalance(track.getChannel().getBalance());
 
479
                }
 
480
                
 
481
                return channels;
 
482
        }
 
483
        
 
484
        private byte toChannelByte(short s){
 
485
                return  (byte) ((s + 1) / 8);
 
486
        }
 
487
}
 
 
b'\\ No newline at end of file'