Magazine Archive

Home -> Magazines -> Issues -> Articles in this issue -> View

Adventures In MIDILand (Part 6)

Part 6. In this final episode Martin Russ returns to base camp, and completes his exploration of the MIDI programming jungle with a de-briefing for his fellow travellers.

What have we been doing for the last six months? Silly games? Pointless manipulations? No! This series has tried to show how MIDI works at its deepest and most complex level, by providing real example programs which can actually be modified by the users themselves. Consequently, anyone who has followed this series and used the programs should have been inspired to try and alter them to do something different. In this case, the series will have succeeded, and at least some of the ignorance concerning MIDI will have been removed from the world. There can be no substitute for actually manipulating the raw MIDI information itself as a way of learning about its innermost secrets.

This month's adventure completes a grand tour of almost all the things that we can explore with MIDI, with the exception of System Exclusive — which was covered in a previous series of mine in Sound On Sound (April 1989 to March 1990). Unlike our previous software safaris, the location of this month's first exploration is in the mind, not in a MIDILand program.


We could consider our explorations so far as taking place within a multi-dimensional space that involves the following elements: pitch events; timbre events; time events.

These are also the elements which make up musical notation. Pitch is usually vertical, whilst time is horizontal, and timbre is usually, well, inadequately described by words. I have concentrated on mapping events — not only within their own categories (pitch transposition, MIDI clock doubling), but also across the groups (Channelising, pitch to velocity). The end result has been to show that almost any mapping is possible, which is certainly not the impression you might get when you first look at the tidy categorised MIDI messages.

Just as a real safari would attempt to show you animals in some sort of context, so this exploration of MIDI has tried to include programs dealing pitch, timbre and time in a meaningful way. We started with simple manipulations to explore ways of using a computer to display and modify MIDI information, and then progressed to programs which implemented running status, thereby allowing interaction with all types of MIDI messages. The powerful technique of mapping was introduced as a way of describing and documenting the changes we were making. Finally, time events were shown to be capable of alteration in very similar ways to those in the other groups.

In all of the examples, the underlying driving force has been the MIDI messages themselves. They have shaped the structure of the programs and the approaches to solving the problems associated with the complexity of MIDI messages. The evolution of MIDI has meant that many features have been added to the basic spec, which means that the decoding of messages can be awkward and tedious, especially with running status to confuse matters.

The programs we have so far used as examples have all implemented just enough decoding of incoming MIDI bytes to produce the changes required. To complete the decoding, a series of decisions need to be made so that the MIDI bytes and the following data bytes can be interpreted correctly. Using this information, we can outline the sort of structure which could be used in a program (see flowchart in Figure 1).

Figure 1. Flowchart for decoding MIOI messages

This series of decisions can be thought of as a tree, where you make a decision as each branch splits into several smaller branches, thus reducing the number of possibilities until the type of byte is identified. We could translate this into a program with the same structure, but this would seem tedious, since the decisions are concerned with just simple 'yes' or 'no' answers. Instead it is often easier to use a structure which does some initial yes/no splitting, but which then uses a series of questions looking for a 'yes', and moving on to another similar question if the answer is 'no' — which looks like this:

main program
input = INP(3)
low_nibble = input AND &H0F
top_bit = input AND &H80
IF top_bit = &H80 THEN
GOTO start

SUB process_status_byte(input)
nybble = input AND &HF0
IF nybble = &HF0 THEN
IF nybble = &HE0 THEN
IF nybble = &HD0 THEN

SUB decode_system_byte(input)
system = input AND &H0F
IF system = &H00 THEN
IF system = &H01 THEN
IF system = &H02 THEN

The main program section waits for a valid status byte, and then passes control to the subroutine, which decodes the byte further, possibly passing it to other subroutines for further decoding.

The contrast between the two methods is similar to the game where you have to guess a number (between 1 and 9, for example) in the least number of tries. One approach would be to start at 1 and ask if it is each of the numbers in turn, as you count up. In the worst case, you would have to ask nine questions to find out the answer. Another approach would be to ask if the number is higher than 5, and if yes, then ask if the number is higher than 7, and if yes, then ask if it is higher than 8, and so on, halving the possible range of numbers at each guess. With the second method you can reach the correct answer in four tries at most. Each method has its advantages and disadvantages, which is why the program uses a little of both methods.

In a real application program, it is unlikely that the main MIDI input routine would be in exactly this form, but it would be interrupt driven instead, so that it could deal with MIDI bytes as they arrive by putting partially decoded bytes into buffers for subsequent use by the main program. The technique of splitting the bytes using a structure with a series of decisions is just as relevant, regardless of the implementation.


So what do real world MIDI programs look like? The simplifications which have to be applied to create short understandable programs make the examples given so far in this series rather unrealistic. One of the major problems in any programming task is making sure that the program copes with errors or unexpected results — in the case of MIDI programs, this usually means coping with nothing happening at the MIDI input. All the programs so far will wait for a MIDI input until you press a key (on the computer keyboard) to quit the program — and even to quit you need MIDI messages actually appearing at the ST's MIDI In, otherwise the program will not exit the loop where it waits for a MIDI byte to become available.

Often the process of making the program work despite a plethora of possible disasters means writing program segments that replace the commands of the language itself. In fact, rewriting the standard functions so that they do what you want rather than what the original programmer thought you wanted is often a major part of the programming task. By way of illustration, here is part of the MIDI input routine from one of my programs:

SUB wait_for_midi(timeout!)
' times out after timeout period
SHARED error_flag,mm
mm = &HFF
t! = TIMER
LOOP UNTIL (mm<>&HFF) OR ((TIMER -t!) > timeout!)
IF ((TIMER -t!) >= timeout!) THEN
error_flag = TRUE
error_flag = FALSE

This subroutine approximately replaces the m = INP(3) AND &HFF statement which has appeared in most of the programs so far, but it has the advantage that it either returns a MIDI byte with the Error Flag set to false, or returns nothing after a timeout period with no MIDI activity, but with the Error Flag set to true. The calling loop checks the flag and acts accordingly, in a similar way to the previous examples in this series. The INP(3) function provided by Basic has none of these features, and it is quite easy to write a program which will lock up whilst waiting for a MIDI byte to arrive!

When you add in the problems of unexpected System Real Time messages (like $F8 clock ticks) upsetting the status temporarily, or the problems of interpreting All Notes Off events combined with Sustain Pedal events, then the ways of coping with MIDI input become necessarily complex — and completely outside the scope of a series like this. Even a powerful compiled Basic like HiSoft is not fast enough for many real-world MIDI programming needs, which is why many programmers write their MIDI routines in assembly language.

So, I hope you now have a better grasp of a few of the problems involved in MIDI programming, and some idea of how they can be solved. This series has aimed to show the workings of MIDI by example and by experiment, rather than explain exactly how to write MIDI programs. Even so, I hope that you are now more impressed by the programming skill needed to write a program which can cope with multichannel simultaneous recording or realtime MIDI processing.


The rough guide to the territory that you were given in part one of this series can now be expanded into a sort of index for the series as a whole:

Part 1: MIDI Fundamentals
The basic MIDI programming loop
The MIDI Display program
Part 2: Running Status
Note Numbers and Velocity
Timing and Controllers
The program skeleton
Part 3: Channels
Status changes
MIDI buffers
The MGRAY bias detector
Part 4: Mapping
Message type changes
Program changes
The Mapper program
Part 5: Clocks and tempo
Time warping
Merging as mapping
The MCLOCK humaniser
Part 6: De-brief
Things to come


Similarly, the list of example programs which was given in Part 2 can now be indexed to their relevant positions within the series:

Name Description Part
MAP The Mapper 4
MKKEY Keyboard Remapper 4
MKREV Keyboard Reverser 2
MKDLY Keyboard Delayer 2
MKOCT Keyboard Octave Reverser 4
MKFLM Keyboard Flammer 2
MKADD Keyboard Add Octave/Fifth etc 2
MKSTC Keyboard Staccato-iser 3
MKTRN Keyboard Transposer 2
MKCHD Keyboard Chorder 2
MK2CH Keyboard 2 Channels at Once 3
MK4CH Keyboard 4 Channels at once 3
MKSWP Keyboard Velocity/Note Swapper 4
MKV2N Keyboard Velocity Transpose 3
MKV2T Keyboard Velocity Transpose with constant velocity 3
MKV2P Keyboard Velocity to Pitch Bend 4
MKSPL Keyboard Splitter 3
MVREV Velocity Reverser 2
MVQNT Velocity Quantiser 2
MVSPL Velocity Splitter 3
MCHAN01 Channeliser 3
MCHAN04 GEM Channeliser 3
RSTAT Running Status Detector 2
MDRS Running Status Remover 2
MBUFF MIDI Buffer Display 3
MDISP MIDI Hex Display 1
MPQNT Pitch Bend Quantiser 2
MCLOCK MIDI Clock Humaniser 5
MDRADD Note to Drum Converter 4
MCLKHA MIDI Clock Halver 5
MCLKDB MIDI Clock Doubler 5
MASCLK Active Sensing to MIDI Clock 5
MKN2D Note to Start/Stop Control 5
MKN2PC Keyboard Note to Program Change 4
MSIMPL How not to do it! 2


The 'MIDI Fundamentals' panel in the first part of this series was designed as an introduction to MIDI. Looking back at MIDI with our now experienced eyes, it is possible to rewrite it from a completely different viewpoint. The re-written version might go like this:

"The Musical Instrument Digital Interface specifies a method of communicating information between electronic musical instruments using messages which can be one, two, three or more bytes in length. The initial parts of the first of these bytes (the Status byte) to be received provides information on the type of event which is being conveyed by the MIDI message. The remainder of the initial byte is used for either channel information (MIDI provides 16 separate channels) or for additional information about the type of message. The status byte is indicated by setting the most significant bit high, any following bytes have this bit set to low, thereby restricting the data capacity of a single MIDI data byte to 7 bits.

There are two types of message:

Channel messages are used to convey information specific to one of the 16 channels and consist of one, two or three bytes. The additional bytes after the initial Status byte are used to indicate extra parameters relevant to the message type. For example, in a Note On message, the second byte gives the note number and the third byte the attack velocity. If the type of message is the same for subsequent messages, the status byte may be dropped and just the data bytes sent under Running Status.

System messages are designed for transmitting global information to all the equipment on a MIDI network, and they deal with the overall timing and control aspects. Although most of these messages are single bytes (especially the System real Time messages where they are kept as short as possible), messages of any length can be sent by using the System Exclusive header and footer bytes."

If you have followed the series closely, try going back and looking at the original description, and see if your understanding has changed in line with the new version above.

I hope you have enjoyed this unusual journey through the rarely charted depths of MIDI programming. MIDI is a fascinating subject, ripe for exploration and swapping of information, and I would encourage all readers to follow up the series examples with their own investigations, and to share their discoveries, preferably through the UK MIDI Association.


All the programs mentioned in this series can be found on the MIDILand Programs disk set (order code S101) which is available from SOS Software, price £7 inc postage.

SOS Software, PO Box 30, St Ives. Cambridgeshire, PE17 4XQ. 0480 61244.


If you want to find out the latest information, or even make your own contribution to any topic related to MIDI, then the best thing to do is to contact your local official MIDI organisation. In the UK, it is the UKMA.

Vic Lennard, UKMA, (Contact Details).


In case you thought that translating the example programs to another programming language would result in code which was completely different, you might be interested in the following partial conversion of what was virtually the first program in this series, MDISP, into HiSoft C for the ST:

char mc;
int status;
mc = Bconin(3);
while (mc == 0xFE);
if (mc > 0x7F)
printf("\n %X", mc);
printf(" %X", mc);
status = Bconstat(2);
while (status != -1);

Although GEMDOS calls have replaced the more familiar INP(3) and INP(2) Basic keywords, the overall structure of the program is very similar to those shown earlier in this series. The outermost loop waits for the keyboard to be pressed, whilst the inner loop waits for any MIDI byte other than $FE to arrive, thus implementing Active Sensing filtering. The two 'printf' statements just print out the bytes on the screen, in hex and with simple formatting.


MIDI is an evolving standard. Much of what will happen to it over the next few years will be the direct result of action taken to strengthen its weak points, and so by looking at them you can make good guesses as to future developments.

The Sample Dump Standard is rather too slow for transmitting the 16-bit high sample rate sounds of today's technology.

The debate over how few Europeans actually use MIDI Time Code in contrast to the apparently large numbers of American users continues.

Rumours of MIDI lighting standards refuse to go away.

The recently released Bank Switching and Effects Controller additions to the MIDI Standard show that user feedback does have an effect, although the bank switching was well overdue.

A lack of 'policing' of MIDI implementations has led to confusion over whether C4 or C3 should be mapped to MIDI Note Number 60. Similarly, some instruments do not remember their MIDI setup during power-down and need to be reset from scratch every time they are powered up.

With a runaway success on their hands, it still seems unlikely that the International MIDI Association and the MIDI Manufacturers Association will upset things by releasing MIDI 2.0 without ensuring full compatibility with the existing standard. Any other approach could destroy the amazing progress which has happened over the last seven years.

Previous Article in this issue

The Beatmaster

Next article in this issue

Software Support

Sound On Sound - Copyright: SOS Publications Ltd.
The contents of this magazine are re-published here with the kind permission of SOS Publications Ltd.


Sound On Sound - Jan 1991




Adventures In MIDILand

Part 1 | Part 2 | Part 3 | Part 4 | Part 5 | Part 6 (Viewing)

Feature by Martin Russ

Previous article in this issue:

> The Beatmaster

Next article in this issue:

> Software Support

Help Support The Things You Love

mu:zines is the result of thousands of hours of effort, and will require many thousands more going forward to reach our goals of getting all this content online.

If you value this resource, you can support this project - it really helps!

Donations for July 2020
Issues donated this month: 0

New issues that have been donated or scanned for us this month.

Funds donated this month: £0.00

All donations and support are gratefully appreciated - thank you.

Please Contribute to mu:zines by supplying magazines, scanning or donating funds. Thanks!

Monetary donations go towards site running costs, and the occasional coffee for me if there's anything left over!

Small Print

Terms of usePrivacy