Magazine Archive

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

Adventures In MIDILand (Part 4)

Part 4: Martin Russ looks at how mapping can help in traversing the MIDI jungle.

Some words just seem to appear in product reviews or technical articles without any adequate explanation — 'samploid', for example, is typical of the less informative words that have emerged recently. But often a more descriptive word is used in a special sense, and its full meaning may not be clear. I am often guilty of using the word 'mapping' without any detailed explanation, and since the conventional meaning of the word is rather appropriate to the idea of going on safari in the world of MIDI, I had better set the record straight. This adventure gives a guide to exactly what MIDI mapping is, and how it can help to integrate all your MIDI instruments into a huge and powerful system, or produce weird manipulations of MIDI information.


You will not need compasses, dividers and rulers for MIDI mapping. It refers to the mathematical concept of connections, rather than the process of making a map of unexplored territory, and MIDI Note Numbers are a good place to start our investigation. The MIDI specification states that Note Number 60 ($3C) represents Middle C, and so you would expect that playing Middle C on a keyboard would produce a MIDI message with &H3C as the second byte. Putting this in a more formal way, we could say that Middle C is connected to $3C, since playing Middle C results in a message containing $3C.

This idea of connections is called 'mapping' in mathematics, and so we could rephrase the statement as "Middle C maps to $3C", or more generally: "the second byte of a MIDI Note On message maps to the pitch of the note played".

This abstraction of the actual value to a more general one is very useful when describing how MIDI works. In this case I have carefully avoided stating exactly what note Middle C is, because different manufacturers have different ways of defining it. Some call it C3, whilst others call it C2, but even with the same name the actual pitch could be transposed by an octave. By saying that the second byte maps to pitch we can cover all these alternative interpretations by imagining a mapping where several values all map to one other value.

General Case:
2nd Byte of Note On -> Pitch

Specific Example:
$3C -> Middle C
C3 or C2 or C4 -> Middle C
$3C -> C3 or C2 or C4
where the symbol -> means 'maps to'.

Looking at the wider context, we can use mapping to describe what is happening in other MIDI situations. For example: the modulation wheel typically maps MIDI Controller #1 to LFO Pitch Modulation Depth (ie. it controls vibrato depth). If we use the mapping symbol to describe a transformation, then we can describe some of the changes we made to MIDI messages in Part 2 of this series:

Pitch -> Pitch + Transpose describes the pitch transposing program MKTRN. The left hand side of the equation shows the state before the mapping, and the right hand side shows the output state after the transformation.

Pitch -> 120-Pitch defines the MKREV keyboard reverser program which 'inverts' the keyboard.

Note On Channel 1 -> Note On Channel 2 describes a channel changing program like MCHAN.

Note On Channel 1 -> Note On Channel 1
-> Note On Channel 2
-> Note On Channel 3
-> Note On Channel 4
describes the MK4CFH 4-channel convertor program designed to stack up sounds on multi-timbral synths.


The last example given above begins to show another use of mapping techniques which can be applied to many situations. Most multi-effects units now offer selection of effect patches by MIDI Program Change messages, just as you would expect, but they often also offer Patch Tables or Maps which let you specify which effects patch is selected by each Program Change message. This means that you do not have to move effects patches around in memory so that they match the Program Change messages sent by selecting sounds on your master keyboard. A typical Patch Map might look like this:

Program Change 0 -> Effects Patch 0
Program Change 1 -> Effects Patch 0
Program Change 2 -> Effects Patch 37


The first two sounds (on the master keyboard) both need Effect 0, whilst sound 3 needs Effect 37 and so on. This map may take some time to create initially, but once installed it enables the combination of master synth and effects unit to behave as an integrated system, with Program Changes selecting the appropriate effects automatically.

When stacking several synths or expanders a similar facility would mean much easier selection of composite sounds, but few manufacturers offer Patch Maps on instruments (not yet anyway — let's hope they're reading). Another situation in which Patch Maps would be useful is where you have a sequencer driving several expanders (all on different MIDI channels) via a thru box. Recording a program change from the master keyboard onto any track and then playing the track will switch programs on whatever expander is assigned to that channel. Simple stuff. This is fine if you are sure of your instrumentation (ie choice of sounds), but suppose you want to change programs on all the expanders — you would have to alter the recorded Program Change messages on all the tracks, or change patches manually on all the expanders. Searching through memories for a different bass sound and a better string sound to go with it, and then deciding that the original sounds worked best is time consuming, and usually results in a pile of scribbled patch number notes which you can never find later anyhow.

What you need is something which enables you to generate Program Change messages on all 16 MIDI channels from just one control — or to put it another way, one control maps to 16 patch changes, one per channel. As far as I know, no commercial orchestration/arrangement utility like this exists, so I wrote one! Since it performs mapping of program changes, I called it 'The Mapper'.


The Mapper is a Program Change mapping utility program which is really intended for the power user of MIDI systems. It is designed to aid those with many MIDI keyboards and expanders, who want to be able to recall a complete performance-orchestration-arrangement with the press of one button.

By a 'performance' I mean a complete snapshot of the programs in each piece of equipment on every MIDI channel — rather like a Multi on an SY77. If you have 16 pieces of MIDI equipment, one per channel, then you will know all about how tedious it can be setting the program changes for more than just one or two synths. Storing the MIDI program changes in a sequencer file can be a nuisance as well — all that channel changing and checking to make sure the right data is set up, etc. The Mapper changes this forever. Ten memories are provided, with disc storage for your own performances. Each set of 16 program changes can be recalled with just one mouse click. So, you get ten sets of 16 separate Patch Maps, one per channel, ten deep (160 separate patch numbers are stored overall).

Compared to the programs described so far, The Mapper is simple. The only hard work is getting the GEM interface to work, so I will show only the essential parts of the program, that relate to the MIDI processing.

Part of the Mapper program:
FOR channel = 0 TO 15
program_change channel, c(mem,channel+1)
NEXT channel
SUB program_change(chan,num)
chan = chan AND &HFF
num = num AND &HFF
OUT 3, &HC0 OR chan
OUT 3, num

The array 'c' is used to hold the mapping table of program change numbers, and the 'mem' variable indexes which of the ten available memories is being output. The For/Next loop scans through the MIDI channels, outputting the appropriate Program Change message, on the correct channel and with the mapped Program Change number each time. Without using a GEM interface, it is quite easy to write a simple program which can do the basics of The Mapper, but you will need to add file handling in order to be able to store and recall the mapping tables.

The only major problem with using The Mapper is that it is a Program, not a Desk Accessory, which means that in order to make best use of it you need a sequencer which enables you to run another program 'inside it' like Dr.T's RealTime. But the idea is the important thing in all these examples, and I intend to convert The Mapper to a desk accessory one day. Even if I don't get around to it, you may see the idea appear in commercial sequencers. Currently most sequencers offer the equivalent of one memory per sequence or phrase (the Patch Memory in Hollis Research's Trackman is a good example), which means that you need to fiddle about recording sequences with just Program Change messages or setting up patch numbers and then replaying the empty sequences, just to recall the orchestration. The Mapper, combined with RealTime or a sequencer with similar facilities, makes it easy.


Now that we have the idea of mapping firmly in our grasp, we can look at our programs in a new light. You should be able to see that the MKTRN Transposer and MKREV Reverser programs, which have already been described, can be thought of as pitch mapping transformations. The MKKEY program takes this a stage further by allowing you to remap the notes of an octave so that a C will be transformed into another note, whilst a D will become yet another note, and so on. This allows you to convert a conventional keyboard into one where playing in C major (ie using the white notes) produces notes in a different key signature. By mapping the notes to a blues scale you can produce some very jazzy chords without any real effort — just by playing in C major.

MKKEY is based around an array of values which hold the mapping information for an octave. These are repeated for the whole keyboard, so all the octaves are identical. With a larger array, you could remap all 128 MIDI notes, but it would be very tedious. The compromise of a single octave works well in practice. Six pre-defined scales are provided, and you can also enter your own (the example array data below shows what an 'ordinary' octave looks like).

The format of the array:
m (note, scale)
where 'note' indexes the note number within the scale, and 'scale' indexes the particular scale mapping chosen.

normal keyboard (scale =0)

Part of MKKEY program:
OUT 3, n
n = INP(3)
m = n AND &H7F
oct = m\12
note = m MOD 12
OUT 3, (oct*12)+m(note,scale)

The incoming note number is stored in variable 'n', masked with 128 and stored as variable 'm' (this ensures that the value is below 128). The octave number is then calculated by integer-dividing by 12. The actual note number within the octave is calculated using the Modulus function (m MOD 12). The output uses the octave number to produce the basic note number for the octave, and adds in a note number from the octave array, indexed by the note and scale variables.

By using this program you can force whatever is played on the keyboard to produce notes in a fixed key: the C major setting turns all the black notes into the corresponding white notes, with the end result that anything you play comes out in C major. The blues scale is more problematical, especially since there are not enough keys to perform the mapping properly. The compromise I have chosen leaves you with an E which seems out of place, but the other notes work well.

The reversed octaves scale gives you rising pitch across the keyboard, but with each octave the wrong way up! These transformations can be permanently programmed into any synth which offers individual key scale tuning, if you want to use them for special effects on any sounds.


Perhaps the least useful but most intriguing mapping that involves velocity must be swapping the velocity and note values. You are probably well used to the fact that keyboards have limited velocity sensitivity but very precise pitch control — this program reverses that situation. You now have very fine control over the velocity across the keyboard, and the strength of playing determines the pitch, which is now more difficult — if not impossible — to control accurately. Anyone who can produce decent music with such a controller certainly has exceptional keyboard skills.

Swapping the two values is not as easy as it might seem, because the program needs to take account of the fact that the pitch information is now coming from how hard you play the keyboard, and so a single velocity value has to be mapped to a Note On and a Note Off message. This means that this program is monophonic, and notes will not sustain.

Part of MKSWP program:
v = INP(3) AND &HFF
OUT 3, v
OUT 3, n
OUT 3, &H80+chan
OUT 3, v
OUT 3, 0
n = INP(3) AND &HFF
a = n AND &H80
IF (a <> &H80) THEN OUT 3, (in AND &HF0) + chan: GOTO do_next
GOTO retest

Instead of swapping note and velocity information, you can map the velocity to a MIDI Controller or even to another message entirely, like Pitch Bend. We have already seen velocity-controlled transposing in the MKV2N program, but the MKV2P program gives you a critical velocity value (the 'add' variable in the program segment) below which nothing happens, but above which notes are pitch bent. This is easier to use than describe...

Part of MKV2P program:
OUT 3, n
v = INP(3) AND &HFF
IF v = 0 THEN
OUT 3, 0
OUT 3, 120
OUT 3, &HE0 + chan
OUT 3, 0
IF v > add THEN
OUT 3, v
OUT 3,&H40
n = INP(3) AND &HFF
a = n AND &H80
IF (a <> &H80) THEN OUT 3, (in AND &HF0) + chan: GOTO do_next
GOTO retest

Notice that this program extends the idea of restoring the original status by using a different type of message instead of just a different status. This can give complete freedom in how you transform from one message to another.


Returning to the same ground as that covered by the Mapper, the MKN2PC program lets you map just one of the keyboard notes to increment Program Change numbers:
Keyboard Note -> Increment Program Change

The trigger note must be chosen with some care — the note a semitone above the root of the home key is seldom used, and therefore often makes a suitable choice. If you do play the trigger note by accident, it takes 127 more presses to get you back to where you were!

Part of MKN2PC program:
n = INP(3) AND &HFF
v = INP(3) AND &HFF
OUT 3, n
OUT 3, v
IF ((n=add) AND (v<>0)) THEN
OUT 3, &HC0 + chan
OUT 3, pc
pc = pc + 1
IF pc > 127 THEN pc = 0

You could alter the program to create two trigger notes, one to increment the program number and the other to decrement it, but this doubles the chances of an accident.


Because the Note On message is such a fundamental part of the way that MIDI is designed, I have tended to concentrate on modifications to note number and velocity, and mapping them to other messages. One of the most important lines in any program is the filter which decides which messages will be processed:

Idealised MIDI processor program:
INPUT byte
IF byte = (wanted message type) THEN

In most of the examples so far the wanted message types have been Note On ($90) or Note Off ($80) — all the other messages are completely ignored. You can process other messages by altering the message type in this part of the program. First of all remove the channel nibble by masking (ANDing) with $F0:
a = Input_byte AND &HF0
and then do the comparison:
(a=&H90) selects just Note On messages
(a=&HB0) selects just MIDI Controller messages
(a=&HD0) selects just Channel Aftertouch messages
(a=&HE0) selects just Pitch bend messages

Linking these comparisons with ORs lets you choose only those messages you want, for example:
(a=&H90) OR (a=&H80) selects Note On and Off messages
(a=&H90) OR (a=&H80) OR (a=&HB0) selects Notes and Controller messages

The last example would be very useful for the keyboard modifying programs since it allows the sustain pedal to be used, although the Pitch Bend and Aftertouch are still filtered out. However, if we changed the programs by simply using these new statements, the MIDI Controller messages would be interpreted as Note Ons or Offs and this would alter the controller information. We could change the structure so that there are two levels of filtering:

INPUT byte
IF byte = (wanted message types) THEN
IF byte = (main message type) THEN

It is important to remember that we are using BASIC near the limits of its speed, and if we send too much information for processing the buffers will start to fill up, and we may run into overflow problems. Conversely, if we do not send the information we need to be able to control the devices, then we are overfiltering. The limitations of BASIC begin to become apparent when you are sending lots of running status, controller, and after touch information — which is why we need to filter message types and use buffering.

In many cases, though, we need to pass most of the messages through the program without changing them. Because of this, many of the programs implement a slightly different variation of the structures shown above, which processes only certain types of message, and passes everything else through unchanged.

INPUT byte
IF byte = (wanted message type) THEN

This program structure picks out the message we want to manipulate, and passes any other message through without changing it. If you look at a real segment of program that implements this you can see the way that the structure changes in order to take running status into account:

Part-of MDRAD program:
n = INP(3)
a = n AND &HF0
escape$ = INKEY$
IF escape$ <>"" THEN GOTO leave
IF NOT((a = &H90) OR (a = &H80)) THEN
OUT 3, n
GOTO start
n = INP(3)
OUT 3, a
OUT 3, n
v = INP(3)
OUT 3, v
OUT 3, a + chan
OUT 3, drum_note
OUT 3, v
n = INP(3)
b = n AND &H80
IF (b <> &H80) THEN GOTO do_next
GOTO retest

The MKDRAD program takes an incoming Note On/Off message and uses it to echo a drum note on a different channel. By setting the note and channel to trigger a closed hi-hat it is possible to produce a drum 'backing' from live playing by using velocity to control the drum volume. This sounds better with skilled hands in reality than it does in print!


The last three expeditions have gradually increased the power of the transformations we can make to MIDI messages. Running Status was the first obstacle to be overcome, and then we made our way through the Status Change jungle. This adventure has shown how the concept of mapping allows the changes to be accurately described, and has shown how to change one MIDI message into another.

Only one area remains unexplored — messages concerned with timing information. Prepare for Time Warp next month!


The 'disk' accompanying this series is actually two disks — there are too many programs to fit on one. The two disk package contains all the programs mentioned in this series (plus a few more), and is available from SOS Software, price £7 inc postage.

SOS Software, (Contact Details).


Since most of the programs so far seem to have the same structure (with only minor changes to accomplish the necessary manipulations) it seems obvious to combine them all together into a single big program. There are four reasons why I have chosen not to do this.

Such a program would be so complicated that much of the meaning would be lost. In a series trying to show you how to achieve MIDI processing (and help you understand what is happening) any added complexity would only confuse the issue. The limitations of BASIC also mean that it is not really possible to create a comprehensive MIDI processor.

There are lots of rumours about commercial MIDI processors which are apparently just about to surface. You only need to look at some of the transformations which can already be achieved in some popular sequencers to see how the examples shown in this series could be incorporated.

Some of the strange manipulations shown in this series are included merely to show what is possible — and most importantly, how to do it. Swapping velocity and pitch information may be clever but it is not very useful musically. The whole idea is to show the sort of processing and program structure which can be used to cope with the complexities which have evolved within MIDI.

I do not have the time for an assembler-level [text missing in article.]


Read the next part in this series:
Adventures In MIDILand (Part 5)

Previous Article in this issue

Kawai MX16

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 - Nov 1990




Adventures In MIDILand

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

Feature by Martin Russ

Previous article in this issue:

> Kawai MX16

Next article in this issue:

> Competition: Win An Akai S10...

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 September 2020
Issues donated this month: 0

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

Funds donated this month: £38.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