Java - MIDI programming 1
programming MIDI in java is fun because the built in midi package from sun provides a rich API (applicaton programming interface) for MIDI purposes. Therefore there is no more need to struggle with low level coding to open a device, connecting an device input to an output etc.
In this tutorial we are going to learn how to use the java midi package to open the defaultsynthesizer of the operating system and producing the sound of single note.
Ok, let start coding, open your favorit editor which I guess is eclipse and start a new java project (for example java-midi-1). Now add a new class to the project, “SimpleSynth” and import the required classes from the javax.sound.midi package
import javax.sound.midi.MidiSystem; import javax.sound.midi.ShortMessage; import javax.sound.midi.MidiMessage; import javax.sound.midi.Receiver; import javax.sound.midi.Synthesizer; import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.InvalidMidiDataException;
A short explanation: the MidiSystem class is the interface to MIDI resources (for example synthesizer, sequencer etc). Using the ShortMessage class we will create MidiMessage objects which stores information needed by the receiver. The MidiUnavailableException is an exception class for handling missing MIDI resources while the InvalidMidiDataException class is used to catch invalid midi data errors. It sounds a little bit confusing I guess, so lets start with an example by opening the default synthesizer of the operating system.
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.Receiver;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.InvalidMidiDataException;
public class SimpleSynth {
Synthesizer synth;
public SimpleSynth() {
try {
synth = MidiSystem.getSynthesizer();
synth.open();
}
catch(MidiUnavailableException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SimpleSynth synth = new SimpleSynth();
}
}
Now, what we have done here is: we declare a Synthesizer class attribute. In the constructor of our class we create a try catch block which catch a MidiUnavailableException if there is no synthesizer found. Then we use the interface of the MidiSystem class to get the default synthesizer of the operating system, after we have the synthesizer object we just open it by calling its open() method. Lets go further by creating the receiver and some MIDI messages.
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.Receiver;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.InvalidMidiDataException;
public class SimpleSynth {
Synthesizer synth;
Receiver rcvr;
public SimpleSynth() {
try {
synth = MidiSystem.getSynthesizer();
synth.open();
rcvr = synth.getReceiver();
}
catch(MidiUnavailableException e) {
e.printStackTrace();
System.exit(1);
}
}
private MidiMessage getMessage(int cmd, int note) {
try {
ShortMessage msg = new ShortMessage();
int channel = 0;
int velocity = 60;
msg.setMessage(cmd, channel, note, velocity);
return (MidiMessage) msg;
}
catch(InvalidMidiDataException e) {
e.printStackTrace();
System.exit(1);
}
return null;
}
public static void main(String[] args) {
SimpleSynth synth = new SimpleSynth();
}
}
As you see, we add a new class attribute of type Receiver. To initialize the receiver object we use the getReceiver() method from the synthesizer. Also a new method getMessage is added to the class. In the getMessage method we first create a ShortMessage object and set the message we want to occur using its setMessage method. The setMessage() method from the ShortMessage object are filled with 4 params, the command, MIDI channel, data1 and data2. Since we want a note message the data2 ( the velocity ) is hardcoded into 60 and we also want this message goes to the MIDI channel 0. The last part will be to produce the sound of a note, so lets go for it. Take a look at the code example below.
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.Receiver;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.InvalidMidiDataException;
public class SimpleSynth {
Synthesizer synth;
Receiver rcvr;
public SimpleSynth() {
try {
synth = MidiSystem.getSynthesizer();
synth.open();
rcvr = synth.getReceiver();
}
catch(MidiUnavailableException e) {
e.printStackTrace();
System.exit(1);
}
MidiMessage noteOn = getNoteOnMessage(62);
rcvr.send(noteOn, 0);
try {
Thread.sleep(2000);
}
catch(InterruptedException e) {
e.printStackTrace();
}
MidiMessage noteOff = getNoteOffMessage(62);
rcvr.send(noteOff, 0);
}
private MidiMessage getNoteOnMessage(int note) {
return getMessage(ShortMessage.NOTE_ON,note);
}
private MidiMessage getNoteOffMessage(int note) {
return getMessage(ShortMessage.NOTE_OFF,note);
}
private MidiMessage getMessage(int cmd, int note) {
try {
ShortMessage msg = new ShortMessage();
msg.setMessage(cmd, 0, note, 60);
return (MidiMessage) msg;
}
catch(InvalidMidiDataException e) {
e.printStackTrace();
System.exit(1);
}
return null;
}
public static void main(String[] args) {
SimpleSynth synth = new SimpleSynth();
}
}
Two helper method are added, the getNoteOnMessage() and the getNoteOffMessage(). As you see, the code in the constructor continuos with creating a noteOn MidiMessage with a pitch value of 62 (which is a C) and sends it into to the receiver object, the second param of the send method is the timestamp param. Since we want to execute the message immediately we set it to 0. After sending the noteOn MidiMessage we pause the programm for 2 seconds using the Thread.sleep method. After the thread wakes up we send a noteOff message to the receiver to stop the playing note. If everything works correct you should hear a piano sound of the note C for two seconds.
So, that was the first lesson of java MIDI programming, I hope I will find some time to write another tutorials. see you.
Posted in Tutorials