2
* Created on 16-dic-2005
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.tg;
9
import java.io.DataOutputStream;
11
import java.io.FileNotFoundException;
12
import java.io.FileOutputStream;
13
import java.io.IOException;
14
import java.util.ArrayList;
15
import java.util.Iterator;
16
import java.util.List;
18
import org.herac.tuxguitar.song.models.Component;
19
import org.herac.tuxguitar.song.models.Duration;
20
import org.herac.tuxguitar.song.models.InstrumentString;
21
import org.herac.tuxguitar.song.models.Lyric;
22
import org.herac.tuxguitar.song.models.Marker;
23
import org.herac.tuxguitar.song.models.Measure;
24
import org.herac.tuxguitar.song.models.MeasureHeader;
25
import org.herac.tuxguitar.song.models.Note;
26
import org.herac.tuxguitar.song.models.NoteEffect;
27
import org.herac.tuxguitar.song.models.RGBColor;
28
import org.herac.tuxguitar.song.models.Silence;
29
import org.herac.tuxguitar.song.models.Song;
30
import org.herac.tuxguitar.song.models.SongChannel;
31
import org.herac.tuxguitar.song.models.SongTrack;
32
import org.herac.tuxguitar.song.models.Tempo;
33
import org.herac.tuxguitar.song.models.TimeSignature;
34
import org.herac.tuxguitar.song.models.Tupleto;
35
import org.herac.tuxguitar.song.models.VelocityValues;
36
import org.herac.tuxguitar.song.models.effects.BendEffect;
37
import org.herac.tuxguitar.song.models.effects.GraceEffect;
38
import org.herac.tuxguitar.song.models.effects.HarmonicEffect;
39
import org.herac.tuxguitar.song.models.effects.TremoloBarEffect;
40
import org.herac.tuxguitar.song.models.effects.TremoloPickingEffect;
41
import org.herac.tuxguitar.song.models.effects.TrillEffect;
46
* TODO To change the template for this generated type comment go to
47
* Window - Preferences - Java - Code Style - Code Templates
49
public class TGOutputStream extends TGStream{
50
private DataOutputStream dataOutputStream;
52
public TGOutputStream(FileOutputStream file) throws FileNotFoundException {
53
this.dataOutputStream = new DataOutputStream(file);
56
public TGOutputStream(String fileName) throws FileNotFoundException {
57
this(new FileOutputStream(new File(fileName)));
60
public void write(Song song){
64
this.dataOutputStream.flush();
65
this.dataOutputStream.close();
66
} catch (IOException e) {
71
private void writeVersion(){
72
writeString(TG_VERSION);
76
private void writeSong(Song song){
78
writeString(song.getName());
80
//escribo el interprete
81
writeString(song.getInterpret());
84
writeString(song.getAlbum());
87
writeString(song.getAuthor());
89
//escribo la cantidad de measure headers
90
writeShort((short)song.getMeasureHeaders().size());
93
MeasureHeader lastHeader = null;
94
for(int i = 0;i < song.getMeasureHeaders().size();i++){
95
MeasureHeader header = (MeasureHeader)song.getMeasureHeaders().get(i);
96
writeMeasureHeader(header,lastHeader);
101
//escribo la cantidad de pistas
102
writeByte(song.getTracks().size());
105
for(int i = 0;i < song.getTracks().size();i++){
106
SongTrack track = (SongTrack)song.getTracks().get(i);
112
private void writeTrack(SongTrack track){
115
if(!track.getLyrics().isEmpty()){
116
header |= TRACK_LYRICS;
121
writeString(track.getName());
124
writeChannel(track.getChannel());
126
//escribo los compases
127
Measure lastMeasure = null;
128
Iterator measureIt = track.getMeasures().iterator();
129
while(measureIt.hasNext()){
130
Measure measure = (Measure)measureIt.next();
131
writeMeasure(measure,lastMeasure);
132
lastMeasure = measure;
135
//escribo la cantidad de cuerdas
136
writeByte(track.getStrings().size());
138
//escribo las cuerdas
139
Iterator stringIt = track.getStrings().iterator();
140
while(stringIt.hasNext()){
141
InstrumentString string = (InstrumentString)stringIt.next();
142
writeInstrumentString(string);
146
writeByte(track.getOffset() - SongTrack.MIN_OFFSET);
149
writeRGBColor(track.getColor());
152
if(((header & TRACK_LYRICS) != 0)){
153
writeLyrics(track.getLyrics());
159
private void writeMeasureHeader(MeasureHeader measureheader,MeasureHeader lastMeasureHeader){
161
if(lastMeasureHeader == null){
162
header |= MEASURE_HEADER_TIMESIGNATURE;
163
header |= MEASURE_HEADER_TEMPO;
164
if(measureheader.getTripletFeel() != MeasureHeader.TRIPLET_FEEL_NONE){
165
header |= MEASURE_HEADER_TRIPLET_FEEL;
169
int numerator = measureheader.getTimeSignature().getNumerator();
170
int value = measureheader.getTimeSignature().getDenominator().getValue();
171
int prevNumerator = lastMeasureHeader.getTimeSignature().getNumerator();
172
int prevValue = lastMeasureHeader.getTimeSignature().getDenominator().getValue();
173
if(numerator != prevNumerator || value != prevValue){
174
header |= MEASURE_HEADER_TIMESIGNATURE;
177
if(measureheader.getTempo().getValue() != lastMeasureHeader.getTempo().getValue()){
178
header |= MEASURE_HEADER_TEMPO;
181
if(measureheader.getTripletFeel() != lastMeasureHeader.getTripletFeel()){
182
header |= MEASURE_HEADER_TRIPLET_FEEL;
185
header = (measureheader.isRepeatStart())?header |= MEASURE_HEADER_OPEN_REPEAT:header;
186
header = (measureheader.getNumberOfRepetitions() > 0)?header |= MEASURE_HEADER_CLOSE_REPEAT:header;
187
header = (measureheader.hasMarker())?header |= MEASURE_HEADER_MARKER:header;
191
//escribo el timeSignature
192
if(((header & MEASURE_HEADER_TIMESIGNATURE) != 0)){
193
writeTimeSignature(measureheader.getTimeSignature());
197
if(((header & MEASURE_HEADER_TEMPO) != 0)){
198
writeTempo(measureheader.getTempo());
201
//escribo el numero de repeticiones
202
if(((header & MEASURE_HEADER_CLOSE_REPEAT) != 0)){
203
writeShort((short)measureheader.getNumberOfRepetitions());
207
if(((header & MEASURE_HEADER_MARKER) != 0)){
208
writeMarker(measureheader.getMarker());
211
//escribo el triplet feel
212
if(((header & MEASURE_HEADER_TRIPLET_FEEL) != 0)){
213
writeByte(measureheader.getTripletFeel());
218
private void writeMeasure(Measure measure,Measure lastMeasure){
220
if(lastMeasure == null){
221
header |= MEASURE_CLEF;
222
header |= MEASURE_KEYSIGNATURE;
225
if(measure.getClef() != lastMeasure.getClef()){
226
header |= MEASURE_CLEF;
229
if(measure.getKeySignature() != lastMeasure.getKeySignature()){
230
header |= MEASURE_KEYSIGNATURE;
236
List components = getMeasureComponents(measure);
237
//escribo la cantidad de notas
238
writeShort((short)components.size());
240
//escribo las cuerdas
241
Component lastComponent = null;
242
Iterator it = components.iterator();
244
Component component = (Component)it.next();
245
writeComponent(component,lastComponent);
246
lastComponent = component;
250
if(((header & MEASURE_CLEF) != 0)){
251
writeByte(measure.getClef());
254
//escribo el key signature
255
if(((header & MEASURE_KEYSIGNATURE) != 0)){
256
writeByte(measure.getKeySignature());
260
private void writeChannel(SongChannel channel){
262
header = (channel.isSolo())?header |= CHANNEL_SOLO:header;
263
header = (channel.isMute())?header |= CHANNEL_MUTE:header;
267
writeByte(channel.getChannel());
269
//escribo el canal de efectos
270
writeByte(channel.getEffectChannel());
272
//escribo el instrumento
273
writeByte(channel.getInstrument());
276
writeByte(channel.getVolume());
279
writeByte(channel.getBalance());
282
writeByte(channel.getChorus());
285
writeByte(channel.getReverb());
288
writeByte(channel.getPhaser());
291
writeByte(channel.getTremolo());
294
private void writeComponent(Component component,Component lastComponent){
296
if(component instanceof Note){
297
Note note = (Note)component;
298
header |= COMPONENT_NOTE;
299
header = (note.isTiedNote())?header |= COMPONENT_TIEDNOTE:header;
300
header = ( !(lastComponent instanceof Note) && note.getVelocity() != VelocityValues.DEFAULT )?header |= COMPONENT_VELOCITY:header;
301
header = ((lastComponent instanceof Note) && (note.getVelocity() != ((Note)lastComponent).getVelocity() ) )?header |= COMPONENT_VELOCITY:header;
302
header = (note.getEffect().hasAnyEffect())?header |= COMPONENT_EFFECT:header;
303
}else if(component instanceof Silence){
304
header |= COMPONENT_SILENCE;
306
header = (lastComponent == null || component.getStart() != lastComponent.getStart())?header |= COMPONENT_NEXT_BEAT:header;
307
header = (lastComponent == null || !component.getDuration().isEqual(lastComponent.getDuration()))?header |= COMPONENT_NEXT_DURATION:header;
311
//escribo la duracion
312
if(((header & COMPONENT_NEXT_DURATION) != 0)){
313
writeDuration(component.getDuration());
315
if(((header & COMPONENT_NOTE) != 0)){
316
Note note = (Note)component;
319
writeByte(note.getValue());
322
writeByte(note.getString());
324
//escribo el velocity
325
if(((header & COMPONENT_VELOCITY) != 0)){
326
writeByte(note.getVelocity());
329
//escribo los efectos
330
if(((header & COMPONENT_EFFECT) != 0)){
331
writeNoteEffect(note.getEffect());
338
private void writeInstrumentString(InstrumentString string){
340
writeByte(string.getValue());
344
private void writeTempo(Tempo tempo){
346
writeShort((short)tempo.getValue());
350
private void writeTimeSignature(TimeSignature timeSignature){
351
//escribo el numerador
352
writeByte(timeSignature.getNumerator());
354
//escribo el denominador
355
writeDuration(timeSignature.getDenominator());
358
private void writeDuration(Duration duration){
360
header = (duration.isDotted())?header |= DURATION_DOTTED:header;
361
header = (duration.isDoubleDotted())?header |= DURATION_DOUBLE_DOTTED:header;
362
header = (!duration.getTupleto().isEqual(Duration.NO_TUPLETO))?header |= DURATION_TUPLETO:header;
366
writeByte(duration.getValue());
369
if(((header & DURATION_TUPLETO) != 0)){
370
writeTupleto(duration.getTupleto());
374
private void writeTupleto(Tupleto tupleto){
376
writeByte(tupleto.getEnters());
378
//escribo los tiempos
379
writeByte(tupleto.getTimes());
383
private void writeNoteEffect(NoteEffect effect){
386
header = (effect.isBend())?header |= EFFECT_BEND:header;
387
header = (effect.isTremoloBar())?header |= EFFECT_TREMOLO_BAR:header;
388
header = (effect.isHarmonic())?header |= EFFECT_HARMONIC:header;
389
header = (effect.isGrace())?header |= EFFECT_GRACE:header;
390
header = (effect.isTrill())?header |= EFFECT_TRILL:header;
391
header = (effect.isTremoloPicking())?header |= EFFECT_TREMOLO_PICKING:header;
392
header = (effect.isVibrato())?header |= EFFECT_VIBRATO:header;
393
header = (effect.isDeadNote())?header |= EFFECT_DEAD:header;
394
header = (effect.isSlide())?header |= EFFECT_SLIDE:header;
395
header = (effect.isHammer())?header |= EFFECT_HAMMER:header;
396
header = (effect.isGhostNote())?header |= EFFECT_GHOST:header;
397
header = (effect.isAccentuatedNote())?header |= EFFECT_ACCENTUATED:header;
398
header = (effect.isHeavyAccentuatedNote())?header |= EFFECT_HEAVY_ACCENTUATED:header;
399
header = (effect.isPalmMute())?header |= EFFECT_PALM_MUTE:header;
400
header = (effect.isStaccato())?header |= EFFECT_STACCATO:header;
401
header = (effect.isTapping())?header |= EFFECT_TAPPING:header;
402
header = (effect.isSlapping())?header |= EFFECT_SLAPPING:header;
403
header = (effect.isPopping())?header |= EFFECT_POPPING:header;
404
header = (effect.isFadeIn())?header |= EFFECT_FADE_IN:header;
406
writeHeader(header,3);
409
if(((header & EFFECT_BEND) != 0)){
410
writeBendEffect(effect.getBend());
414
if(((header & EFFECT_TREMOLO_BAR) != 0)){
415
writeTremoloBarEffect(effect.getTremoloBar());
419
if(((header & EFFECT_HARMONIC) != 0)){
420
writeHarmonicEffect(effect.getHarmonic());
424
if(((header & EFFECT_GRACE) != 0)){
425
writeGraceEffect(effect.getGrace());
429
if(((header & EFFECT_TRILL) != 0)){
430
writeTrillEffect(effect.getTrill());
433
//leo el tremolo picking
434
if(((header & EFFECT_TREMOLO_PICKING) != 0)){
435
writeTremoloPickingEffect(effect.getTremoloPicking());
439
private void writeBendEffect(BendEffect effect){
440
//escribo la cantidad de puntos
441
writeByte(effect.getPoints().size());
443
Iterator it = effect.getPoints().iterator();
445
BendEffect.BendPoint point = (BendEffect.BendPoint)it.next();
447
//escribo la posicion
448
writeByte(point.getPosition());
451
writeByte(point.getValue());
455
private void writeTremoloBarEffect(TremoloBarEffect effect){
456
//escribo la cantidad de puntos
457
writeByte(effect.getPoints().size());
459
Iterator it = effect.getPoints().iterator();
461
TremoloBarEffect.TremoloBarPoint point = (TremoloBarEffect.TremoloBarPoint)it.next();
463
//escribo la posicion
464
writeByte(point.getPosition());
467
writeByte( (point.getValue() + TremoloBarEffect.MAX_VALUE_LENGTH) );
471
private void writeHarmonicEffect(HarmonicEffect effect){
473
writeByte(effect.getType());
476
if(effect.getType() == HarmonicEffect.TYPE_ARTIFICIAL){
477
writeByte(effect.getData() - HarmonicEffect.MIN_ARTIFICIAL_OFFSET);
478
}else if(effect.getType() == HarmonicEffect.TYPE_TAPPED){
479
writeByte(effect.getData());
483
private void writeGraceEffect(GraceEffect effect){
485
header = (effect.isDead())?header |= GRACE_FLAG_DEAD:header;
486
header = (effect.isOnBeat())?header |= GRACE_FLAG_ON_BEAT:header;
492
writeByte(effect.getFret());
494
//excribo la duracion
495
writeByte(effect.getDuration());
497
//excribo el velocity
498
writeByte(effect.getDynamic());
500
//excribo la transicion
501
writeByte(effect.getTransition());
504
private void writeTremoloPickingEffect(TremoloPickingEffect effect){
505
//excribo la duracion
506
writeByte(effect.getDuration().getValue());
509
private void writeTrillEffect(TrillEffect effect){
511
writeByte(effect.getFret());
513
//excribo la duracion
514
writeByte(effect.getDuration().getValue());
518
private void writeMarker(Marker marker){
520
writeString(marker.getTitle());
523
writeRGBColor(marker.getColor());
526
private void writeRGBColor(RGBColor color){
528
writeShort((short)color.getR());
529
writeShort((short)color.getG());
530
writeShort((short)color.getB());
533
private void writeLyrics(Lyric lyrics){
534
//escribo el compas de comienzo
535
writeShort((short)lyrics.getFrom());
538
writeString(lyrics.getLyrics());
542
private List getMeasureComponents(Measure measure){
543
List components = new ArrayList();
544
components.addAll(measure.getNotes());
545
components.addAll(measure.getSilences());
547
for(int i = 0;i < components.size();i++){
548
Component minComponent = null;
549
for(int j = i;j < components.size();j++){
550
Component component = (Component)components.get(j);
551
if(minComponent == null || component.getStart() < minComponent.getStart()){
552
minComponent = component;
555
components.remove(minComponent);
556
components.add(i,minComponent);
561
public void writeByte(int v){
563
this.dataOutputStream.write(v);
564
} catch (IOException e) {
569
private void writeString(String v){
571
this.dataOutputStream.write(v.length());
572
this.dataOutputStream.writeChars(v);
573
} catch (IOException e) {
578
public void writeHeader(int v){
580
this.dataOutputStream.write(v);
581
} catch (IOException e) {
586
public void writeHeader(int v,int bCount){
587
for(int i = bCount; i > 0; i --){
588
writeHeader( (v >>> ( (8 * i) - 8 ) ) & 0xFF);
593
public void writeShort(short v){
595
this.dataOutputStream.writeShort(v);
596
} catch (IOException e) {