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