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.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;
38
* TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
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;
46
public GP3OutputStream(){
50
public TGFileFormat getFileFormat(){
51
return new TGFileFormat("Guitar Pro 3",("*" + GP3_FORMAT_EXTENSION));
54
public boolean isSupportedExtension(String extension) {
55
return (extension.toLowerCase().equals(GP3_FORMAT_EXTENSION)) ;
58
public void writeSong(TGSong song){
61
throw new TGFileFormatException("Empty Song!!!");
63
TGMeasureHeader header = song.getMeasureHeader(0);
64
writeStringByte(GP3_VERSION, 30);
66
writeBoolean( (header.getTripletFeel() == TGMeasureHeader.TRIPLET_FEEL_EIGHTH) );
67
writeInt(header.getTempo().getValue());
70
writeInt(song.countMeasureHeaders());
71
writeInt(song.countTracks());
72
writeMeasureHeaders(song);
74
writeMeasures(song,header.getTempo().clone(getFactory()));
76
} catch (Exception e) {
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("");
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});
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());
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);
129
private void writeMeasureHeader(TGMeasureHeader measure, TGTimeSignature timeSignature) throws IOException {
131
if (measure.getNumber() == 1 || measure.getTimeSignature().getNumerator() != timeSignature.getNumerator()) {
134
if (measure.getNumber() == 1 || measure.getTimeSignature().getDenominator().getValue() != timeSignature.getDenominator().getValue()) {
137
if (measure.isRepeatOpen()) {
140
if (measure.getRepeatClose() > 0) {
143
if (measure.hasMarker()) {
146
writeUnsignedByte(flags);
148
if ((flags & 0x01) != 0) {
149
writeByte((byte) measure.getTimeSignature().getNumerator());
151
if ((flags & 0x02) != 0) {
152
writeByte((byte) measure.getTimeSignature().getDenominator().getValue());
154
if ((flags & 0x08) != 0) {
155
writeByte((byte) measure.getRepeatClose());
157
if ((flags & 0x20) != 0) {
158
writeMarker(measure.getMarker());
162
private void writeTracks(TGSong song) throws IOException {
163
for (int i = 0; i < song.countTracks(); i++) {
164
TGTrack track = song.getTrack(i);
169
private void createTrack(TGTrack track) throws IOException {
171
if (track.isPercussionTrack()) {
174
writeUnsignedByte(flags);
176
writeStringByte(track.getName(), 40);
177
writeInt(track.getStrings().size());
178
for (int i = 0; i < 7; i++) {
180
if (track.getStrings().size() > i) {
181
TGString string = (TGString) track.getStrings().get(i);
182
value = string.getValue();
187
writeInt(track.getChannel().getChannel() + 1);
188
writeInt(track.getChannel().getEffectChannel() + 1);
190
writeInt(Math.min(Math.max(track.getOffset(),0),12));
191
writeColor(track.getColor());
194
private void writeMeasure(TGMeasure measure, TGTempo tempo) throws IOException {
195
int beatCount = measure.countBeats();
197
for (int i = 0; i < beatCount; i++) {
198
TGBeat beat = measure.getBeat( i );
199
writeBeat(beat, measure, tempo);
203
private void writeBeat(TGBeat beat,TGMeasure measure, TGTempo songTempo) throws IOException {
204
TGDuration duration = beat.getDuration();
206
if (duration.isDotted() || duration.isDoubleDotted() ) {
209
if (!duration.getTupleto().isEqual(TGTupleto.NORMAL)) {
212
if(beat.isTextBeat()){
215
if (measure.getTempo().getValue() != songTempo.getValue()) {
218
TGNoteEffect effect = null;
219
if (beat.isRestBeat()) {
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() ||
234
writeUnsignedByte(flags);
236
if ((flags & 0x40) != 0) {
237
writeUnsignedByte(2);
239
writeByte(parseDuration(duration));
240
if ((flags & 0x20) != 0) {
241
writeInt(duration.getTupleto().getEnters());
243
if ((flags & 0x04) != 0) {
244
writeText(beat.getText());
246
if ((flags & 0x08) != 0) {
247
writeBeatEffects(effect);
249
if ((flags & 0x10) != 0) {
250
writeMixChange(measure.getTempo());
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);
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);
274
private void writeNote(TGNote note) throws IOException {
275
int flags = ( 0x20 | 0x10 );
276
if(note.getEffect().isGhostNote()){
279
if (note.getEffect().isBend() || note.getEffect().isGrace() || note.getEffect().isSlide() || note.getEffect().isHammer()) {
282
writeUnsignedByte(flags);
283
if ((flags & 0x20) != 0) {
284
int typeHeader = 0x01;
285
if (note.isTiedNote()) {
287
}else if(note.getEffect().isDeadNote()){
290
writeUnsignedByte(typeHeader);
292
if ((flags & 0x10) != 0) {
293
writeByte((byte)(((note.getVelocity() - TGVelocities.MIN_VELOCITY) / TGVelocities.VELOCITY_INCREMENT) + 1));
295
if ((flags & 0x20) != 0) {
296
writeByte((byte) note.getValue());
298
if ((flags & 0x08) != 0) {
299
writeNoteEffects(note.getEffect());
303
private byte parseDuration(TGDuration duration) {
305
switch (duration.getValue()) {
306
case TGDuration.WHOLE:
309
case TGDuration.HALF:
312
case TGDuration.QUARTER:
315
case TGDuration.EIGHTH:
318
case TGDuration.SIXTEENTH:
321
case TGDuration.THIRTY_SECOND:
324
case TGDuration.SIXTY_FOURTH:
331
private void writeText(TGText text) throws IOException {
332
writeStringByteSizeOfInteger(text.getValue());
335
private void writeBeatEffects(TGNoteEffect noteEffect) throws IOException {
337
if (noteEffect.isVibrato()) {
340
if (noteEffect.isTremoloBar() || noteEffect.isTapping() || noteEffect.isSlapping() || noteEffect.isPopping()) {
343
if (noteEffect.isHarmonic() && noteEffect.getHarmonic().getType() == TGEffectHarmonic.TYPE_NATURAL) {
346
if (noteEffect.isHarmonic() && noteEffect.getHarmonic().getType() != TGEffectHarmonic.TYPE_NATURAL) {
349
if (noteEffect.isFadeIn()) {
352
writeUnsignedByte(flags);
354
if ((flags & 0x20) != 0) {
355
if (noteEffect.isTremoloBar()){
356
writeUnsignedByte(0);
359
else if (noteEffect.isTapping()){
360
writeUnsignedByte(1);
363
else if (noteEffect.isSlapping()){
364
writeUnsignedByte(2);
367
else if (noteEffect.isPopping()){
368
writeUnsignedByte(3);
374
private void writeNoteEffects(TGNoteEffect effect) throws IOException {
376
if (effect.isBend()) {
379
if (effect.isHammer()) {
382
if (effect.isSlide()) {
385
if (effect.isGrace()) {
388
writeUnsignedByte(flags);
390
if ((flags & 0x01) != 0) {
391
writeBend(effect.getBend());
393
if ((flags & 0x10) != 0) {
394
writeGrace(effect.getGrace());
398
private void writeBend(TGEffectBend bend) throws IOException {
399
int points = bend.getPoints().size();
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) );
411
private void writeGrace(TGEffectGrace grace) throws IOException {
413
writeUnsignedByte(0xff);
415
writeUnsignedByte(grace.getFret());
417
writeUnsignedByte(((grace.getDynamic() - TGVelocities.MIN_VELOCITY) / TGVelocities.VELOCITY_INCREMENT) + 1);
418
if(grace.getTransition() == TGEffectGrace.TRANSITION_NONE){
419
writeUnsignedByte(0);
421
else if(grace.getTransition() == TGEffectGrace.TRANSITION_SLIDE){
422
writeUnsignedByte(1);
424
else if(grace.getTransition() == TGEffectGrace.TRANSITION_BEND){
425
writeUnsignedByte(2);
427
else if(grace.getTransition() == TGEffectGrace.TRANSITION_HAMMER){
428
writeUnsignedByte(3);
430
writeUnsignedByte(grace.getDuration());
433
private void writeMixChange(TGTempo tempo) throws IOException {
434
for (int i = 0; i < 7; i++) {
435
writeByte((byte) -1);
437
writeInt(tempo.getValue());
441
private void writeMarker(TGMarker marker) throws IOException {
442
writeStringByteSizeOfInteger(marker.getTitle());
443
writeColor(marker.getColor());
446
private void writeColor(TGColor color) throws IOException {
447
writeUnsignedByte(color.getR());
448
writeUnsignedByte(color.getG());
449
writeUnsignedByte(color.getB());
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);
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());
484
private byte toChannelByte(short s){
485
return (byte) ((s + 1) / 8);
b'\\ No newline at end of file'