Пример #1
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();
    }
  }
Пример #2
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();
    }
  }
Пример #3
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;
     }
   }
 }
Пример #4
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();
    }
  }
Пример #5
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();
    }
  }
Пример #6
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);
   }
 }
Пример #7
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();
     }
   }
 }
Пример #8
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();
     }
   }
 }
Пример #9
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;
 }
Пример #10
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;
   }
 }
Пример #11
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;
   }
 }
Пример #12
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;
   }
 }
Пример #13
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;
   }
 }
Пример #14
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;
    }
  }
Пример #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();
   }
 }
Пример #16
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.");
	}
    }
Пример #17
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);
  }
Пример #18
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++;
   }
 }
Пример #19
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();
   }
 }
Пример #20
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;
   }
 }
Пример #21
0
  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();
    }
  }
Пример #22
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);
    }
  }
Пример #23
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;
   }
 }
Пример #24
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();
   }
 }
Пример #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();
   }
 }
Пример #26
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;
    }
  }
Пример #27
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();
   }
 }
Пример #28
0
  public void parseSequence(boolean[][] grid) {
    ShortMessage on;
    this.grid = grid;
    ShortMessage off;
    int tickLength = 16;
    try {
      ShortMessage sm = new ShortMessage();
      sm.setMessage(ShortMessage.PROGRAM_CHANGE, 0, instrument, 0);
      track.add(new MidiEvent(sm, 0));
      for (boolean[] aGrid : grid) {
        for (int col = 0; col < aGrid.length; col++) {
          if (aGrid[col]) {
            if (other == 1) {
              other = 0;
            } else {
              other = 1;
            }
            off = new ShortMessage();
            off.setMessage(
                ShortMessage.NOTE_OFF,
                0,
                scale[(grid[0].length - col - 1 + other) % scale.length],
                velocity);
            on = new ShortMessage();
            on.setMessage(
                ShortMessage.NOTE_ON,
                0,
                scale[(grid[0].length - col - 1 + other) % scale.length],
                velocity);
            track.add(new MidiEvent(on, ticks));
            track.add(new MidiEvent(off, ticks + tickLength));
          }
        }
        ticks += tickLength;
      }

    } catch (InvalidMidiDataException e) {
      e.printStackTrace();
    }
  }
Пример #29
0
  /*
   * Change the color of the correct pad on both Launchpads
   * It returns boolean to ensure the signal was sent correctly before doing
   * the console output in the above methods (or prints an error if it fails)
   */
  private boolean setColor(int pad, boolean isOn) {
    boolean success = true;

    // Set and send message (which contains the color) to the real Launchpad
    ShortMessage message = new ShortMessage();
    try {
      if (isOn) {
        message.setMessage(144, pad, colorIndexes[colorIndex]);
      } else {
        message.setMessage(144, pad, colorIndexes[OFF]);
      }
    } catch (InvalidMidiDataException e1) {
      e1.printStackTrace();
      success = false;
    }

    // Gets here if Launchpad is not connected
    // TODO: Output error message if Launchpad is connected but this still fails (might be possible)
    try {
      out.getReceiver().send(message, -1);
    } catch (MidiUnavailableException | NullPointerException e) {
      //			e.printStackTrace();
      //			success = false;
    }

    // Send the pad color to the screen
    try {
      if (isOn) {
        launchpad.setColor(pad, colorValues[colorIndex]);
      } else {
        launchpad.setColor(pad, colorValues[OFF]);
      }
    } catch (NullPointerException e) {
      if (isOn) System.out.println("\t*\tError:\t\t<\tPad " + pad + " cannot be set\t\t>");
      success = false;
    }

    return success; // Made it
  }
Пример #30
0
  /**
   * Converts the given tune to a midi sequence.
   *
   * @param tune The tune to be converted.
   * @return The midi sequence of the tune.
   */
  public Sequence toMidiSequence(Tune tune) {
    Sequence sequence = null;
    try {
      if (instrument == null) {
        Synthesizer synth = MidiSystem.getSynthesizer();
        synth.open();
        try {
          setInstrument(synth.getAvailableInstruments()[0]);
        } finally {
          synth.close();
        }
      }
      // Sequence in ticks per quarter note : PPQ = Pulse Per Quarter Note
      // Resolution is expressed in ticks per beat.
      // Last parameter "1" is the number of tracks.
      sequence = new Sequence(Sequence.PPQ, SEQUENCE_RESOLUTION, 1);
      // Set the instrument on channel 0
      ShortMessage sm = new ShortMessage();
      sm.setMessage(ShortMessage.PROGRAM_CHANGE, 0, instrument.getPatch().getProgram(), 0);

      Track track = sequence.createTrack();
      track.add(new MidiEvent(sm, 0));
      // long trackLengthInTicks = track.ticks();
      int lastRepeatOpen = -1;
      int repeatNumber = 1;
      boolean inWrongEnding = false;
      KeySignature tuneKey = null;
      KeySignature currentKey = null;
      Hashtable partsKey = new Hashtable();

      long elapsedTime = 0;
      NoteAbstract[] graceNotes = null;
      Music staff = tune.getMusicForAudioRendition();
      Iterator it = staff.getVoices().iterator();
      while (it.hasNext()) {
        Voice voice = (Voice) it.next();
        int i = 0; // StaffItem iterator
        while (i < voice.size()) {
          if (!inWrongEnding) {
            // ==================================================================== TEMPO
            if (voice.elementAt(i) instanceof abc.notation.Tempo) {
              addTempoEventsFor(
                  track,
                  elapsedTime,
                  getMidiMessagesFor((Tempo) voice.elementAt(i))); // , trackLengthInTicks));
            } else
            /*if (voice.elementAt(i) instanceof abc.notation.PartLabel) {
            	//Imagine... part A in Gmaj, B in Amin
            	//in tune you have K:G, P:A, ... P:B, K:Am
            	//if you have part order ABA, when you return to A
            	//you stay in Amin. This stores the tuneKey when a
            	//new part appear, and restitute it when part is played again
            	abc.notation.PartLabel pl = (abc.notation.PartLabel) voice.elementAt(i);
            	if (partsKey.get(pl.getLabel()+"") == null) {
            		partsKey.put(pl.getLabel()+"", tuneKey);
            	} else {
            		tuneKey = (KeySignature) partsKey.get(pl.getLabel()+"");
            	}
            }
            else*/
            // ==================================================================== KEY SIGNATURE
            if (voice.elementAt(i) instanceof abc.notation.KeySignature) {
              tuneKey = (KeySignature) (voice.elementAt(i));
              currentKey = new KeySignature(tuneKey.getAccidentals());
            } else
            // ==================================================================== NOTE
            // Notes ending ties should be ignored. Already taken into
            // account in getNoteLengthInTicks(Note)
            if (voice.elementAt(i) instanceof abc.notation.Note
                && !((abc.notation.Note) voice.elementAt(i)).isEndingTie()) {

              Note note = (Note) voice.elementAt(i);
              long noteDuration;
              boolean fermata = false;
              Vector decorationNotes = new Vector();
              if (note.hasGeneralGracing() || note.hasDecorations()) {
                Decoration[] d = note.getDecorations();
                for (int j = 0; j < d.length; j++) {
                  switch (d[j].getType()) {
                    case Decoration.FERMATA:
                    case Decoration.FERMATA_INVERTED:
                      fermata = true;
                      break;
                    case Decoration.LOWERMORDENT:
                    case Decoration.UPPERMORDENT:
                    case Decoration.DOUBLE_LOWER_MORDANT:
                    case Decoration.DOUBLE_UPPER_MORDANT:
                    case Decoration.TRILL:
                    case Decoration.TURN: // GRUPETTO_UP
                    case Decoration.TURN_INVERTED: // GRUPETTO_DOWN
                    case Decoration.TURNX:
                    case Decoration.TURNX_INVERTED:
                      Note n = new Note(note.getHeight());
                      n.setAccidental(note.getAccidental(currentKey));
                      Note o =
                          new Interval(Interval.SECOND, Interval.MAJOR, Interval.UPWARD)
                              .calculateSecondNote(n);
                      Note m =
                          new Interval(Interval.SECOND, Interval.MAJOR, Interval.DOWNWARD)
                              .calculateSecondNote(n);
                      // TODO ornament templates: regular, musette, balkan...
                      // n.setStrictDuration(Note.SIXTEENTH);
                      // o.setDuration((short)(Note.EIGHTH+Note.SIXTEENTH));
                      o.setAccidental(Accidental.NONE);
                      m.setAccidental(Accidental.NONE);
                      n.setStrictDuration(Note.THIRTY_SECOND);
                      m.setStrictDuration(Note.THIRTY_SECOND);
                      o.setStrictDuration(Note.THIRTY_SECOND);
                      switch (d[j].getType()) {
                        case Decoration.DOUBLE_LOWER_MORDANT:
                          decorationNotes.add(n);
                          decorationNotes.add(m);
                        case Decoration.LOWERMORDENT:
                          decorationNotes.add(n);
                          decorationNotes.add(m);
                          break;
                        case Decoration.DOUBLE_UPPER_MORDANT:
                        case Decoration.TRILL:
                          decorationNotes.add(n);
                          decorationNotes.add(o);
                        case Decoration.UPPERMORDENT:
                          decorationNotes.add(n);
                          decorationNotes.add(o);
                          break;
                        case Decoration.TURNX_INVERTED:
                        case Decoration.TURN:
                          decorationNotes.add(o);
                          decorationNotes.add(n);
                          decorationNotes.add(m);
                          break;
                        case Decoration.TURNX:
                        case Decoration.TURN_INVERTED:
                          decorationNotes.add(m);
                          decorationNotes.add(n);
                          decorationNotes.add(o);
                      }
                      break;
                  }
                }
                // currently not used
                // future use: playing rolls, slides, etc.
              }
              long graceNotesDuration = 0;
              if (note.hasGracingNotes() || (decorationNotes.size() > 0)) {
                graceNotes = note.getGracingNotes();
                // gracing are eighth note for graphical rendition
                // and because that's it in the parser
                // adapt duration to note length
                int divisor = 1;
                if (note.getStrictDuration() >= Note.HALF) divisor = 1; // grace is an eighth
                else if (note.getStrictDuration() >= Note.QUARTER) divisor = 2; // 16th
                else if (note.getStrictDuration() >= Note.EIGHTH) divisor = 4; // 32nd
                else divisor = 8; // 64th
                if (note.hasGracingNotes()) {
                  for (int j = 0; j < graceNotes.length; j++) {
                    noteDuration = getNoteLengthInTicks(graceNotes[j], staff) / divisor;
                    graceNotesDuration += noteDuration;
                    if (graceNotes[j] instanceof Note)
                      playNote(
                          (Note) graceNotes[j], i, currentKey, elapsedTime, noteDuration, track);
                    else
                      playMultiNote(
                          (MultiNote) graceNotes[j],
                          i,
                          currentKey, /*elapsedTime,*/
                          noteDuration,
                          track,
                          staff);
                    elapsedTime += noteDuration;
                  }
                }
                for (int j = 0; j < decorationNotes.size(); j++) {
                  noteDuration = getNoteLengthInTicks((Note) decorationNotes.elementAt(j), staff);
                  graceNotesDuration += noteDuration;
                  playNote(
                      (Note) decorationNotes.elementAt(j),
                      i,
                      currentKey,
                      elapsedTime,
                      noteDuration,
                      track);
                  elapsedTime += noteDuration;
                }
              }
              // The note duration if the note isn't part of a tuplet.
              noteDuration = getNoteLengthInTicks(note, staff) - graceNotesDuration;
              if (noteDuration <= 0) // in case of too much grace notes
              noteDuration = getNoteLengthInTicks(note, staff);
              if (fermata) noteDuration *= 2;
              playNote(note, i, currentKey, elapsedTime, noteDuration, track);
              elapsedTime += noteDuration;
            } else
            // ==================================================================== MULTI NOTE
            if ((voice.elementAt(i) instanceof abc.notation.MultiNote)) {
              MultiNote multiNote = (MultiNote) voice.elementAt(i);
              playMultiNote(multiNote, i, currentKey, elapsedTime, track, staff);
              elapsedTime += getNoteLengthInTicks(multiNote, staff);
            }
          } // endif (!inWrongEnding)
          // ====================================================================== REPEAT BAR LINE
          if (voice.elementAt(i) instanceof abc.notation.RepeatBarLine) {
            RepeatBarLine bar = (RepeatBarLine) voice.elementAt(i);
            if (repeatNumber < bar.getRepeatNumbers()[0] && lastRepeatOpen != -1) {
              repeatNumber++;
              i = lastRepeatOpen;
            } else if (repeatNumber > bar.getRepeatNumbers()[0]) inWrongEnding = true;
            else inWrongEnding = false;
          } else
          // ====================================================================== BAR LINE OPEN /
          // CLOSE
          if (voice.elementAt(i) instanceof abc.notation.BarLine) {
            // currentKey = new KeySignature(tuneKey.getAccidentals());
            switch (((BarLine) (voice.elementAt(i))).getType()) {
              case BarLine.SIMPLE:
                break;
              case BarLine.REPEAT_OPEN:
                lastRepeatOpen = i;
                repeatNumber = 1;
                break;
              case BarLine.REPEAT_CLOSE:
                if (repeatNumber < 2 && lastRepeatOpen != -1) {
                  repeatNumber++;
                  i = lastRepeatOpen;
                } else {
                  repeatNumber = 1;
                  lastRepeatOpen = -1;
                }
                break;
                // TODO case BarLine.BEGIN_AND_END_REPEAT
            }
          }
          // Whatever kind of bar line it is
          if (voice.elementAt(i) instanceof abc.notation.BarLine) {
            currentKey = new KeySignature(tuneKey.getAccidentals());
          }
          i++;
        } // end while each element in voice
      } // end while each voice in music
    } catch (InvalidMidiDataException e) {
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return sequence;
  }