2
* Created on 09-ene-2006
4
* TODO To change the template for this generated file go to
5
* Window - Preferences - Java - Code Style - Code Templates
7
package org.herac.tuxguitar.io.gtp;
9
import java.io.IOException;
10
import java.util.Iterator;
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;
41
* TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
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;
49
private static final String[] PAGE_SETUP_LINES = {
56
"Words & Music by %WORDSMUSIC%",
57
"Copyright %COPYRIGHT%",
58
"All Rights Reserved - International Copyright Secured",
63
public GP5OutputStream() {
67
public TGFileFormat getFileFormat(){
68
return new TGFileFormat("Guitar Pro 5","*.gp5");
71
public boolean isSupportedExtension(String extension) {
72
return (extension.toLowerCase().equals(GP5_FORMAT_EXTENSION)) ;
75
public void writeSong(TGSong song){
78
throw new TGFileFormatException("Empty Song!!!");
80
TGMeasureHeader header = song.getMeasureHeader(0);
81
writeStringByte(GP5_VERSION, 30);
85
writeInt(header.getTempo().getValue());
89
for(int i = 0; i < 42; i ++){
90
writeByte((byte)0xff);
92
writeInt(song.countMeasureHeaders());
93
writeInt(song.countTracks());
94
writeMeasureHeaders(song);
97
writeMeasures(song, header.getTempo().clone(getFactory()));
99
} catch (Exception e) {
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("");
117
private void writeLyrics(TGSong song) throws IOException{
118
TGTrack lyricTrack = null;
119
Iterator it = song.getTracks();
121
TGTrack track = (TGTrack)it.next();
122
if(!track.getLyrics().isEmpty()){
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++) {
132
writeStringInteger("");
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
145
writeByte( ( byte )0xff ); // View flags
146
writeByte( ( byte )0x01 ); // View flags
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);
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});
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++) {
175
TGMeasureHeader measure = song.getMeasureHeader(i);
176
writeMeasureHeader(measure, timeSignature);
178
timeSignature.setNumerator(measure.getTimeSignature().getNumerator());
179
timeSignature.getDenominator().setValue(measure.getTimeSignature().getDenominator().getValue());
184
private void writeMeasureHeader(TGMeasureHeader measure, TGTimeSignature timeSignature) throws IOException {
186
if(measure.getNumber() == 1){
189
if (measure.getNumber() == 1 || measure.getTimeSignature().getNumerator() != timeSignature.getNumerator()) {
192
if (measure.getNumber() == 1 || measure.getTimeSignature().getDenominator().getValue() != timeSignature.getDenominator().getValue()) {
195
if (measure.isRepeatOpen()) {
198
if (measure.getRepeatClose() > 0) {
201
if (measure.getRepeatAlternative() > 0) {
204
if (measure.hasMarker()) {
207
writeUnsignedByte(flags);
209
if ((flags & 0x01) != 0) {
210
writeByte((byte) measure.getTimeSignature().getNumerator());
212
if ((flags & 0x02) != 0) {
213
writeByte((byte) measure.getTimeSignature().getDenominator().getValue());
215
if ((flags & 0x08) != 0) {
216
writeByte((byte) (measure.getRepeatClose() + 1));
218
if ((flags & 0x20) != 0) {
219
writeMarker(measure.getMarker());
221
if ((flags & 0x10) != 0) {
222
writeByte((byte)measure.getRepeatAlternative());
224
if ((flags & 0x40) != 0) {
227
if((flags & 0x10) == 0){
230
if ((flags & 0x01) != 0) {
233
if(measure.getTripletFeel() == TGMeasureHeader.TRIPLET_FEEL_NONE){
236
else if(measure.getTripletFeel() == TGMeasureHeader.TRIPLET_FEEL_EIGHTH){
239
else if(measure.getTripletFeel() == TGMeasureHeader.TRIPLET_FEEL_SIXTEENTH){
244
private void writeTracks(TGSong song) throws IOException {
245
for (int i = 0; i < song.countTracks(); i++) {
246
TGTrack track = song.getTrack(i);
251
private void writeTrack(TGTrack track) throws IOException {
253
if (track.isPercussionTrack()) {
256
writeUnsignedByte(flags);
258
writeStringByte(track.getName(), 40);
259
writeInt(track.getStrings().size());
260
for (int i = 0; i < 7; i++) {
262
if (track.getStrings().size() > i) {
263
TGString string = (TGString) track.getStrings().get(i);
264
value = string.getValue();
269
writeInt(track.getChannel().getChannel() + 1);
270
writeInt(track.getChannel().getEffectChannel() + 1);
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});
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);
288
private void writeMeasure(TGMeasure measure, TGTempo tempo) throws IOException {
289
int beatCount = measure.countBeats();
291
for (int i = 0; i < beatCount; i++) {
292
TGBeat beat = measure.getBeat( i );
293
writeBeat(beat, measure, tempo);
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);
304
if(playedNote.getEffect().isFadeIn()){
305
effect.setFadeIn(true);
307
if(playedNote.getEffect().isTremoloBar()){
308
effect.setTremoloBar(playedNote.getEffect().getTremoloBar().clone(getFactory()));
310
if(playedNote.getEffect().isTapping()){
311
effect.setTapping(true);
313
if(playedNote.getEffect().isSlapping()){
314
effect.setSlapping(true);
316
if(playedNote.getEffect().isPopping()){
317
effect.setPopping(true);
322
if (duration.isDotted() || duration.isDoubleDotted()) {
325
if (beat.isChordBeat()) {
328
if (beat.isTextBeat()) {
331
if (effect.isTremoloBar() || effect.isTapping() || effect.isSlapping() || effect.isPopping() || effect.isFadeIn()) {
334
if (measure.getTempo().getValue() != tempo.getValue()) {
337
if (!duration.getTupleto().isEqual(TGTupleto.NORMAL)) {
340
if (beat.isRestBeat()) {
343
writeUnsignedByte(flags);
345
if ((flags & 0x40) != 0) {
346
writeUnsignedByte(0x02);
348
writeByte(parseDuration(duration));
349
if ((flags & 0x20) != 0) {
350
writeInt(duration.getTupleto().getEnters());
353
if ((flags & 0x02) != 0) {
354
writeChord(beat.getChord());
357
if ((flags & 0x04) != 0) {
358
writeText(beat.getText());
361
if ((flags & 0x08) != 0) {
362
writeBeatEffects(effect);
365
if ((flags & 0x10) != 0) {
366
writeMixChange(measure.getTempo());
367
tempo.setValue(measure.getTempo().getValue());
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);
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);
393
private void writeNote(TGNote note) throws IOException {
395
int flags = ( 0x20 | 0x10 );
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()) {
409
if( note.getEffect().isGhostNote() ){
412
if( note.getEffect().isHeavyAccentuatedNote() ){
415
if( note.getEffect().isAccentuatedNote() ){
418
writeUnsignedByte(flags);
420
if ((flags & 0x20) != 0) {
421
int typeHeader = 0x01;
422
if (note.isTiedNote()) {
424
}else if(note.getEffect().isDeadNote()){
427
writeUnsignedByte(typeHeader);
429
if ((flags & 0x10) != 0) {
430
writeByte((byte)(((note.getVelocity() - TGVelocities.MIN_VELOCITY) / TGVelocities.VELOCITY_INCREMENT) + 1));
432
if ((flags & 0x20) != 0) {
433
writeByte((byte) note.getValue());
436
if ((flags & 0x08) != 0) {
437
writeNoteEffects(note.getEffect());
441
private byte parseDuration(TGDuration duration) {
443
switch (duration.getValue()) {
444
case TGDuration.WHOLE:
447
case TGDuration.HALF:
450
case TGDuration.QUARTER:
453
case TGDuration.EIGHTH:
456
case TGDuration.SIXTEENTH:
459
case TGDuration.THIRTY_SECOND:
462
case TGDuration.SIXTY_FOURTH:
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);
473
writeInt( chord.getFirstFret() );
474
for (int i = 0; i < 7; i++) {
475
writeInt( (i < chord.countStrings() ? chord.getFretValue(i) : -1 ) ) ;
480
private void writeBeatEffects(TGNoteEffect effect) throws IOException{
484
if(effect.isFadeIn()){
487
if(effect.isTapping() || effect.isSlapping() || effect.isPopping()){
490
if(effect.isTremoloBar()){
493
writeUnsignedByte(flags1);
494
writeUnsignedByte(flags2);
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);
505
if ((flags2 & 0x04) != 0) {
506
writeTremoloBar(effect.getTremoloBar());
510
private void writeNoteEffects(TGNoteEffect effect) throws IOException {
513
if (effect.isBend()) {
516
if (effect.isHammer()) {
519
if (effect.isGrace()) {
522
if (effect.isStaccato()) {
525
if (effect.isPalmMute()) {
528
if (effect.isTremoloPicking()) {
531
if (effect.isSlide()) {
534
if (effect.isHarmonic()) {
537
if (effect.isTrill()) {
540
if (effect.isVibrato()) {
543
writeUnsignedByte(flags1);
544
writeUnsignedByte(flags2);
545
if ((flags1 & 0x01) != 0) {
546
writeBend(effect.getBend());
549
if ((flags1 & 0x10) != 0) {
550
writeGrace(effect.getGrace());
553
if ((flags2 & 0x04) != 0) {
554
writeTremoloPicking(effect.getTremoloPicking());
557
if ((flags2 & 0x08) != 0) {
561
if ((flags2 & 0x10) != 0) {
565
if ((flags2 & 0x20) != 0) {
566
writeTrill(effect.getTrill());
571
private void writeBend(TGEffectBend bend) throws IOException {
572
int points = bend.getPoints().size();
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) );
584
private void writeTremoloBar(TGEffectTremoloBar tremoloBar) throws IOException {
585
int points = tremoloBar.getPoints().size();
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)) );
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);
603
else if(grace.getTransition() == TGEffectGrace.TRANSITION_SLIDE){
604
writeUnsignedByte(1);
606
else if(grace.getTransition() == TGEffectGrace.TRANSITION_BEND){
607
writeUnsignedByte(2);
609
else if(grace.getTransition() == TGEffectGrace.TRANSITION_HAMMER){
610
writeUnsignedByte(3);
612
writeUnsignedByte(grace.getDuration());
613
writeUnsignedByte( (grace.isDead() ? 0x01 : 0) | (grace.isOnBeat() ? 0x02 : 0) );
616
private void writeTrill(TGEffectTrill trill) throws IOException {
617
writeByte((byte)trill.getFret());
618
if(trill.getDuration().getValue() == TGDuration.SIXTEENTH){
620
}else if(trill.getDuration().getValue() == TGDuration.THIRTY_SECOND){
622
}else if(trill.getDuration().getValue() == TGDuration.SIXTY_FOURTH){
627
private void writeTremoloPicking(TGEffectTremoloPicking tremoloPicking) throws IOException{
628
if(tremoloPicking.getDuration().getValue() == TGDuration.EIGHTH){
630
}else if(tremoloPicking.getDuration().getValue() == TGDuration.SIXTEENTH){
632
}else if(tremoloPicking.getDuration().getValue() == TGDuration.THIRTY_SECOND){
637
private void writeText(TGText text) throws IOException {
638
writeStringByteSizeOfInteger(text.getValue());
641
private void writeMixChange(TGTempo tempo) throws IOException {
642
writeByte((byte) 0xff);
643
for(int i = 0; i < 16; i++){
644
writeByte((byte) 0xff);
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
658
writeByte((byte)0xff);
661
private void writeMarker(TGMarker marker) throws IOException {
662
writeStringByteSizeOfInteger(marker.getTitle());
663
writeColor(marker.getColor());
666
private void writeColor(TGColor color) throws IOException {
667
writeUnsignedByte(color.getR());
668
writeUnsignedByte(color.getG());
669
writeUnsignedByte(color.getB());
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);
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());
704
private byte toChannelByte(short s){
705
return (byte) ((s + 1) / 8);
b'\\ No newline at end of file'