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

« back to all changes in this revision

Viewing changes to TuxGuitar-midi/src/org/herac/tuxguitar/io/midi/MidiSongImporter.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
package org.herac.tuxguitar.io.midi;
 
2
 
 
3
import java.io.InputStream;
 
4
import java.util.ArrayList;
 
5
import java.util.Iterator;
 
6
import java.util.List;
 
7
 
 
8
import org.herac.tuxguitar.io.base.TGFileFormat;
 
9
import org.herac.tuxguitar.io.base.TGFileFormatException;
 
10
import org.herac.tuxguitar.io.base.TGSongImporter;
 
11
import org.herac.tuxguitar.io.midi.base.MidiEvent;
 
12
import org.herac.tuxguitar.io.midi.base.MidiMessage;
 
13
import org.herac.tuxguitar.io.midi.base.MidiSequence;
 
14
import org.herac.tuxguitar.io.midi.base.MidiTrack;
 
15
import org.herac.tuxguitar.player.base.MidiControllers;
 
16
import org.herac.tuxguitar.song.factory.TGFactory;
 
17
import org.herac.tuxguitar.song.managers.TGSongManager;
 
18
import org.herac.tuxguitar.song.models.TGBeat;
 
19
import org.herac.tuxguitar.song.models.TGChannel;
 
20
import org.herac.tuxguitar.song.models.TGColor;
 
21
import org.herac.tuxguitar.song.models.TGDuration;
 
22
import org.herac.tuxguitar.song.models.TGMeasure;
 
23
import org.herac.tuxguitar.song.models.TGMeasureHeader;
 
24
import org.herac.tuxguitar.song.models.TGNote;
 
25
import org.herac.tuxguitar.song.models.TGSong;
 
26
import org.herac.tuxguitar.song.models.TGString;
 
27
import org.herac.tuxguitar.song.models.TGTempo;
 
28
import org.herac.tuxguitar.song.models.TGTimeSignature;
 
29
import org.herac.tuxguitar.song.models.TGTrack;
 
30
 
 
31
public class MidiSongImporter implements TGSongImporter{
 
32
        
 
33
        private static final int MIN_DURATION_VALUE = TGDuration.SIXTY_FOURTH;
 
34
        
 
35
        private int resolution;
 
36
        private List headers;
 
37
        private List tracks;
 
38
        private List tempNotes;
 
39
        private List tempChannels;
 
40
        private List trackTuningHelpers;
 
41
        private MidiSettings settings;
 
42
        protected TGFactory factory;
 
43
        
 
44
        public MidiSongImporter(){
 
45
                super();
 
46
        }
 
47
        
 
48
        public TGFileFormat getFileFormat() {
 
49
                return new TGFileFormat("Midi","*.mid;*.midi");
 
50
        }
 
51
        
 
52
        public String getImportName() {
 
53
                return "Midi";
 
54
        }
 
55
        
 
56
        public boolean configure(boolean setDefaults){
 
57
                this.settings = (setDefaults ? MidiSettings.getDefaults() : new MidiSettingsDialog().open());
 
58
                return (this.settings != null);
 
59
        }
 
60
        
 
61
        public TGSong importSong(TGFactory factory,InputStream stream) throws TGFileFormatException {
 
62
                try {
 
63
                        if(this.settings == null){
 
64
                                return null;
 
65
                        }
 
66
                        this.factory = factory;
 
67
                        
 
68
                        MidiSequence sequence = new MidiFileReader().getSequence(stream);
 
69
                        initFields(sequence);
 
70
                        for(int i = 0; i < sequence.countTracks(); i++){
 
71
                                MidiTrack track = sequence.getTrack(i);
 
72
                                int trackNumber = getNextTrackNumber();
 
73
                                int events = track.size();
 
74
                                for(int j = 0;j < events;j ++){
 
75
                                        MidiEvent event = track.get(j);
 
76
                                        parseMessage(trackNumber,event.getTick(),event.getMessage());
 
77
                                }
 
78
                        }
 
79
                        checkAll();
 
80
                        
 
81
                        TGSong song = this.factory.newSong();
 
82
                        
 
83
                        Iterator headers = this.headers.iterator();
 
84
                        while(headers.hasNext()){
 
85
                                song.addMeasureHeader((TGMeasureHeader)headers.next());
 
86
                        }
 
87
                        Iterator tracks = this.tracks.iterator();
 
88
                        while(tracks.hasNext()){
 
89
                                song.addTrack((TGTrack)tracks.next());
 
90
                        }
 
91
                        return new SongAdjuster(this.factory,song).adjustSong();
 
92
                } catch (Throwable throwable) {
 
93
                        throw new TGFileFormatException(throwable);
 
94
                }
 
95
        }
 
96
        
 
97
        private void initFields(MidiSequence sequence){
 
98
                this.resolution = sequence.getResolution();
 
99
                this.headers = new ArrayList();
 
100
                this.tracks = new ArrayList();
 
101
                this.tempNotes = new ArrayList();
 
102
                this.tempChannels = new ArrayList();
 
103
                this.trackTuningHelpers = new ArrayList();
 
104
        }
 
105
        
 
106
        private int getNextTrackNumber(){
 
107
                return (this.tracks.size() + 1);
 
108
        }
 
109
        
 
110
        private void parseMessage(int trackNumber,long tick,MidiMessage message){
 
111
                long parsedTick = parseTick(tick + this.resolution);
 
112
                
 
113
                //NOTE ON
 
114
                if(message.getType() == MidiMessage.TYPE_SHORT && message.getCommand() == MidiMessage.NOTE_ON){
 
115
                        parseNoteOn(trackNumber,parsedTick,message.getData());
 
116
                }
 
117
                //NOTE OFF
 
118
                else if(message.getType() == MidiMessage.TYPE_SHORT && message.getCommand() == MidiMessage.NOTE_OFF){
 
119
                        parseNoteOff(trackNumber,parsedTick,message.getData());
 
120
                }
 
121
                //PROGRAM CHANGE
 
122
                else if(message.getType() == MidiMessage.TYPE_SHORT && message.getCommand() == MidiMessage.PROGRAM_CHANGE){
 
123
                        parseProgramChange(message.getData());
 
124
                }
 
125
                //CONTROL CHANGE
 
126
                else if(message.getType() == MidiMessage.TYPE_SHORT && message.getCommand() == MidiMessage.CONTROL_CHANGE){
 
127
                        parseControlChange(message.getData());
 
128
                }
 
129
                //TIME SIGNATURE
 
130
                else if(message.getType() == MidiMessage.TYPE_META && message.getCommand() == MidiMessage.TIME_SIGNATURE_CHANGE){
 
131
                        parseTimeSignature(parsedTick,message.getData());
 
132
                }
 
133
                //TEMPO
 
134
                else if(message.getType() == MidiMessage.TYPE_META && message.getCommand() == MidiMessage.TEMPO_CHANGE){
 
135
                        parseTempo(parsedTick,message.getData());
 
136
                }
 
137
        }
 
138
        
 
139
        private long parseTick(long tick){
 
140
                return Math.abs(TGDuration.QUARTER_TIME * tick / this.resolution);
 
141
        }
 
142
        
 
143
        private void parseNoteOn(int track,long tick,byte[] data){
 
144
                int length = data.length;
 
145
                int channel = (length > 0)?((data[0] & 0xFF) & 0x0F):0;
 
146
                int value = (length > 1)?(data[1] & 0xFF):0;
 
147
                int velocity = (length > 2)?(data[2] & 0xFF):0;
 
148
                if(velocity == 0){
 
149
                        parseNoteOff(track,tick,data);
 
150
                }else if(value > 0){
 
151
                        makeTempNotesBefore(tick,track);
 
152
                        getTempChannel(channel).setTrack(track);
 
153
                        getTrackTuningHelper(track).checkValue(value);
 
154
                        this.tempNotes.add(new TempNote(track,channel,value,tick));
 
155
                }
 
156
        }
 
157
        
 
158
        private void parseNoteOff(int track,long tick,byte[] data){
 
159
                int length = data.length;
 
160
                
 
161
                int channel = (length > 0)?((data[0] & 0xFF) & 0x0F):0;
 
162
                int value = (length > 1)?(data[1] & 0xFF):0;
 
163
                
 
164
                makeNote(tick,track,channel,value);
 
165
        }
 
166
        
 
167
        private void parseProgramChange(byte[] data){
 
168
                int length = data.length;
 
169
                int channel = (length > 0)?((data[0] & 0xFF) & 0x0F):-1;
 
170
                int instrument = (length > 1)?(data[1] & 0xFF):-1;
 
171
                if(channel != -1 && instrument != -1){
 
172
                        getTempChannel(channel).setInstrument(instrument);
 
173
                }
 
174
        }
 
175
        
 
176
        private void parseControlChange(byte[] data){
 
177
                int length = data.length;
 
178
                int channel = (length > 0)?((data[0] & 0xFF) & 0x0F):-1;
 
179
                int control = (length > 1)?(data[1] & 0xFF):-1;
 
180
                int value = (length > 2)?(data[2] & 0xFF):-1;
 
181
                if(channel != -1 && control != -1 && value != -1){
 
182
                        if(control == MidiControllers.VOLUME){
 
183
                                getTempChannel(channel).setVolume(value);
 
184
                        }
 
185
                        else if(control == MidiControllers.BALANCE){
 
186
                                getTempChannel(channel).setBalance(value);
 
187
                        }
 
188
                }
 
189
        }
 
190
        
 
191
        private void parseTimeSignature(long tick,byte[] data){
 
192
                if(data.length >= 2){
 
193
                        TGTimeSignature timeSignature = this.factory.newTimeSignature();
 
194
                        timeSignature.setNumerator(data[0]);
 
195
                        timeSignature.getDenominator().setValue(TGDuration.QUARTER);
 
196
                        if (data[1] == 0) {
 
197
                                timeSignature.getDenominator().setValue(TGDuration.WHOLE);
 
198
                        } else if (data[1] == 1) {
 
199
                                timeSignature.getDenominator().setValue(TGDuration.HALF);
 
200
                        } else if (data[1] == 2) {
 
201
                                timeSignature.getDenominator().setValue(TGDuration.QUARTER);
 
202
                        } else if (data[1] == 3) {
 
203
                                timeSignature.getDenominator().setValue(TGDuration.EIGHTH);
 
204
                        } else if (data[1] == 4) {
 
205
                                timeSignature.getDenominator().setValue(TGDuration.SIXTEENTH);
 
206
                        } else if (data[1] == 5) {
 
207
                                timeSignature.getDenominator().setValue(TGDuration.THIRTY_SECOND);
 
208
                        }
 
209
                        getHeader(tick).setTimeSignature(timeSignature);
 
210
                }
 
211
        }
 
212
        
 
213
        private void parseTempo(long tick,byte[] data){
 
214
                if(data.length >= 3){
 
215
                        TGTempo tempo = TGTempo.fromUSQ(this.factory,(data[2] & 0xff) | ((data[1] & 0xff) << 8) | ((data[0] & 0xff) << 16));
 
216
                        getHeader(tick).setTempo(tempo);
 
217
                }
 
218
        }
 
219
        
 
220
        private TGTrack getTrack(int number){
 
221
                Iterator it = this.tracks.iterator();
 
222
                while(it.hasNext()){
 
223
                        TGTrack track = (TGTrack)it.next();
 
224
                        if(track.getNumber() == number){
 
225
                                return track;
 
226
                        }
 
227
                }
 
228
                TGChannel channel = this.factory.newChannel();
 
229
                channel.setChannel((short)-1);
 
230
                channel.setEffectChannel((short)-1);
 
231
                channel.setInstrument((short)0);
 
232
                
 
233
                TGTrack track = this.factory.newTrack();
 
234
                track.setNumber(number);
 
235
                track.setChannel(channel);
 
236
                TGColor.RED.copy(track.getColor());
 
237
                
 
238
                this.tracks.add(track);
 
239
                return track;
 
240
        }
 
241
        
 
242
        private TGMeasureHeader getHeader(long tick){
 
243
                long realTick = (tick >= TGDuration.QUARTER_TIME)?tick:TGDuration.QUARTER_TIME;
 
244
                
 
245
                Iterator it = this.headers.iterator();
 
246
                while(it.hasNext()){
 
247
                        TGMeasureHeader header = (TGMeasureHeader)it.next();
 
248
                        if(realTick >= header.getStart() && realTick < header.getStart() + header.getLength()){
 
249
                                return header;
 
250
                        }
 
251
                }
 
252
                TGMeasureHeader last = getLastHeader();
 
253
                TGMeasureHeader header = this.factory.newHeader();
 
254
                header.setNumber((last != null)?last.getNumber() + 1:1);
 
255
                header.setStart((last != null)?(last.getStart() + last.getLength()):TGDuration.QUARTER_TIME);
 
256
                header.getTempo().setValue(  (last != null)?last.getTempo().getValue():120 );
 
257
                if(last != null){
 
258
                        last.getTimeSignature().copy(header.getTimeSignature());
 
259
                }else{
 
260
                        header.getTimeSignature().setNumerator(4);
 
261
                        header.getTimeSignature().getDenominator().setValue(TGDuration.QUARTER);
 
262
                }
 
263
                this.headers.add(header);
 
264
                
 
265
                if(realTick >= header.getStart() && realTick < header.getStart() + header.getLength()){
 
266
                        return header;
 
267
                }
 
268
                return getHeader(realTick);
 
269
        }
 
270
        
 
271
        private TGMeasureHeader getLastHeader(){
 
272
                if(!this.headers.isEmpty()){
 
273
                        return (TGMeasureHeader)this.headers.get(this.headers.size() - 1);
 
274
                }
 
275
                return null;
 
276
        }
 
277
        
 
278
        private TGMeasure getMeasure(TGTrack track,long tick){
 
279
                long realTick = (tick >= TGDuration.QUARTER_TIME)?tick:TGDuration.QUARTER_TIME;
 
280
                Iterator it = track.getMeasures();
 
281
                while(it.hasNext()){
 
282
                        TGMeasure measure = (TGMeasure)it.next();
 
283
                        if(realTick >= measure.getStart() && realTick < measure.getStart() + measure.getLength()){
 
284
                                return measure;
 
285
                        }
 
286
                }
 
287
                getHeader(realTick);
 
288
                for(int i = 0;i < this.headers.size();i++){
 
289
                        boolean exist = false;
 
290
                        TGMeasureHeader header = (TGMeasureHeader)this.headers.get(i);
 
291
                        int measureCount = track.countMeasures();
 
292
                        for(int j = 0;j < measureCount;j++){
 
293
                                TGMeasure measure = track.getMeasure(j);
 
294
                                if(measure.getHeader().equals(header)){
 
295
                                        exist = true;
 
296
                                }
 
297
                        }
 
298
                        if(!exist){
 
299
                                TGMeasure measure = this.factory.newMeasure(header);
 
300
                                track.addMeasure(measure);
 
301
                        }
 
302
                }
 
303
                return getMeasure(track,realTick);
 
304
        }
 
305
        
 
306
        private TGBeat getBeat(TGMeasure measure, long start){
 
307
                int beatCount = measure.countBeats();
 
308
                for( int i = 0 ; i < beatCount ; i ++){
 
309
                        TGBeat beat = measure.getBeat( i );
 
310
                        if( beat.getStart() == start){
 
311
                                return beat;
 
312
                        }
 
313
                }
 
314
                
 
315
                TGBeat beat = this.factory.newBeat();
 
316
                beat.setStart(start);
 
317
                measure.addBeat(beat);
 
318
                return beat;
 
319
        }
 
320
        
 
321
        private TempNote getTempNote(int track,int channel,int value,boolean purge){
 
322
                for(int i = 0;i < this.tempNotes.size();i ++){
 
323
                        TempNote note = (TempNote)this.tempNotes.get(i);
 
324
                        if(note.getTrack() == track && note.getChannel() == channel && note.getValue() == value){
 
325
                                if(purge){
 
326
                                        this.tempNotes.remove(i);
 
327
                                }
 
328
                                return note;
 
329
                        }
 
330
                }
 
331
                return null;
 
332
        }
 
333
        
 
334
        protected TrackTuningHelper getTrackTuningHelper(int track){
 
335
                Iterator it = this.trackTuningHelpers.iterator();
 
336
                while(it.hasNext()){
 
337
                        TrackTuningHelper helper = (TrackTuningHelper)it.next();
 
338
                        if(helper.getTrack() == track){
 
339
                                return helper;
 
340
                        }
 
341
                }
 
342
                TrackTuningHelper helper = new TrackTuningHelper(track);
 
343
                this.trackTuningHelpers.add(helper);
 
344
                
 
345
                return helper;
 
346
        }
 
347
        
 
348
        private void makeTempNotesBefore(long tick,int track){
 
349
                long nextTick = tick;
 
350
                boolean check = true;
 
351
                while(check){
 
352
                        check = false;
 
353
                        for(int i = 0;i < this.tempNotes.size();i ++){
 
354
                                TempNote note = (TempNote)this.tempNotes.get(i);
 
355
                                if(note.getTick() < nextTick && note.getTrack() == track){
 
356
                                        nextTick = note.getTick() + (TGDuration.QUARTER_TIME * 5); //First beat + 4/4 measure;
 
357
                                        makeNote(nextTick,track,note.getChannel(),note.getValue());
 
358
                                        check = true;
 
359
                                        break;
 
360
                                }
 
361
                        }
 
362
                }
 
363
        }
 
364
        
 
365
        private void makeNote(long tick,int track,int channel,int value){
 
366
                TempNote tempNote = getTempNote(track,channel,value,true);
 
367
                if(tempNote != null){
 
368
                        int nString = 0;
 
369
                        int nValue = (tempNote.getValue() + this.settings.getTranspose());
 
370
                        int nVelocity = 64;
 
371
                        long nStart = tempNote.getTick();
 
372
                        TGDuration minDuration = newDuration(MIN_DURATION_VALUE);
 
373
                        TGDuration nDuration = TGDuration.fromTime(this.factory,tick - tempNote.getTick(),minDuration);
 
374
                        
 
375
                        TGMeasure measure = getMeasure(getTrack(track),tempNote.getTick());
 
376
                        TGBeat beat = getBeat(measure, nStart);
 
377
                        nDuration.copy(beat.getDuration());
 
378
                        
 
379
                        TGNote note = this.factory.newNote();
 
380
                        note.setValue(nValue);
 
381
                        note.setString(nString);
 
382
                        note.setVelocity(nVelocity);
 
383
                        
 
384
                        beat.addNote(note);
 
385
                }
 
386
        }
 
387
        
 
388
        public TempChannel getTempChannel(int channel){
 
389
                Iterator it = this.tempChannels.iterator();
 
390
                while(it.hasNext()){
 
391
                        TempChannel tempChannel = (TempChannel)it.next();
 
392
                        if(tempChannel.getChannel() == channel){
 
393
                                return tempChannel;
 
394
                        }
 
395
                }
 
396
                TempChannel tempChannel = new TempChannel(channel);
 
397
                this.tempChannels.add(tempChannel);
 
398
                
 
399
                return tempChannel;
 
400
        }
 
401
        
 
402
        private void checkAll()throws Exception{
 
403
                checkTracks();
 
404
                
 
405
                int headerCount = this.headers.size();
 
406
                for(int i = 0;i < this.tracks.size();i ++){
 
407
                        TGTrack track = (TGTrack)this.tracks.get(i);
 
408
                        
 
409
                        while(track.countMeasures() < headerCount){
 
410
                                long start = TGDuration.QUARTER_TIME;
 
411
                                TGMeasure lastMeasure = ((track.countMeasures() > 0)?track.getMeasure(track.countMeasures() - 1) :null);
 
412
                                if(lastMeasure != null){
 
413
                                        start = (lastMeasure.getStart() + lastMeasure.getLength());
 
414
                                }
 
415
                                
 
416
                                track.addMeasure(this.factory.newMeasure(getHeader(start)));
 
417
                        }
 
418
                }
 
419
                
 
420
                if(this.headers.isEmpty() || this.tracks.isEmpty()){
 
421
                        throw new Exception("Empty Song");
 
422
                }
 
423
        }
 
424
        
 
425
        private void checkTracks(){
 
426
                Iterator it = this.tracks.iterator();
 
427
                while(it.hasNext()){
 
428
                        TGTrack track = (TGTrack)it.next();
 
429
                        Iterator tcIt = this.tempChannels.iterator();
 
430
                        while(tcIt.hasNext()){
 
431
                                TempChannel tempChannel = (TempChannel)tcIt.next();
 
432
                                if(tempChannel.getTrack() == track.getNumber()){
 
433
                                        if(track.getChannel().getChannel() < 0){
 
434
                                                track.getChannel().setChannel((short)tempChannel.getChannel());
 
435
                                                track.getChannel().setInstrument((short)tempChannel.getInstrument());
 
436
                                                track.getChannel().setVolume((short)tempChannel.getVolume());
 
437
                                                track.getChannel().setBalance((short)tempChannel.getBalance());
 
438
                                        }else if(track.getChannel().getEffectChannel() < 0){
 
439
                                                track.getChannel().setEffectChannel((short)tempChannel.getChannel());
 
440
                                        }
 
441
                                }
 
442
                        }
 
443
                        if(track.getChannel().getChannel() < 0){
 
444
                                track.getChannel().setChannel((short)(TGSongManager.MAX_CHANNELS - 1));
 
445
                                track.getChannel().setInstrument((short)0);
 
446
                                track.getChannel().setVolume((short)127);
 
447
                                track.getChannel().setBalance((short)64);
 
448
                        }
 
449
                        if(track.getChannel().getEffectChannel() < 0){
 
450
                                track.getChannel().setEffectChannel(track.getChannel().getChannel());
 
451
                        }
 
452
                        
 
453
                        if(!track.isPercussionTrack()){
 
454
                                track.setStrings(getTrackTuningHelper(track.getNumber()).getStrings());
 
455
                        }else{
 
456
                                track.setStrings(TGSongManager.createPercusionStrings(this.factory,6));
 
457
                        }
 
458
                }
 
459
        }
 
460
        
 
461
        protected TGDuration newDuration(int value){
 
462
                TGDuration duration = this.factory.newDuration();
 
463
                duration.setValue(value);
 
464
                return duration;
 
465
        }
 
466
        
 
467
        private class TempNote{
 
468
                private int track;
 
469
                private int channel;
 
470
                private int value;
 
471
                private long tick;
 
472
                
 
473
                public TempNote(int track, int channel, int value,long tick) {
 
474
                        this.track = track;
 
475
                        this.channel = channel;
 
476
                        this.value = value;
 
477
                        this.tick = tick;
 
478
                }
 
479
                
 
480
                public int getChannel() {
 
481
                        return this.channel;
 
482
                }
 
483
                
 
484
                public void setChannel(int channel) {
 
485
                        this.channel = channel;
 
486
                }
 
487
                
 
488
                public long getTick() {
 
489
                        return this.tick;
 
490
                }
 
491
                
 
492
                public void setTick(long tick) {
 
493
                        this.tick = tick;
 
494
                }
 
495
                
 
496
                public int getTrack() {
 
497
                        return this.track;
 
498
                }
 
499
                
 
500
                public void setTrack(int track) {
 
501
                        this.track = track;
 
502
                }
 
503
                
 
504
                public int getValue() {
 
505
                        return this.value;
 
506
                }
 
507
                
 
508
                public void setValue(int value) {
 
509
                        this.value = value;
 
510
                }
 
511
                
 
512
        }
 
513
        
 
514
        private class TempChannel{
 
515
                private int channel;
 
516
                private int instrument;
 
517
                private int volume;
 
518
                private int balance;
 
519
                private int track;
 
520
                
 
521
                public TempChannel(int channel) {
 
522
                        this.channel = channel;
 
523
                        this.instrument = 0;
 
524
                        this.volume = 127;
 
525
                        this.balance = 64;
 
526
                        this.track = -1;
 
527
                }
 
528
                
 
529
                public int getBalance() {
 
530
                        return this.balance;
 
531
                }
 
532
                
 
533
                public void setBalance(int balance) {
 
534
                        this.balance = balance;
 
535
                }
 
536
                
 
537
                public int getChannel() {
 
538
                        return this.channel;
 
539
                }
 
540
                
 
541
                public void setChannel(int channel) {
 
542
                        this.channel = channel;
 
543
                }
 
544
                
 
545
                public int getInstrument() {
 
546
                        return this.instrument;
 
547
                }
 
548
                
 
549
                public void setInstrument(int instrument) {
 
550
                        this.instrument = instrument;
 
551
                }
 
552
                
 
553
                public int getTrack() {
 
554
                        return this.track;
 
555
                }
 
556
                
 
557
                public void setTrack(int track) {
 
558
                        this.track = track;
 
559
                }
 
560
                
 
561
                public int getVolume() {
 
562
                        return this.volume;
 
563
                }
 
564
                
 
565
                public void setVolume(int volume) {
 
566
                        this.volume = volume;
 
567
                }
 
568
                
 
569
        }
 
570
        
 
571
        private class TrackTuningHelper{
 
572
                private int track;
 
573
                private int maxValue;
 
574
                private int minValue;
 
575
                
 
576
                public TrackTuningHelper(int track){
 
577
                        this.track = track;
 
578
                        this.maxValue = -1;
 
579
                        this.minValue = -1;
 
580
                }
 
581
                
 
582
                public void checkValue(int value){
 
583
                        if(this.minValue < 0 || value < this.minValue){
 
584
                                this.minValue = value;
 
585
                        }
 
586
                        if(this.maxValue < 0 || value > this.maxValue){
 
587
                                this.maxValue = value;
 
588
                        }
 
589
                }
 
590
                
 
591
                public List getStrings() {
 
592
                        List strings = new ArrayList();
 
593
                        
 
594
                        int maxFret = 24;
 
595
                        
 
596
                        if(this.minValue >= 40 && this.maxValue <= 64 + maxFret){
 
597
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,1, 64));
 
598
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,2, 59));
 
599
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,3, 55));
 
600
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,4, 50));
 
601
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,5, 45));
 
602
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,6, 40));
 
603
                        }
 
604
                        else if(this.minValue >= 38 && this.maxValue <= 64 + maxFret){
 
605
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,1, 64));
 
606
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,2, 59));
 
607
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,3, 55));
 
608
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,4, 50));
 
609
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,5, 45));
 
610
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,6, 38));
 
611
                        }
 
612
                        else if(this.minValue >= 35 && this.maxValue <= 64 + maxFret){
 
613
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,1, 64));
 
614
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,2, 59));
 
615
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,3, 55));
 
616
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,4, 50));
 
617
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,5, 45));
 
618
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,6, 40));
 
619
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,7, 35));
 
620
                        }
 
621
                        else if(this.minValue >= 28 && this.maxValue <= 43 + maxFret){
 
622
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,1, 43));
 
623
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,2, 38));
 
624
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,3, 33));
 
625
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,4, 28));
 
626
                        }
 
627
                        else if(this.minValue >= 23 && this.maxValue <= 43 + maxFret){
 
628
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,1, 43));
 
629
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,2, 38));
 
630
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,3, 33));
 
631
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,4, 28));
 
632
                                strings.add(TGSongManager.newString(MidiSongImporter.this.factory,5, 23));
 
633
                        }else{
 
634
                                int stringCount = 6;
 
635
                                int stringSpacing = ((this.maxValue - (maxFret - 4) - this.minValue) / stringCount);
 
636
                                if(stringSpacing > 5){
 
637
                                        stringCount = 7;
 
638
                                        stringSpacing = ((this.maxValue - (maxFret - 4) - this.minValue) / stringCount);
 
639
                                }
 
640
                                
 
641
                                int maxStringValue = (this.minValue + (stringCount * stringSpacing));
 
642
                                while(strings.size() < stringCount){
 
643
                                        maxStringValue -= stringSpacing;
 
644
                                        strings.add(TGSongManager.newString(MidiSongImporter.this.factory,strings.size() + 1,maxStringValue));
 
645
                                }
 
646
                        }
 
647
                        
 
648
                        return strings;
 
649
                }
 
650
                
 
651
                public int getMaxValue() {
 
652
                        return this.maxValue;
 
653
                }
 
654
                
 
655
                public int getMinValue() {
 
656
                        return this.minValue;
 
657
                }
 
658
                
 
659
                public int getTrack() {
 
660
                        return this.track;
 
661
                }
 
662
                
 
663
        }
 
664
}
 
665
 
 
666
class SongAdjuster{
 
667
        private TGFactory factory;
 
668
        private TGSong song;
 
669
        private long minDurationTime;
 
670
        
 
671
        public SongAdjuster(TGFactory factory,TGSong song){
 
672
                this.factory = factory;
 
673
                this.song = song;
 
674
                this.minDurationTime = 40;
 
675
        }
 
676
        
 
677
        public TGSong adjustSong(){
 
678
                Iterator it = this.song.getTracks();
 
679
                
 
680
                while(it.hasNext()){
 
681
                        TGTrack track = (TGTrack)it.next();
 
682
                        adjustTrack(track);
 
683
                }
 
684
                return this.song;
 
685
        }
 
686
        
 
687
        private void adjustTrack(TGTrack track){
 
688
                Iterator it = track.getMeasures();
 
689
                while(it.hasNext()){
 
690
                        TGMeasure measure = (TGMeasure)it.next();
 
691
                        process(measure);
 
692
                }
 
693
        }
 
694
        
 
695
        public void process(TGMeasure measure){
 
696
                orderBeats(measure);
 
697
                joinBeats(measure);
 
698
                adjustStrings(measure);
 
699
        }
 
700
        
 
701
        public void joinBeats(TGMeasure measure){
 
702
                TGBeat previous = null;
 
703
                boolean finish = true;
 
704
                
 
705
                long measureStart = measure.getStart();
 
706
                long measureEnd = (measureStart + measure.getLength());
 
707
                for(int i = 0;i < measure.countBeats();i++){
 
708
                        TGBeat beat = measure.getBeat( i );
 
709
                        long beatStart = beat.getStart();
 
710
                        long beatLength = beat.getDuration().getTime();
 
711
                        if(previous != null){
 
712
                                long previousStart = previous.getStart();
 
713
                                long previousLength = previous.getDuration().getTime();
 
714
                                
 
715
                                //if(previousStart == beatStart){
 
716
                                if(beatStart >= previousStart && (previousStart + this.minDurationTime) > beatStart ){
 
717
                                        // add beat notes to previous
 
718
                                        for(int n = 0;n < beat.countNotes();n++){
 
719
                                                TGNote note = beat.getNote( n );
 
720
                                                previous.addNote( note );
 
721
                                        }
 
722
                                        
 
723
                                        // add beat chord to previous
 
724
                                        if(!previous.isChordBeat() && beat.isChordBeat()){
 
725
                                                previous.setChord( beat.getChord() );
 
726
                                        }
 
727
                                        
 
728
                                        // add beat text to previous
 
729
                                        if(!previous.isTextBeat() && beat.isTextBeat()){
 
730
                                                previous.setText( beat.getText() );
 
731
                                        }
 
732
                                        
 
733
                                        // set the best duration
 
734
                                        if(beatLength > previousLength && (beatStart + beatLength) <= measureEnd){
 
735
                                                beat.getDuration().copy(previous.getDuration());
 
736
                                        }
 
737
                                        
 
738
                                        measure.removeBeat(beat);
 
739
                                        finish = false;
 
740
                                        break;
 
741
                                }
 
742
                                
 
743
                                else if(previousStart < beatStart && (previousStart + previousLength) > beatStart){
 
744
                                        if(beat.isRestBeat()){
 
745
                                                measure.removeBeat(beat);
 
746
                                                finish = false;
 
747
                                                break;
 
748
                                        }
 
749
                                        TGDuration duration = TGDuration.fromTime(this.factory, (beatStart - previousStart) );
 
750
                                        duration.copy( previous.getDuration() );
 
751
                                }
 
752
                        }
 
753
                        if( (beatStart + beatLength) > measureEnd ){
 
754
                                if(beat.isRestBeat()){
 
755
                                        measure.removeBeat(beat);
 
756
                                        finish = false;
 
757
                                        break;
 
758
                                }
 
759
                                TGDuration duration = TGDuration.fromTime(this.factory, (measureEnd - beatStart) );
 
760
                                duration.copy( beat.getDuration() );
 
761
                        }
 
762
                        
 
763
                        previous = beat;
 
764
                }
 
765
                if(!finish){
 
766
                        joinBeats(measure);
 
767
                }
 
768
        }
 
769
        
 
770
        public void orderBeats(TGMeasure measure){
 
771
                for(int i = 0;i < measure.countBeats();i++){
 
772
                        TGBeat minBeat = null;
 
773
                        for(int j = i;j < measure.countBeats();j++){
 
774
                                TGBeat beat = measure.getBeat(j);
 
775
                                if(minBeat == null || beat.getStart() < minBeat.getStart()){
 
776
                                        minBeat = beat;
 
777
                                }
 
778
                        }
 
779
                        measure.moveBeat(i, minBeat);
 
780
                }
 
781
        }
 
782
        
 
783
        private void adjustStrings(TGMeasure measure){
 
784
                for(int i = 0;i < measure.countBeats();i++){
 
785
                        TGBeat beat = measure.getBeat( i );
 
786
                        adjustStrings(beat);
 
787
                }
 
788
        }
 
789
        
 
790
        private void adjustStrings(TGBeat beat){
 
791
                TGTrack track = beat.getMeasure().getTrack();
 
792
                List freeStrings = new ArrayList( track.getStrings() );
 
793
                List notesToRemove = new ArrayList();
 
794
                
 
795
                //ajusto las cuerdas
 
796
                Iterator it = beat.getNotes().iterator();
 
797
                while(it.hasNext()){
 
798
                        TGNote note = (TGNote)it.next();
 
799
                        
 
800
                        int string = getStringForValue(freeStrings,note.getValue());
 
801
                        for(int j = 0;j < freeStrings.size();j ++){
 
802
                                TGString tempString = (TGString)freeStrings.get(j);
 
803
                                if(tempString.getNumber() == string){
 
804
                                        note.setValue(note.getValue() - tempString.getValue());
 
805
                                        note.setString(tempString.getNumber());
 
806
                                        freeStrings.remove(j);
 
807
                                        break;
 
808
                                }
 
809
                        }
 
810
                        
 
811
                        //Cannot have more notes on same string 
 
812
                        if(note.getString() < 1){
 
813
                                notesToRemove.add( note );
 
814
                        }
 
815
                }
 
816
                
 
817
                // Remove notes
 
818
                while( notesToRemove.size() > 0 ){
 
819
                        beat.removeNote( (TGNote)notesToRemove.get( 0 ) );
 
820
                        notesToRemove.remove( 0 );
 
821
                }
 
822
        }
 
823
        
 
824
        private int getStringForValue(List strings,int value){
 
825
                int minFret = -1;
 
826
                int stringForValue = 0;
 
827
                for(int i = 0;i < strings.size();i++){
 
828
                        TGString string = (TGString)strings.get(i);
 
829
                        int fret = value - string.getValue();
 
830
                        if(minFret < 0 || (fret >= 0 && fret < minFret)){
 
831
                                stringForValue = string.getNumber();
 
832
                                minFret = fret;
 
833
                        }
 
834
                }
 
835
                return stringForValue;
 
836
        }
 
837
}
 
 
b'\\ No newline at end of file'