Esempio n. 1
0
  public void PlayMidiFile(String name, String filename) {
    Sequencer seq = null;
    Transmitter seqTrans = null;
    Synthesizer synth;
    Receiver synthRcvr = null;
    File midiFile = null;

    try {
      seq = MidiSystem.getSequencer();
      seqTrans = seq.getTransmitter();
      synth = MidiSystem.getSynthesizer();
      synthRcvr = synth.getReceiver();
      midiFile = new File(filename);

      if (seq == null) {
        Debug.showMessage("MidiCSD::PlayMidiFile: Sequencer nicht gefunden!");
      } else {
        seq.open();

        seqTrans.setReceiver(synthRcvr);

        Sequence mySeq;
        mySeq = MidiSystem.getSequence(midiFile);

        new Player(name, seq, mySeq, synth, m_playing).start();
      }
    } catch (MidiUnavailableException e) {
      Debug.showException(e, "MidiCSD::PlayMidiFile: MidiUnavailable" + e.getMessage());
    } catch (InvalidMidiDataException e) {
      Debug.showException(e, "MidiCSD::PlayMidiFile: InvalidMidiDataException" + e.getMessage());
    } catch (IOException e) {
      Debug.showException(e, "MidiCSD::PlayMidiFile:IOException (fn:" + filename + ")");
    }
  }
Esempio n. 2
0
  public void playSequence() {

    // Check if sequencer is stopped
    sequencer.addMetaEventListener(
        new MetaEventListener() {
          public void meta(MetaMessage m) {
            // A message of this type is automatically sent
            // when we reach the end of the track
            if (m.getType() == 47) {
              sequencer.setTempoInBPM(tempo);
              // start  the song at the last position
              sequencerFrame.doa = sequencerFrame.conway.nextStep();
              parseSequence(sequencerFrame.doa);
              sequencerFrame.refresh();

              sequencer.start();
            }
          }
        });
    // first start
    try {
      sequencer.setSequence(sequence);
      sequencer.start();

    } catch (InvalidMidiDataException e) {
      e.printStackTrace();
    }
  }
Esempio n. 3
0
  public Sequencer(int instrument, int tempo) {
    // Set up initial settings for the sequencer
    this.instrument = instrument;
    this.tempo = tempo;
    Synthesizer synth;
    ticks = 0;
    velocity = 64; // Mid volume

    try {
      // Setup values to create sequencer
      sequence = new Sequence(Sequence.PPQ, 16);
      sequencer = MidiSystem.getSequencer();
      sequencer.open();
      synth = MidiSystem.getSynthesizer();
      synth.open();
      sequencer.getTransmitter().setReceiver(synth.getReceiver());
      sequencer.setTempoInBPM(tempo);
      track = sequence.createTrack();

    } catch (InvalidMidiDataException e) {
      e.printStackTrace();
    } catch (MidiUnavailableException e) {
      e.printStackTrace();
    }
  }
Esempio n. 4
0
 private void fadeout(PlayTask th, int quarterNotes) {
   int off = 0;
   float subst = 1f / (quarterNotes * 32f);
   synchronized (th.playQueue) {
     Iterator<MidimsgHolder> i = th.playQueue.iterator();
     MidimsgHolder last = null;
     for (float factor = 1f; i.hasNext(); ) {
       MidimsgHolder d = i.next();
       if (d.msg != null) {
         byte[] m = d.msg.getMessage();
         if ((m[0] & 0xFF) >> 4 == 0x09) {
           float fv = (float) (m[2] & 0xFF) * factor;
           m[2] = (byte) fv;
           ShortMessage m2 = new ShortMessage();
           try {
             m2.setMessage(NOTE_ON, m[0] & 0x0F, (int) (m[1] & 0xFF), (int) (m[2] & 0xFF));
             d.msg = m2;
           } catch (InvalidMidiDataException ex) {
             ex.printStackTrace();
           }
         }
       }
       if (last != null) factor -= (d.offset - last.offset) * subst;
       if (factor < 0f) factor = 0f;
       last = d;
     }
   }
 }
Esempio n. 5
0
  private void loadSoundBank(File soundbankFile) {

    try {

      synthesizer.close();
      Soundbank sb = MidiSystem.getSoundbank(soundbankFile);
      synthesizer = MidiSystem.getSynthesizer();
      synthesizer.open();

      System.out.println("soundbank added: " + sb);

      if (sb != null) {
        System.out.println("soundbank supported: " + synthesizer.isSoundbankSupported(sb));
        boolean bInstrumentsLoaded = synthesizer.loadAllInstruments(sb);
        System.out.println("Instruments loaded: " + bInstrumentsLoaded);
      }

    } catch (MidiUnavailableException e) {
      e.printStackTrace();
    } catch (InvalidMidiDataException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
Esempio n. 6
0
 /**
  * Shows an edit midi event dialog.
  *
  * @param event The events to be edited.
  * @return <code>true</code> if the dialog has been shown.
  */
 public static boolean showEditShortMessageEventDialog(
     MidiEvent event, TrackProxy track, MidiDescriptor midiDescriptor) {
   MidiEditPanel mep =
       new MidiEditPanel(
           track,
           event,
           SgEngine.getInstance().getResourceBundle().getString("midi.event.edit.event"));
   Object[] message = new Object[] {mep};
   int option =
       JOptionPane.showConfirmDialog(
           getMainFrame(),
           message,
           SgEngine.getInstance().getResourceBundle().getString("midi.event.edit.title"),
           JOptionPane.OK_CANCEL_OPTION,
           JOptionPane.PLAIN_MESSAGE,
           null);
   if (option == JOptionPane.OK_OPTION && mep.hasChanged()) {
     try {
       // create change edit and perform changes
       Object changeObj = new Object();
       ChangeEventsEdit edit =
           new ChangeEventsEdit(track, new MidiEvent[] {event}, midiDescriptor, null, changeObj);
       mep.applyChanges(changeObj);
       edit.perform();
       midiDescriptor.getUndoManager().addEdit(edit);
     } catch (InvalidMidiDataException imdex) {
       JOptionPane.showMessageDialog(
           getMainFrame(),
           imdex.getMessage(),
           SgEngine.getInstance().getResourceBundle().getString("error.invalidMidiData"),
           JOptionPane.ERROR_MESSAGE);
     }
   }
   return true;
 }
Esempio n. 7
0
  /*
   * Uses the sequencer to play a Midi sequence from a .mid file
   * or a .txt file containing a JFugue string.
   */
  public void playMidiFile(String filePath) {

    try {

      if (filePath.equals("")) {
        // launch a file chooser (just for testing)
        final JFileChooser fc = new JFileChooser();
        int returnVal = fc.showOpenDialog(app.getMainComponent());
        if (returnVal == JFileChooser.APPROVE_OPTION) {
          filePath = fc.getSelectedFile().getAbsolutePath();
        }
      }

      String ext = filePath.substring(filePath.lastIndexOf(".") + 1);
      if (ext.equals("mid")) {
        // Load new sequence from .mid file
        tickPosition = 0;
        sequence = MidiSystem.getSequence(new File(filePath));
        playSequence(sequence, tickPosition);
      } else if (ext.equals("txt")) {
        playJFugueFromFile(new File(filePath));
      } else if (ext.equals("gm")) {
        loadSoundBank(new File(filePath));
      }

    } catch (IOException e) {
      e.printStackTrace();
    } catch (InvalidMidiDataException e) {
      e.printStackTrace();
    }
  }
Esempio n. 8
0
 /**
  * Constructor. It breaks a Song into its MidiEvent components, and adds them together in order to
  * create a MIDI file.
  *
  * @param song The song to export
  */
 public MidiExporter() {
   // Create the Sequence that will contain everything
   try {
     sequence = new Sequence(Sequence.PPQ, 2);
   } catch (InvalidMidiDataException ex) {
     ex.printStackTrace();
     System.exit(1);
   }
 }
Esempio n. 9
0
 /**
  * Plays a sequence, optionally looping. This method returns immediately. The sequence is not
  * played if it is invalid.
  */
 public void play(Sequence sequence, boolean loop) {
   if (sequencer != null && sequence != null && sequencer.isOpen()) {
     try {
       sequencer.setSequence(sequence);
       sequencer.start();
       this.loop = loop;
     } catch (InvalidMidiDataException ex) {
       ex.printStackTrace();
     }
   }
 }
Esempio n. 10
0
 public static MidiEvent createEvent(int command, int channel, int one, int two, long tick) {
   MidiEvent midiEvent = null;
   try {
     ShortMessage message = new ShortMessage();
     message.setMessage(command, channel, one, two);
     midiEvent = new MidiEvent(message, tick);
   } catch (InvalidMidiDataException e) {
     e.printStackTrace();
   }
   return midiEvent;
 }
Esempio n. 11
0
 /**
  * Send a NOTE OFF message on this output.
  *
  * @param channel Channel on which to send the message
  * @param note Note pitch
  * @param velocity Note velocity
  * @return 1 on success, 0 on error
  */
 public int sendNoteOff(int channel, int note, int velocity) {
   ShortMessage msg = new ShortMessage();
   try {
     msg.setMessage(MidiEvent.NOTE_OFF, channel, note, velocity);
     receiver.send(msg, -1);
     return 1;
   } catch (InvalidMidiDataException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
     return 0;
   }
 }
Esempio n. 12
0
 /**
  * Send a SYSEX MIDI message on this output
  *
  * @param msg Bytes of the sysex message, have to contain 0xF0 at the beginning and 0xF7 at the
  *     end
  * @return 1 on success, 0 on error
  */
 public int sendSysex(byte[] msg) {
   javax.sound.midi.SysexMessage msg2 = new javax.sound.midi.SysexMessage();
   try {
     msg2.setMessage(msg, msg.length);
     receiver.send(msg2, 0);
     return 1;
   } catch (InvalidMidiDataException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
     return 0;
   }
 }
Esempio n. 13
0
 /**
  * Send a Program Change on this output
  *
  * @param channel Channel on which to send the message
  * @param value Program Change value
  * @return 1 on success, 0 on error
  */
 public int sendProgramChange(int value) {
   ShortMessage msg = new ShortMessage();
   try {
     msg.setMessage(MidiEvent.PROGRAM_CHANGE, value, -1);
     receiver.send(msg, -1);
     return 1;
   } catch (InvalidMidiDataException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
     return 0;
   }
 }
Esempio n. 14
0
 /**
  * Send a Controller change message on this output.
  *
  * @param channel Channel on which to send the message
  * @param cc Controller Change number
  * @param value Controller Change value
  * @return 1 on success, 0 on error
  */
 public int sendController(int channel, int cc, int value) {
   ShortMessage msg = new ShortMessage();
   try {
     msg.setMessage(MidiEvent.CONTROL_CHANGE, channel, cc, value);
     receiver.send(msg, -1);
     return 1;
   } catch (InvalidMidiDataException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
     return 0;
   }
 }
Esempio n. 15
0
 // mergePlayEmptyTest(): m1 and/or m2 empty
 @Test
 public void mergePlayEmptyTest() {
   Merge a = new Merge(new Rest(0), new Rest(0));
   try {
     SequencePlayer player = new SequencePlayer(140, 12);
     a.play(player, 0);
     assertEquals("Meta event: END_OF_TRACK Tick: 0\n", player.toString());
   } catch (MidiUnavailableException mue) {
     mue.printStackTrace();
   } catch (InvalidMidiDataException imde) {
     imde.printStackTrace();
   }
 }
Esempio n. 16
0
  /** Carrega a seqüência do sistema de arquivos. Retorna null se um erro ocorrer. */
  public Sequence getSequence(String name) {

    String filename = "/recursos/sons/" + name;
    try {
      return MidiSystem.getSequence(getClass().getResource((filename)));
    } catch (InvalidMidiDataException ex) {
      ex.printStackTrace();
      return null;
    } catch (IOException ex) {
      ex.printStackTrace();
      return null;
    }
  }
Esempio n. 17
0
 private void tune(final Receiver recv) {
   try {
     if (rebasedTuning != null) {
       for (int i = 0; i < 16; i++) {
         MidiUtils.sendTunings(recv, i, 0, "african", rebasedTuning);
         MidiUtils.sendTuningChange(recv, i, 0);
       }
     }
   } catch (final IOException e) {
     LOG.log(Level.SEVERE, e.getMessage(), e);
   } catch (final InvalidMidiDataException e) {
     LOG.log(Level.SEVERE, e.getMessage(), e);
   }
 }
Esempio n. 18
0
    void init_midi(LContext lcontext) {
	if (!midiSynthInitialized) {
	    midiSynthInitialized = true;
	    try {
		midiSynth = MidiSystem.getSynthesizer();
		midiSynth.open();
		if (midiSynth.getDefaultSoundbank() == null) {
		    ((LContext) lcontext).canvas.setMessage
			("Reading sound bank from server. Please wait...");
		    if (lcontext != null) {
			/* empty */
		    }
		    URL url = new URL(((LContext) lcontext).codeBase
				      + "soundbank.gm");
		    Soundbank soundbank = MidiSystem.getSoundbank(url);
		    if (soundbank != null) {
			midiSynth.loadAllInstruments(soundbank);
			((LContext) lcontext).canvas.setMessage("");
		    } else {
			midiSynth.close();
			midiSynth = null;
		    }
		}
	    } catch (MidiUnavailableException midiunavailableexception) {
		midiunavailableexception.printStackTrace();
		midiSynth = null;
	    } catch (MalformedURLException malformedurlexception) {
		malformedurlexception.printStackTrace();
		midiSynth = null;
	    } catch (InvalidMidiDataException invalidmididataexception) {
		invalidmididataexception.printStackTrace();
		midiSynth = null;
	    } catch (IOException ioexception) {
		ioexception.printStackTrace();
		midiSynth = null;
	    } catch (AccessControlException accesscontrolexception) {
		accesscontrolexception.printStackTrace();
		midiSynth = null;
	    }
	    if (midiSynth != null) {
		MidiChannel[] midichannels = midiSynth.getChannels();
		for (int i = 0; i < midichannels.length; i++) {
		    if (midichannels[i] != null)
			midichannels[i].programChange(0);
		}
	    } else
		((LContext) lcontext).canvas.setMessage
		    ("No soundbank; note & drum commands disabled.");
	}
    }
Esempio n. 19
0
  /**
   * Create the MidiEvent for a note, given the data.
   *
   * @param command The command value for the ShortMessage
   * @param note The MIDI value for the note to be played
   * @param eventTime When this event should occur
   * @param velocity The velocity of this note
   * @return The MidiEvent for the note
   */
  private MidiEvent createNoteEvent(int command, int note, int eventTime, int velocity) {
    // Create the message and set its parameters to the ones given.
    ShortMessage message = new ShortMessage();
    try {
      message.setMessage(command, 0, note, velocity);
    } catch (InvalidMidiDataException ex) {
      // Something went wrong.
      ex.printStackTrace();
      System.exit(1);
    }

    // Create the MidiEvent and return it.
    return new MidiEvent(message, eventTime);
  }
Esempio n. 20
0
 // musicPlayLargeCaseTest(): row row row your boat
 @Test
 public void musicPlayLargeCaseTest() {
   try {
     SequencePlayer player = new SequencePlayer(140, 12);
     rowRowRowYourBoat.play(player, .125);
     player.play();
     Thread.sleep(10000);
   } catch (MidiUnavailableException mue) {
     mue.printStackTrace();
   } catch (InvalidMidiDataException imde) {
     imde.printStackTrace();
   } catch (InterruptedException ie) {
     ie.printStackTrace();
   }
 }
Esempio n. 21
0
 public void outputFirstEvents() {
   if (notes.get(currentNote).getTime() == 0) {
     Event currentEvent = notes.get(currentNote);
     for (int note : currentEvent.getAllNotes()) {
       try {
         MidiMessage message = new ShortMessage(ShortMessage.NOTE_ON, 0, note, 97);
         receiver.send(message, System.nanoTime());
       } catch (InvalidMidiDataException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
       }
     }
     currentNote++;
   }
 }
Esempio n. 22
0
 /** Loads a sequence from an input stream. Returns null if an error occurs. */
 public Sequence getSequence(InputStream is) {
   try {
     if (!is.markSupported()) {
       is = new BufferedInputStream(is);
     }
     Sequence s = MidiSystem.getSequence(is);
     is.close();
     return s;
   } catch (InvalidMidiDataException ex) {
     ex.printStackTrace();
     return null;
   } catch (IOException ex) {
     ex.printStackTrace();
     return null;
   }
 }
  public NoteIndexMessage(int indexInScore) {
    // System.out.println("new NoteIndexMessage(" + indexInScore +")");
    // FF 7F <len> <id> <data>  Sequencer-Specific Meta-event
    // m_pos = pos;
    byte[] buffer = new byte[3];

    buffer[0] = (byte) ((indexInScore & 0x00ff0000) >> 16);
    buffer[1] = (byte) ((indexInScore & 0x0000ff00) >> 8);
    buffer[2] = (byte) (indexInScore & 0x000000ff);

    try {
      setMessage(MidiMessageType.NOTE_INDEX_MARKER, buffer, buffer.length);
    } catch (InvalidMidiDataException e) {
      e.printStackTrace();
    }
  }
Esempio n. 24
0
  /**
   * Displays a dialog that allows the user to set the number of repeatings of the given MIDI note
   * on the given MIDI track. If the user confirms, an undoable edit is created and added to the
   * provided <code>MidiDescriptor</code>'s <code>UndoManager</code>.
   *
   * @param midiDescriptor The <code>MidiDescriptor</code>.
   * @param track The MIDI track. It is assumed that this track belongs to the given <code>
   *     MidiDescriptor</code>'s <code>SgMidiSequence</code>.
   * @param events The events that describe the note to be repeated. It is assumed that these events
   *     belong to the given MIDI track.
   */
  public static void showRepeatNoteDialog(
      MidiDescriptor midiDescriptor, TrackProxy track, MidiEvent[] events) {
    ResourceBundle rb = SgEngine.getInstance().getResourceBundle();

    SgMidiSequence sequence = null;
    try {
      sequence = midiDescriptor.getSequence();
    } catch (InvalidMidiDataException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    if (sequence == null) {
      return;
    }

    RepeatNotePanel repeatNotePanel = new RepeatNotePanel(1, 4);

    Object[] message =
        new Object[] {
          repeatNotePanel,
        };
    int option =
        JOptionPane.showConfirmDialog(
            getMainFrame(),
            message,
            rb.getString("midi.note.repeat.title"),
            JOptionPane.OK_CANCEL_OPTION,
            JOptionPane.PLAIN_MESSAGE,
            null);
    if (option == JOptionPane.OK_OPTION) {
      int tactCount = repeatNotePanel.getTactCountValue();
      int countPerTact = repeatNotePanel.getCountPerTactValue();
      MidiEvent[] addedEvents = MidiToolkit.repeatEvents(sequence, events, countPerTact, tactCount);

      AddEventsEdit undoableEdit =
          new AddEventsEdit(
              track,
              addedEvents,
              midiDescriptor,
              rb.getString("edit.repeatEventsEdit"),
              UiToolkit.class);
      undoableEdit.perform();
      midiDescriptor.getUndoManager().addEdit(undoableEdit);
    }
  }
Esempio n. 25
0
 // parallelPlayEqualsTest(): m1 = m2
 @Test
 public void parallelPlayEqualsTest() {
   Parallel a = new Parallel(new Note(1, new Pitch('C')), new Note(1, new Pitch('C')));
   try {
     SequencePlayer player = new SequencePlayer(140, 12);
     a.play(player, 0);
     assertEquals(
         "Event: NOTE_ON  Pitch: 60  Tick: 0\n"
             + "Event: NOTE_ON  Pitch: 60  Tick: 0\n"
             + "Event: NOTE_OFF Pitch: 60  Tick: 12\n"
             + "Event: NOTE_OFF Pitch: 60  Tick: 12\n"
             + "Meta event: END_OF_TRACK Tick: 12\n",
         player.toString());
   } catch (MidiUnavailableException mue) {
     mue.printStackTrace();
   } catch (InvalidMidiDataException imde) {
     imde.printStackTrace();
   }
 }
Esempio n. 26
0
 /**
  * Send a Pitch Bend on this output
  *
  * @param channel Channel on which to send the message
  * @param value Program Change value
  * @return 1 on success, 0 on error
  */
 public int sendPitchBend(int channel, int value) {
   ShortMessage msg = new ShortMessage();
   try {
     // int ub = (int)Math.floor( value / 128 );
     // int bb = value-(128*ub);
     int bb = value & 0x7f;
     int ub = value >> 7;
     //			if( ub>0 ){ bb = bb | 0x80; }
     //			System.out.println("ub="+ub);
     //			System.out.println("bb="+bb);
     msg.setMessage(MidiEvent.PITCH_BEND, channel, bb, ub);
     receiver.send(msg, -1);
     return 1;
   } catch (InvalidMidiDataException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
     return 0;
   }
 }
Esempio n. 27
0
 public void playMusic() {
   if (judgetone == true) {
     System.out.print("Make Cheerful Song.\r\n");
     try {
       sequence = new Sequence(Sequence.PPQ, 24, 3);
       MelodyMaker.setCheerfulMelody(sequence, length, velocity);
       AccompanimentMaker.makeCheerfulAccompaniment(sequence, length, velocity);
       sequencer = MidiSystem.getSequencer();
       sequencer.open();
       sequencer.setSequence(sequence);
       sequencer.start();
       while (sequencer.isRunning()) Thread.sleep(100);
     } catch (InterruptedException e) {
       e.printStackTrace();
     } catch (MidiUnavailableException e) {
       e.printStackTrace();
     } catch (InvalidMidiDataException e) {
       e.printStackTrace();
     } finally {
       if (sequencer != null && sequencer.isOpen()) sequencer.close();
     }
   } else if (judgetone == false) {
     System.out.print("Make Gloomy Song.\r\n");
     try {
       sequence = new Sequence(Sequence.PPQ, 24, 3);
       MelodyMaker.setGloomyMelody(sequence, length, velocity);
       AccompanimentMaker.makeGloomyAccompaniment(sequence, length, velocity);
       sequencer = MidiSystem.getSequencer();
       sequencer.open();
       sequencer.setSequence(sequence);
       sequencer.start();
       while (sequencer.isRunning()) Thread.sleep(100);
     } catch (InterruptedException e) {
       e.printStackTrace();
     } catch (MidiUnavailableException e) {
       e.printStackTrace();
     } catch (InvalidMidiDataException e) {
       e.printStackTrace();
     } finally {
       if (sequencer != null && sequencer.isOpen()) sequencer.close();
     }
   }
 }
Esempio n. 28
0
 // chordPlayDifferentDurationsTest(): m1.duration != m2.duration
 @Test
 public void chordPlayDifferentDurationsTest() {
   Chord a = new Chord(new Note(1, new Pitch('D')), new Note(2, new Pitch('C')));
   try {
     SequencePlayer player = new SequencePlayer(140, 12);
     a.play(player, 0);
     assertEquals(
         "Event: NOTE_ON  Pitch: 62  Tick: 0\n"
             + "Event: NOTE_ON  Pitch: 60  Tick: 0\n"
             + "Event: NOTE_OFF Pitch: 62  Tick: 12\n"
             + "Event: NOTE_OFF Pitch: 60  Tick: 24\n"
             + "Meta event: END_OF_TRACK Tick: 24\n",
         player.toString());
   } catch (MidiUnavailableException mue) {
     mue.printStackTrace();
   } catch (InvalidMidiDataException imde) {
     imde.printStackTrace();
   }
 }
Esempio n. 29
0
  private void sendIfReady() {
    // send event if ready
    while (ready()) {
      Event currentEvent = notes.get(currentNote);
      for (int note : currentEvent.getAllNotes()) {
        try {
          MidiMessage message = new ShortMessage(ShortMessage.NOTE_ON, 0, note, 97);
          receiver.send(message, System.nanoTime());
        } catch (InvalidMidiDataException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
      currentNote++;
    }

    if (currentNote >= notes.size()) {
      done = true;
    }
  }
Esempio n. 30
0
 // notePlayTest(): covers all partitions
 @Test
 public void notePlayTest() {
   Note shortNote = new Note(.5, new Pitch('A'));
   Note highNote = new Note(20, new Pitch('A')).transpose(20);
   try {
     SequencePlayer player = new SequencePlayer(140, 12);
     shortNote.play(player, 0);
     highNote.play(player, .5);
     assertEquals(
         "Event: NOTE_ON  Pitch: 69  Tick: 0\n"
             + "Event: NOTE_OFF Pitch: 69  Tick: 6\n"
             + "Event: NOTE_ON  Pitch: 89  Tick: 6\n"
             + "Event: NOTE_OFF Pitch: 89  Tick: 246\n"
             + "Meta event: END_OF_TRACK Tick: 246\n",
         player.toString());
   } catch (MidiUnavailableException mue) {
     mue.printStackTrace();
   } catch (InvalidMidiDataException imde) {
     imde.printStackTrace();
   }
 }