A few years back, I wrote a few posts about MIDI. Those posts were technical. They explained the messages that MIDI devices use to communicate with each other. Later, we moved most of this to the Wiki, but not all. Some notes, I thought, should come back.
MIDI has always fascinated me – more as a software designer rather than a musician. Years ago, when I was first writing about MIDI and before MIDI guitars were practical, playing an actual guitar was more interesting than using software or keyboards (that I did not know how to play) to put together MIDI tracks. At that time too, I was not impressed with most MIDI sound. A MIDI piano sounded real enough, MIDI drum were good, but guitars or brass – not so much.
I played a bit with MIDI. I used Orinj to build a piano track for a song that needed one (here is the piano track compressed to an mp3). I could barely play the piano, but that is why we have MIDI – for instruments that we do not have or cannot play.
Musical Instrument Digital Interface
MIDI stands for "Musical Instrument Digital Interface" and is a protocol that devices (instruments, computers) use to communicate to each other and to store data. In other words, MIDI is a language for storing and transferring digital representations of music from one device to another.
As a language for digital music, MIDI does not seem that different from sampled audio (e.g., wave files). Every number in a sampled digital audio file tells some electronic device (the computer soundcard, for example) that, at a certain time, the amplitude of the sound should be a certain value. MIDI communicates similarly. Every piece of a MIDI file or sequence tells some electronic device that, "at a certain time", the MIDI device should "do something". These pieces of information are the MIDI events. They carry two pieces of data: 1) the time at which a MIDI device should do something; and 2) the message that tells the MIDI device what to do. Some examples are below. The MIDI protocol itself is detailed in our Wiki.
So, a message tells a MIDI device to do something at a certain time. However:
- The message is just a message. What the MIDI device does with it is up to the device. Different MIDI devices may treat the same message differently.
- As a language, MIDI is ever evolving. It is possible that some devices do not understand some messages. In this case, the devices should simply ignore the messages.
- Some messages are designed to be specific to the devices produced by some manufacturers and should be ignored by others.
That is, MIDI is fuzzy. There is a significant level of flexibility in interpreting the MIDI protocol. Here are some examples.
- Consider a MIDI device that receives the message of the three bytes 0x92 0x3C 0x50. These three bytes tell a MIDI device to play on channel 2 (0x92) the note middle C (0x3C) with velocity of 0x50. If you just send this message to a MIDI device, it will start playing the note. Which instrument will play the note is, however, undefined. How long the note will play for is also undefined.
- If you wanted to define which instrument would play the note, you should have sent a message to the MIDI device before the message above. That message should have specified an instrument for channel 2. If you send the message above anyway without specifying an instrument beforehand, one of two things will happen – the device will either play the note with some default instrument (usually the "acoustic grand piano") or will play the note with whatever instrument was specified for this channel before. The latter could be anything. It could even be an instrument that was sent to channel 2 by some previous MIDI sequence (you could have played some other MIDI file before).
- How long the note is played depends on the device and on what happens afterwards. A MIDI device, sometimes depending on the selected instrument, may play the note indefinitely. Another MIDI device may choose to let the note decay. If you want a note to stop at a certain time, you should send a message to the MIDI device that tells it to stop the note playback. Consider the message 0x82 0x3C 0x50. This message tells the device to stop on channel 2 (0x82) the note middle C (0x3C) with velocity of 0x50. What "velocity" means, however, is not clear. It could be how fast the note decays or it could be something else. Even if it means the speed of decay, it is not clear how long the note will be decaying precisely, for the velocity 0x50.
- Suppose that 0x92 0x3C 0x50 is the last note that you want to play in your MIDI sequence. At a minimum, the MIDI sequence will contain a MIDI event after the note with the message that this is the end of the MIDI track. The MIDI device will probably stop all notes at the end of a track. It is possible that the "end of track" message comes right after the "play this note" message (say, a microsecond after). The note will then probably not be heard at all.
- Suppose that before the note you send a message that starts with the byte 0xE2. This is a "modulation wheel" or a "pitch wheel" message for channel 2. It has a total of three bytes starting with the byte above and ending with two more bytes that specify how much the pitch should change. The values of the two bytes range from 0x0000 to 0x3FFF, but which is which depends on the MIDI device. Usually, 0x0000 means two steps lower and 0x3FFF means two steps higher, while 0x2000 is the center. However, devices are free to interpret these values differently.
Thus, devices that play MIDI have some flexibility in interpreting and even ignoring messages. Let's say that you move a MIDI sequence from one device to another. If the MIDI sequence is well constructed, it will start by telling the MIDI device which instrument should be played by which channel, what the channel volume and pan would be, and so on. If the MIDI sequence is not well constructed, it may omit all this information. In this case, the same sequence could end up being a loud piano on the first device, a quiet guitar on the second, and something else on the same device played a second time. I have noticed, for example, that a MIDI sequence sounds different when played through Orinj and when played through Windows Media Player, even though both should be using the same MIDI device and nothing should have happened in-between.
Devices that allow you to record MIDI have additional flexibility. When you record a piece on your MIDI keyboard, for example, the MIDI keyboard may choose to record or not to record a message for the instrument that should be chosen. MIDI editing software works similarly. While designing Orinj, we forced each track in a MIDI file to start with a set of predefined controllers. We included messages for the instrument, volume and pan, and others. We also assumed, just for clarity, that a small properly organized MIDI file will use one track for one channel. However, as with all software design, there is a choice between "making a piece of software error proof" vs. "providing flexibility". We chose the latter. This means that the users of Orinj are free to delete the initial controllers and to mix tracks and channels. We left it up to the user to make sure that MIDI files are consistent.
I find MIDI interesting, because it is flexible. I also find it a bit frustrating, as all this flexibility makes it somewhat disorganized. Nonetheless, it can be quite powerful.