m@0
|
1 /*=============================================================================
|
m@0
|
2 * File: MidiPlayer.java
|
m@0
|
3 * Author: Marcus Pearce <m.pearce@gold.ac.uk>
|
m@0
|
4 * Created: <2007-02-14 12:13:56 marcusp>
|
marcus@16
|
5 * Time-stamp: <2011-11-15 16:52:06 marcusp>
|
m@0
|
6 *=============================================================================
|
m@0
|
7 */
|
m@0
|
8
|
m@0
|
9 /*
|
m@0
|
10 * Based on:
|
m@0
|
11 * http://www.jsresources.org/examples/SimpleMidiPlayer.html
|
m@0
|
12 * http://www.jsresources.org/examples/DumpSequence.html
|
m@0
|
13 */
|
m@0
|
14
|
m@0
|
15 import java.io.File;
|
m@0
|
16 import java.io.IOException;
|
m@0
|
17 import java.util.ArrayList;
|
m@0
|
18
|
m@0
|
19 import javax.sound.midi.MidiSystem;
|
m@0
|
20 import javax.sound.midi.MidiDevice;
|
m@0
|
21 import javax.sound.midi.InvalidMidiDataException;
|
m@0
|
22 import javax.sound.midi.MidiUnavailableException;
|
m@0
|
23 import javax.sound.midi.MetaEventListener;
|
m@0
|
24 import javax.sound.midi.Sequence;
|
m@0
|
25 import javax.sound.midi.Sequencer;
|
m@0
|
26 import javax.sound.midi.Synthesizer;
|
m@0
|
27 import javax.sound.midi.MidiChannel;
|
m@0
|
28 import javax.sound.midi.Receiver;
|
m@0
|
29 import javax.sound.midi.Transmitter;
|
m@0
|
30 import javax.sound.midi.Track;
|
m@0
|
31 import javax.sound.midi.MidiEvent;
|
m@0
|
32 import javax.sound.midi.MidiMessage;
|
m@0
|
33 import javax.sound.midi.ShortMessage;
|
m@0
|
34 import javax.sound.midi.MetaMessage;
|
m@0
|
35 import javax.sound.midi.SysexMessage;
|
m@0
|
36 import javax.sound.midi.MetaMessage;
|
JShulver@22
|
37 import java.util.Arrays;
|
jeremy@24
|
38 import java.util.Iterator;
|
jeremy@24
|
39
|
jeremy@24
|
40
|
m@0
|
41 public class MidiPlayer {
|
m@0
|
42
|
m@0
|
43 /* variables */
|
m@0
|
44 private Sequencer sequencer = null;
|
m@0
|
45 private Synthesizer synthesizer = null;
|
m@0
|
46 private Sequence sequence = null;
|
jeremy@24
|
47 private ArrayList<Long> onsets, offsets = null;
|
jeremy@24
|
48 private ArrayList<Integer> pitches, velocities = null;
|
m@0
|
49 private int midiDevice = 0; /* 4 for usb midi device */
|
jeremy@24
|
50 private boolean debug;
|
m@0
|
51
|
m@0
|
52 /* accessors */
|
jeremy@24
|
53 public Sequencer getSequencer() { return sequencer; }
|
m@0
|
54
|
jeremy@24
|
55 /* Constructors */
|
jeremy@24
|
56 public MidiPlayer(String path, int deviceNumber, boolean d) {
|
m@0
|
57 File midiFile = new File(path);
|
m@1
|
58 midiDevice = deviceNumber;
|
jeremy@24
|
59 debug = d;
|
m@0
|
60
|
m@0
|
61 // Get sequence
|
m@0
|
62 try { sequence = MidiSystem.getSequence(midiFile); }
|
m@0
|
63 catch (InvalidMidiDataException e) {
|
m@0
|
64 e.printStackTrace();
|
m@0
|
65 System.exit(1);
|
m@0
|
66 }
|
m@0
|
67 catch (IOException e) {
|
m@0
|
68 e.printStackTrace();
|
m@0
|
69 System.exit(1);
|
m@0
|
70 }
|
m@0
|
71 // Get sequencer
|
m@0
|
72 try { sequencer = MidiSystem.getSequencer(); }
|
m@0
|
73 catch (MidiUnavailableException e) {
|
m@0
|
74 e.printStackTrace();
|
m@0
|
75 System.exit(1);
|
m@0
|
76 }
|
m@0
|
77 //sequencer.setTempoInBPM(bpm);
|
m@0
|
78 // Workaround bug in JDK
|
m@0
|
79 // sequencer.addMetaEventListener(new MetaEventListener() {
|
m@0
|
80 // public void meta(MetaMessage event) {
|
m@0
|
81 // if (event.getType() == 47) {
|
m@0
|
82 // sequencer.close();
|
m@0
|
83 // if (synthesizer != null) {
|
m@0
|
84 // synthesizer.close();
|
m@0
|
85 // }
|
m@0
|
86 // }
|
m@0
|
87 // }
|
m@0
|
88 // });
|
m@0
|
89 // Open sequencer
|
m@0
|
90 try { sequencer.open(); }
|
m@0
|
91 catch (MidiUnavailableException e) {
|
m@0
|
92 e.printStackTrace();
|
m@0
|
93 System.exit(1);
|
m@0
|
94 }
|
m@0
|
95 // Assign sequence to sequencer
|
m@0
|
96 try { sequencer.setSequence(sequence); }
|
m@0
|
97 catch (InvalidMidiDataException e) {
|
m@0
|
98 e.printStackTrace();
|
m@0
|
99 System.exit(1);
|
m@0
|
100 }
|
m@0
|
101 // Set up MIDI output for sequence
|
m@0
|
102 try {
|
m@0
|
103 MidiDevice.Info msinfo[] = MidiSystem.getMidiDeviceInfo();
|
m@0
|
104 for(int i = 0; i < msinfo.length; i++) {
|
m@0
|
105 MidiDevice.Info m = msinfo[i];
|
m@0
|
106 // System.out.println("Name: " + m.getName() +
|
m@0
|
107 // "; Vendor: " + m.getVendor() +
|
m@0
|
108 // "; Version: " + m.getVersion());
|
m@0
|
109 }
|
m@0
|
110 // synthesizer = MidiSystem.getSynthesizer();
|
m@0
|
111 MidiDevice synth = MidiSystem.getMidiDevice(msinfo[midiDevice]);
|
m@0
|
112
|
m@0
|
113 // Change the patch
|
m@0
|
114 // MidiChannel channels[] = synthesizer.getChannels();
|
m@0
|
115 // for (int i = 0; i < channels.length; i++)
|
m@0
|
116 // channels[i].programChange(65);
|
m@0
|
117
|
m@0
|
118 synth.open();
|
m@0
|
119 Receiver synthReceiver = synth.getReceiver();
|
m@0
|
120 Transmitter seqTransmitter = sequencer.getTransmitter();
|
m@0
|
121 seqTransmitter.setReceiver(synthReceiver);
|
m@0
|
122
|
m@0
|
123 }
|
m@0
|
124 catch (MidiUnavailableException e) {
|
m@0
|
125 e.printStackTrace();
|
m@0
|
126 }
|
m@0
|
127
|
m@0
|
128 // compute data from the MIDI file
|
jeremy@24
|
129
|
jeremy@24
|
130 /*
|
m@0
|
131 onsets = computeOnsets();
|
m@0
|
132 offsets = computeOffsets();
|
m@0
|
133 pitches = computePitches();
|
jeremy@24
|
134 */
|
jeremy@24
|
135 registerEvents();
|
m@0
|
136
|
jeremy@24
|
137 if (debug) {
|
jeremy@24
|
138 String divisionType;
|
jeremy@24
|
139 if (sequence.getDivisionType() == sequence.PPQ)
|
jeremy@24
|
140 divisionType = "ppq";
|
jeremy@24
|
141 else
|
jeremy@24
|
142 divisionType = "smpte";
|
jeremy@24
|
143 System.out.println("division type = " + divisionType +
|
jeremy@24
|
144 "; resolution = " + sequence.getResolution());
|
jeremy@24
|
145 }
|
m@0
|
146 }
|
m@0
|
147
|
m@0
|
148 /* number of microseconds per MIDI tick */
|
m@0
|
149 private double microsecondsPerTick() {
|
m@0
|
150 double seqTickLength = (float)sequence.getTickLength();
|
m@0
|
151 double seqMicrosecondLength = (float)sequence.getMicrosecondLength();
|
m@0
|
152 double microsecondsPerTick = seqMicrosecondLength / seqTickLength;
|
m@0
|
153 //System.out.println("seqTickLength = " + seqTickLength);
|
m@0
|
154 //System.out.println("seqMicrosecondLength = " + seqMicrosecondLength);
|
m@0
|
155 //System.out.println("microsecondsPerTick = " + microsecondsPerTick);
|
m@0
|
156 return microsecondsPerTick;
|
m@0
|
157 }
|
m@0
|
158
|
m@0
|
159 private long ticksToMicroseconds(long tick) {
|
m@0
|
160 double microsecondsPerTick = microsecondsPerTick();
|
m@0
|
161 double seconds = (double)tick * microsecondsPerTick;
|
m@0
|
162
|
m@0
|
163 return (long)(10 * Math.floor(seconds * 0.1));
|
m@0
|
164 }
|
m@0
|
165
|
m@0
|
166 /* compute a list of note onset times (microseconds) */
|
m@0
|
167 private ArrayList computeOnsets() {
|
m@0
|
168 ArrayList ons = new ArrayList();
|
m@0
|
169 Track[] tracks = sequence.getTracks();
|
m@0
|
170
|
m@0
|
171 for (int nTrack = 0; nTrack < tracks.length; nTrack++) {
|
m@0
|
172 Track track = tracks[nTrack];
|
m@0
|
173 for (int nEvent = 0; nEvent < track.size(); nEvent++) {
|
m@0
|
174 MidiEvent event = track.get(nEvent);
|
m@0
|
175 MidiMessage message = event.getMessage();
|
m@0
|
176 if (message instanceof ShortMessage &&
|
m@0
|
177 ((ShortMessage)message).getCommand() == ShortMessage.NOTE_ON) {
|
m@0
|
178 // System.out.println("onset in ticks = " + event.getTick()+
|
m@0
|
179 // "; onset in microseconds = " +
|
m@0
|
180 // ticksToMicroseconds(event.getTick()));
|
JShulver@22
|
181 //if the event does not have a velocity of zero (i.e. switching a note off)
|
JShulver@22
|
182 if(message.getMessage()[2] != 0) {
|
JShulver@22
|
183 ons.add(ticksToMicroseconds(event.getTick())); //THEN we can add the note
|
JShulver@22
|
184 }
|
m@0
|
185 }
|
m@0
|
186 }
|
m@0
|
187 }
|
m@0
|
188 return ons;
|
m@0
|
189 }
|
m@0
|
190
|
m@0
|
191 /* compute a list of note offset times (microseconds) */
|
m@0
|
192 private ArrayList computeOffsets() {
|
m@0
|
193 ArrayList offs = new ArrayList();
|
m@0
|
194 Track[] tracks = sequence.getTracks();
|
m@0
|
195
|
m@0
|
196 for (int nTrack = 0; nTrack < tracks.length; nTrack++) {
|
m@0
|
197 Track track = tracks[nTrack];
|
m@0
|
198 for (int nEvent = 0; nEvent < track.size(); nEvent++) {
|
m@0
|
199 MidiEvent event = track.get(nEvent);
|
m@0
|
200 MidiMessage message = event.getMessage();
|
m@0
|
201 if (message instanceof ShortMessage &&
|
m@0
|
202 ((ShortMessage)message).getCommand() == ShortMessage.NOTE_OFF) {
|
m@0
|
203 //System.out.println("offset in ticks = " + event.getTick()+
|
m@0
|
204 // "; microsecondsPerTick = " + microsecondsPerTick +
|
m@0
|
205 // "; offset in microseconds = " +
|
m@0
|
206 // (float)event.getTick() * microsecondsPerTick);
|
m@0
|
207 offs.add(ticksToMicroseconds(event.getTick()));
|
m@0
|
208 }
|
JShulver@22
|
209 //if we have not found a note off,
|
JShulver@22
|
210 else if (message instanceof ShortMessage
|
JShulver@22
|
211 && ((ShortMessage)message).getCommand() == ShortMessage.NOTE_ON
|
JShulver@22
|
212 && message.getMessage()[2] == 0) { //but it is a note on with a velocity of zero
|
JShulver@22
|
213 offs.add(ticksToMicroseconds(event.getTick())); //add it as an off signal
|
JShulver@22
|
214 }
|
JShulver@22
|
215
|
m@0
|
216 }
|
m@0
|
217 }
|
m@0
|
218 return offs;
|
m@0
|
219 }
|
m@0
|
220
|
m@0
|
221 /* compute a list of note pitches */
|
m@0
|
222 private ArrayList computePitches() {
|
m@0
|
223 ArrayList pit = new ArrayList();
|
m@0
|
224 Track[] tracks = sequence.getTracks();
|
m@0
|
225
|
m@0
|
226 for (int nTrack = 0; nTrack < tracks.length; nTrack++) {
|
m@0
|
227 Track track = tracks[nTrack];
|
m@0
|
228 for (int nEvent = 0; nEvent < track.size(); nEvent++) {
|
m@0
|
229 MidiEvent event = track.get(nEvent);
|
m@0
|
230 MidiMessage message = event.getMessage();
|
m@0
|
231 if (message instanceof ShortMessage &&
|
m@0
|
232 ((ShortMessage)message).getCommand() == ShortMessage.NOTE_ON)
|
m@0
|
233 pit.add(((ShortMessage)message).getData1());
|
m@0
|
234 }
|
m@0
|
235 }
|
m@0
|
236 return pit;
|
m@0
|
237 }
|
m@0
|
238
|
jeremy@24
|
239 /*
|
jeremy@24
|
240 * Simultaneously construct lists of event onsets, offsets and pitches
|
jeremy@24
|
241 */
|
jeremy@24
|
242 private void registerEvents() {
|
jeremy@24
|
243 onsets = new ArrayList<Long>();
|
jeremy@24
|
244 offsets = new ArrayList<Long>();
|
jeremy@24
|
245 pitches = new ArrayList<Integer>();
|
jeremy@24
|
246 velocities = new ArrayList<Integer>();
|
jeremy@24
|
247
|
jeremy@24
|
248 Track[] tracks = sequence.getTracks();
|
jeremy@24
|
249
|
jeremy@24
|
250 // Iterate over MIDI tracks
|
jeremy@24
|
251 for (int i = 0; i < tracks.length; i++) {
|
jeremy@24
|
252 Track track = tracks[i];
|
jeremy@24
|
253 // Iterate over track events
|
jeremy@24
|
254 for (int j = 0; j < track.size(); j++) {
|
jeremy@24
|
255 registerEvent(i, j);
|
jeremy@24
|
256 }
|
jeremy@24
|
257 }
|
jeremy@24
|
258
|
jeremy@24
|
259 if (debug) {
|
jeremy@24
|
260 System.out.println("\nRegistered events...");
|
jeremy@24
|
261 Iterator<Long> oi = onsets.iterator();
|
jeremy@24
|
262 Iterator<Long> fi = offsets.iterator();
|
jeremy@24
|
263 Iterator<Integer> pi = pitches.iterator();
|
jeremy@24
|
264 Iterator<Integer> vi = velocities.iterator();
|
jeremy@24
|
265
|
jeremy@24
|
266 int pos = 1;
|
jeremy@24
|
267 while (oi.hasNext() && fi.hasNext() && pi.hasNext() && vi.hasNext()) {
|
jeremy@24
|
268 System.out.println("Event " + pos + ": onset " + oi.next() + ", offset " + fi.next()
|
jeremy@24
|
269 + ", pitch " + pi.next() + ", velocity " + vi.next());
|
jeremy@24
|
270 pos++;
|
jeremy@24
|
271 }
|
jeremy@24
|
272
|
jeremy@24
|
273 if (oi.hasNext() || fi.hasNext() || pi.hasNext() || vi.hasNext()) {
|
jeremy@24
|
274 System.out.println("Warning: event lists not equal length.");
|
jeremy@24
|
275 }
|
jeremy@24
|
276 }
|
jeremy@24
|
277 }
|
jeremy@24
|
278
|
jeremy@24
|
279 /*
|
jeremy@24
|
280 * Add the given event to the onset, offset and pitch lists.
|
jeremy@24
|
281 */
|
jeremy@24
|
282 private void registerEvent(int trackIndex, int eventIndex) {
|
jeremy@24
|
283
|
jeremy@24
|
284 Track track = sequence.getTracks()[trackIndex];
|
jeremy@24
|
285 MidiEvent event = track.get(eventIndex);
|
jeremy@24
|
286 MidiMessage message = event.getMessage();
|
jeremy@24
|
287
|
jeremy@24
|
288 // Register NOTE_ON events
|
jeremy@24
|
289 if (message instanceof ShortMessage) {
|
jeremy@24
|
290 ShortMessage shortMsg = (ShortMessage) message;
|
jeremy@24
|
291 int velocity = shortMsg.getData2();
|
jeremy@24
|
292
|
jeremy@24
|
293 if (shortMsg.getCommand() == ShortMessage.NOTE_ON && velocity != 0) {
|
jeremy@24
|
294
|
jeremy@24
|
295 long onset = ticksToMicroseconds(event.getTick());
|
jeremy@24
|
296 int pitch = shortMsg.getData1();
|
jeremy@24
|
297 long offset = getOffset(trackIndex, eventIndex, onset, pitch);
|
jeremy@24
|
298
|
jeremy@24
|
299 registerEvent(onset, offset, pitch, velocity);
|
jeremy@24
|
300 }
|
jeremy@24
|
301 }
|
jeremy@24
|
302 }
|
jeremy@24
|
303
|
jeremy@24
|
304 /*
|
jeremy@24
|
305 * Add the event details to the onset, offset and pitch lists,
|
jeremy@24
|
306 * use onset to determine the list position.
|
jeremy@24
|
307 */
|
jeremy@24
|
308 private void registerEvent(long onset, long offset, int pitch, int velocity) {
|
jeremy@24
|
309
|
jeremy@24
|
310 int index = 0;
|
jeremy@24
|
311 boolean inserted = false;
|
jeremy@24
|
312
|
jeremy@24
|
313 while (index < onsets.size()) {
|
jeremy@24
|
314
|
jeremy@24
|
315 if (onsets.get(index) > onset)
|
jeremy@24
|
316 break;
|
jeremy@24
|
317 else
|
jeremy@24
|
318 index++;
|
jeremy@24
|
319 }
|
jeremy@24
|
320
|
jeremy@24
|
321 onsets.add(index, onset);
|
jeremy@24
|
322 offsets.add(index, offset);
|
jeremy@24
|
323 pitches.add(index, pitch);
|
jeremy@24
|
324 velocities.add(index, pitch);
|
jeremy@24
|
325 }
|
jeremy@24
|
326
|
jeremy@24
|
327
|
jeremy@24
|
328
|
jeremy@24
|
329 /*
|
jeremy@24
|
330 * Find the matching NOTE_OFF event *after* the given NOTE_ON event
|
jeremy@24
|
331 * (the <onsetIndex>th event in track <trackNum>)
|
jeremy@24
|
332 */
|
jeremy@24
|
333 private long getOffset(int trackNum, int onsetIndex, long onsetTime, int pitch) {
|
jeremy@24
|
334
|
jeremy@24
|
335 long offset = -1;
|
jeremy@24
|
336 Track track = sequence.getTracks()[trackNum];
|
jeremy@24
|
337
|
jeremy@24
|
338 // Iterate through remaining events looking for NOTE_OFF
|
jeremy@24
|
339 for (int k = onsetIndex + 1; k < track.size(); k++) {
|
jeremy@24
|
340 MidiEvent event = track.get(k);
|
jeremy@24
|
341 MidiMessage message = event.getMessage();
|
jeremy@24
|
342
|
jeremy@24
|
343 if (message instanceof ShortMessage) {
|
jeremy@24
|
344 ShortMessage shortMsg = (ShortMessage) message;
|
jeremy@24
|
345 int command = shortMsg.getCommand();
|
jeremy@24
|
346
|
jeremy@24
|
347 // Check NOTE_OFF message
|
jeremy@24
|
348 if (command == ShortMessage.NOTE_OFF
|
jeremy@24
|
349 || (command == ShortMessage.NOTE_ON && shortMsg.getData2() == 0)) {
|
jeremy@24
|
350 int pitch2 = shortMsg.getData1();
|
jeremy@24
|
351 // If pitches are identical then offset found
|
jeremy@24
|
352 if (pitch == pitch2) {
|
jeremy@24
|
353 offset = ticksToMicroseconds(event.getTick());
|
jeremy@24
|
354 break;
|
jeremy@24
|
355 }
|
jeremy@24
|
356 }
|
jeremy@24
|
357 }
|
jeremy@24
|
358 }
|
jeremy@24
|
359
|
jeremy@24
|
360 if (offset < 0) {
|
jeremy@24
|
361 System.out.println("No NOTE_OFF found for track " + trackNum
|
jeremy@24
|
362 + ", onset " + onsetTime + ", pitch " + pitch);
|
jeremy@24
|
363 }
|
jeremy@24
|
364
|
jeremy@24
|
365 return offset;
|
jeremy@24
|
366 }
|
jeremy@24
|
367
|
jeremy@24
|
368
|
jeremy@24
|
369
|
m@0
|
370 /* return a list of note onset times (milliseconds) */
|
m@0
|
371 public ArrayList getOnsets() { return onsets; }
|
m@0
|
372
|
m@0
|
373 /* return a list of note offset times (milliseconds) */
|
m@0
|
374 public ArrayList getOffsets() { return offsets; }
|
m@0
|
375
|
m@0
|
376 /* return a list of note pitches */
|
m@0
|
377 public ArrayList getPitches() { return pitches; }
|
m@0
|
378
|
m@0
|
379 /* return a list of note durations (microseconds) */
|
m@0
|
380 public ArrayList getDurations() {
|
m@0
|
381 Object[] ons = onsets.toArray();
|
m@0
|
382 Object[] offs = offsets.toArray();
|
m@0
|
383
|
m@0
|
384 ArrayList durations = new ArrayList();
|
m@0
|
385
|
m@0
|
386 for(int i = 0; i < ons.length; i++) {
|
m@0
|
387 durations.add(((Long)offs[i]).longValue() -
|
m@0
|
388 ((Long)ons[i]).longValue());
|
m@0
|
389 }
|
m@0
|
390 return durations;
|
m@0
|
391 }
|
m@0
|
392
|
m@0
|
393 /* return a list of inter-onset intervals (microseconds) */
|
m@0
|
394 public ArrayList getInterOnsetIntervals() {
|
m@0
|
395 Object[] ons = onsets.toArray();
|
m@0
|
396
|
m@0
|
397 ArrayList iois = new ArrayList();
|
m@0
|
398 long firstIOI = 0;
|
m@0
|
399 iois.add(firstIOI); // IOI of first note is zero
|
m@0
|
400
|
m@0
|
401 for(int i = 1; i < ons.length; i++) {
|
m@0
|
402 iois.add(((Long)ons[i]).longValue() -
|
m@0
|
403 ((Long)ons[i-1]).longValue());
|
m@0
|
404 }
|
m@0
|
405 return iois;
|
m@0
|
406 }
|
m@0
|
407
|
m@0
|
408 /* return the length of a rest preceding a note */
|
m@0
|
409 public ArrayList getDeltaST() {
|
m@0
|
410 Object[] durs = getDurations().toArray();
|
m@0
|
411 Object[] iois = getInterOnsetIntervals().toArray();
|
m@0
|
412
|
m@0
|
413 ArrayList deltaST = new ArrayList();
|
m@0
|
414 long firstDeltaST = 0;
|
m@0
|
415 deltaST.add(firstDeltaST); // deltaST of first note is zero
|
m@0
|
416
|
m@0
|
417 for(int i = 1; i < durs.length; i++) {
|
m@0
|
418 deltaST.add(((Long)durs[i-1]).longValue() -
|
m@0
|
419 ((Long)iois[i]).longValue());
|
m@0
|
420 }
|
m@0
|
421 return deltaST;
|
m@0
|
422 }
|
m@0
|
423
|
jeremy@24
|
424 /*
|
jeremy@24
|
425 * Return the tatum of the midi file, i.e. the shortest
|
jeremy@24
|
426 * note duration or positive rest.
|
jeremy@24
|
427 */
|
JShulver@23
|
428 public long getTatum() {
|
JShulver@23
|
429
|
JShulver@23
|
430
|
m@0
|
431 Object[] durs = getDurations().toArray();
|
m@0
|
432 Object[] rests = getDeltaST().toArray();
|
m@0
|
433 long tatum = -1;
|
m@0
|
434
|
jeremy@24
|
435
|
m@0
|
436 for(int i = 0; i < durs.length; i++) {
|
m@0
|
437 long dur = ((Long)durs[i]).longValue();
|
m@0
|
438 long rest = ((Long)rests[i]).longValue();
|
m@0
|
439 long min = dur;
|
jeremy@24
|
440 if (rest > 0)
|
m@0
|
441 min = Math.min(dur, rest);
|
jeremy@24
|
442 if (debug)
|
jeremy@24
|
443 System.out.println("Dur: " + dur + " Rest: " + rest);
|
m@0
|
444 if (tatum < 0)
|
m@0
|
445 tatum = dur;
|
m@0
|
446 else if (min < tatum)
|
m@0
|
447 tatum = min;
|
m@0
|
448 }
|
JShulver@23
|
449 //tatum = sequence.getResolution()*1000;
|
m@0
|
450 return tatum;
|
m@0
|
451 }
|
m@0
|
452
|
m@0
|
453 /* return length of sequence in microseconds */
|
m@0
|
454 public long getLength() {
|
m@0
|
455 return sequence.getMicrosecondLength();
|
m@0
|
456 }
|
m@0
|
457
|
m@0
|
458 /* play the midi file */
|
m@0
|
459 public void play() {
|
marcus@16
|
460 //System.out.println("MidiPlayer.play: run sequencer.start().");
|
m@0
|
461 sequencer.start();
|
m@0
|
462 }
|
m@0
|
463
|
m@0
|
464 public void stop() {
|
m@4
|
465 if (synthesizer != null) {
|
m@4
|
466 synthesizer.close();
|
m@4
|
467 }
|
m@4
|
468 if (sequencer != null) {
|
m@4
|
469 sequencer.close();
|
m@4
|
470 }
|
m@4
|
471 sequencer = null;
|
m@4
|
472 synthesizer = null;
|
m@4
|
473 }
|
m@0
|
474 }
|