1 package fi.jyu.mit.Music;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.sound.midi.InvalidMidiDataException;
7 import javax.sound.midi.MidiEvent;
8 import javax.sound.midi.MidiSystem;
9 import javax.sound.midi.MidiUnavailableException;
10 import javax.sound.midi.Sequence;
11 import javax.sound.midi.Sequencer;
12 import javax.sound.midi.ShortMessage;
13 import javax.sound.midi.Track;
14
15
57 public class BufferedMidiPlayer2 extends MidiPlayer implements BasicMidiPlayer {
58
59
60
63 private List<NoteTrack> tracks;
64
65 private Sequencer sequencer = null;
66
67 public BufferedMidiPlayer2() {
68 tracks = new ArrayList<NoteTrack>();
69 tracks.add(new NoteTrack());
70 }
71
72
73 public BufferedMidiPlayer2(int channel) {
74 this();
75 selectChannel(channel);
76 }
77
78
79
84 public List<Note>getCopyOfNotes(int index) {
85 return getTrack(index).getCopyOfNotes();
86 }
87
88
93 public List<Note>getNotes(int index) {
94 return getTrack(index).getNotes();
95 }
96
97
100 public void midiSoundNote(int note, int length, int velocity) {
101 tracks.get(0).add(new Note(note, length, velocity));
102 }
103
104 @Override
105 protected void rest(final int barLength) {
106 tracks.get(0).add(new Note.Delay(barLength));
107 }
108
109
110
114 public void runAsync() {
115 long mul = 1;
116 try {
117 Sequence song = new Sequence(0, 4 * 120 ); Track track = song.createTrack();
119 for (int channel = 0; channel < tracks.size(); channel++) {
120 NoteTrack nt = tracks.get(channel);
121 if (nt == null) continue;
122 if ( nt.isMuted() ) continue;
123 long tick = nt.getStartTime()*mul;
124 ShortMessage msgInst = new ShortMessage();
125 msgInst.setMessage(ShortMessage.PROGRAM_CHANGE, channel, nt.getInstrument() - 1, 0);
126 track.add(new MidiEvent(msgInst, tick));
127 while (!nt.isEmpty()) {
128 Note n = nt.remove(0);
129 if (n.isDelay()) {
130 tick += mul * n.getLength();
131 message("Tauko " + n.message());
132 } else {
133 try {
134 ShortMessage msgOn = new ShortMessage();
135 msgOn.setMessage(ShortMessage.NOTE_ON, channel, n.getNote(), n.getVelocity());
136 track.add(new MidiEvent(msgOn, tick));
137 message("Soitin nuotin " + n.message());
138 tick += mul * n.getLength();
139 ShortMessage msgOff = new ShortMessage();
140 msgOff.setMessage(ShortMessage.NOTE_OFF, channel, n.getNote(), n.getVelocity());
141 track.add(new MidiEvent(msgOff, tick));
142 } catch (InvalidMidiDataException e) {
143 }
144 }
145
146 }
147 }
148 sequencer = MidiSystem.getSequencer();
149 sequencer.open();
150 sequencer.setSequence(song);
151
152 if ( isVerbose() ) printSequence(song);
153
154 sequencer.start();
156 } catch (InvalidMidiDataException e) {
157 error("Virhe luettaessa MIDI-dataa! Annoithan MIDI-tiedoston? (.mid)");
158 } catch (MidiUnavailableException e) {
159 error("MIDI-soitinta ei voida alustaa.");
160 }
161
162 }
163
164
165
168 public void stop() {
169 if ( sequencer != null && sequencer.isRunning() ) {
170 sequencer.stop();
171 }
172 sequencer.close();
173 sequencer = null;
174 }
175
176
177
180 public void run() {
181 runAsync();
182 while ( sequencer.isRunning() ) {
183 try {
184 Thread.sleep(200);
185 } catch (InterruptedException e) {
186 }
187 }
188 stop();
189 }
190
191
192
196 public void setInstrument(final int instrument) {
197 setInstrument(0, instrument);
198 }
199
200
205 public void setInstrument(final int index, final int instrument) {
206 super.setInstrument(instrument);
207 getTrack(index).setInstrument(instrument);
208 }
209
210
211
216 public NoteTrack getTrack(int index) {
217 NoteTrack nt;
218 if ( index < 0 ) return tracks.get(0);
219 if ( index < tracks.size() ) {
220 nt = tracks.get(index);
221 if ( nt != null ) return nt;
222 nt = new NoteTrack();
223 tracks.set(index,nt);
224 return nt;
225 }
226 while ( index >= tracks.size() ) tracks.add(null);
227 nt = new NoteTrack();
228 tracks.set(index,nt);
229 return nt;
230 }
231
232
233
238
239 public void play(int index, final List<Note> notes) {
240 for (Note n : notes) {
241 getTrack(index).add(n);
242 }
243 }
244
245
249 @Override
250 public void play(final List<Note> notes) {
251 play(0,notes);
252 }
253
254
255
256
263 public void play(int index,final String sequence, final double length, final int octave, final int velocity) {
264 play(index, getNotes(sequence, length, octave, velocity));
265 }
266
267 public void play(int index,final String sequence, final double length, final int octave) {
268 play(index,sequence, length, octave, getVelocity());
269 }
270
271 public void play(int index,final String sequence, final double length) {
272 play(index,sequence, length, 4, getVelocity());
273 }
274
275 public void play(int index,final String sequence) {
276 play(index,sequence, 0.25, 4, getVelocity());
277 }
278
279
280
285 public void mute(int index,boolean muted) {
286 getTrack(index).mute(muted);
287 }
288
289
293 public boolean isMuted(int index) {
294 return getTrack(index).isMuted();
295 }
296
297
302 public int getCurrentTime(int index) {
303 return getTrack(index).getCurrentTime();
304 }
305
306
307
314 public void setStartTime(int index, int startTime) {
315 getTrack(index).setStartTime(startTime);
316 }
317
318
319
326 public void sync(int dest, int source) {
327 int sourceTime = getCurrentTime(source);
328 int destTime = getCurrentTime(dest);
329
330 int dt = sourceTime - destTime;
331
332 if ( dt > 0 ) getTrack(dest).add(new Note.Delay(dt));
333 if ( dt < 0 ) getTrack(source).add(new Note.Delay(dt));
334 }
335
336 }
337