MIDI Xpander instructions

This is the second of two features by Scott Mackie on the MIDI interface - his introduction and guide to building your own MIDI interface were contained in AMPLINEX 006.

MIDI Performance Code for AMPLE

Scott Mackie
Having, I hope, constructed your MIDI interface and got it running, you can now start on the code needed to make AMPLE run as a MIDI expander.
The 'Xpander' code comes as two parts: an assembler i/o section and an AMPLE handling routine. This has the benefits of machine code speed and AMPLE flexibility. I originally wrote the code entirely in AMPLE but it was really too slow to use properly, and resulted in arpeggios on chordal work - nice effect, but pretty unusable!
Although the assembler routine has its limitations (it slows down a bit after more than 5 notes are pressed simultaneously) it is much more efficient than AMPLE. Chordal work is still slightly slurred but the overall performance is much better.
The code is positioned in memory at &900 and &D00, with buffers at &A00 and &C00 (which unfortunately will corrupt the Staff editor - sorry!). At &D00 is the interrupt code which loads the data from the 6850 (the chip at the 'core' of the MIDI interface) into a circular buffer and updates a pointer. It also 'echoes' the data to the MIDI Out to simulate a MIDI Thru. There is a very small propagation delay, but this almost unnoticeable.
The code at &900 is the data handler. It 'chases' the interrupt routine around the loop, reading the data back out and updating the output pointer accordingly.
This method has the benefit of not missing any data, but the performance can be slowed slightly under heavy data input. The buffer size is a complete page, i.e. 256 bytes, which should be more than enough - if it isn't, you're either Rick Wakeman or playing with the system exclusive dump on the synthesiser!
After reading the buffer, the assembler code interprets the data and stores it accordingly. I use the Econet workspace (&90 to &9F) as variable space, so I'm afraid if the system is to be used on Econet some rewrites may be needed.
The workspace is configured as:
&90: Input pointer. Where the latest input data is in the buffer. Updated by the interrupt routine.
&91: Output pointer. Where the program has got to in the buffer. Updated by the foreground program.
&92: ID byte for the following data 0: Noteon/off 1: Pitchbend 2: Patch change
&93: <ID dependant data> &94: <ID dependant data> &95: Voice to be used for current event &96: Blank &97: . : Voice assignment data held here. . : 128 indicates unused voice &9F:
The assembler routine also provides voice allocation routines for AMPLE, including a keysplit system. When a note is pressed, the code goes to a lookup table at &C80, which contains the details of the currently setup keysplit. The code finds the current zone the key pressed is in and then allocates the voice accordingly. This system allows multi-timbral (i.e. using more than one instrument) music to be played across the entire range of the keyboard.
When a free voice is found for the note to be played on, the note number is placed in the table between &97 and &9F for future reference. A value of 128 indicates that the voice is clear. When a Noteoff is issued, the code checks the table for the note number and places a 128 in the voice location it finds, freeing that voice for future use.
A simple wrap-around system operates so that if the number of notes played in any one zone exceeds the maximum allowed, the overspill notes are played on the first voice of the split. This compromise seems to be the best solution to a rather grey area of synthesiser programming.
Having completed all the data preparation, the assembler routine returns to AMPLE, where the header block is checked and the relevant routines called. The notes are played using the ACT command, and a rest is played for a Noteoff. This allows envelopes such as Swell and Soft to complete.
If required, the code will release a channel to be used again, without issuing a rest. This is achieved by use of the MNOTEOFF command. OFF MNOTEOFF stops Noteoffs issuing rests and is very useful with envelopes that actually tail away to zero, as the sound is more continuous with no rests being issued.
Upright, in particular, is very effective like this and can be played much like a normal piano. A foot pedal can be used to trigger this, connected to the fire button for Joystick 1 on the Analogue port. A simple push-to-make footswitch will do, and the code will detect its depression and act accordingly (see the 'help!' information in the actual program about this).
Right, having waded your way through all that information, how do you use the code?
Having loaded the file F.Xpander, try the following:
RUN
The disc drive should run and load in the file 'F.Xcode'. Set the transmit channel on your synthesiser to channel 1 and enable its MIDI output if required. Pressing a few keys on the synthesiser should now result in AMPLE playing Upright at the right pitch.
If this doesn't work, check that the interface is paged into the right position in memory. The details about this are in the assembler listing file 'F.Xsource' which is included on this disc.
Also included in the 'Xpander' program is an AMPLE word called 'test' that will print out all the data arriving at the MIDI port. This should help with debugging if there's a problem. With luck, the code will work and the fun can start!
Holding the SHIFT key down while pressing a note on the master keyboard should take you back to the AMPLE prompt. The command 'RUN' is intelligent and checks to see if the NMI code is still present. If not, the code will boot in the NMI routines again from disc. If any problem should occur, just press BREAK and type 'RUN' again. This should cure any minor problems (especially if a disc is accessed, as this will overwrite the MIDI interrupt code).
Any sound can be used with the keyboard, just by defining the maximum number of MIDI voices, i.e.
4 MSINGLE viola4
will provide 4-note polyphony with a 4-channel viola sound.
Changing the MIDI receive channel is easy. All that you have to do is type, for example,
6 MCHAN
to set the interface to channel 6. The channel is defaulted to 1 initially.
The MIDI interface also accepts velocity information so the sounds produced will be responsive to velocity data. I haven't tried this feature yet as I can't afford a velocity-sensitive keyboard, but I hope it will work!
Moving the pitch bend wheel on your synthesiser should result in AMPLE changing the pitch of the sound. Incidentally, there's no reason why the pitch bend wheel should cause the pitch to change. It could alter the stereo position, volume, or voice parameters if required. Be experimental with the AMPLE code!
Issuing a patch change from your synthesiser should cause AMPLE to select a new sound for the voices. Edit the word 'Mpatchc' to suit your own tastes and sounds. The word is set up at the moment to provide a general selection of patches.
The last topic to be covered is key splits. All key splits do is to allow different instruments to be used depending on where the note pressed is on the keyboard. Up to 8 instrument zones can be defined, but within the confines of 8 notes of polyphony. For example, you can have a split of 2+6, but not 1+2+6 because this means having to use 9 voices, exceeding the internal limit for AMPLE. The two commands to drive the key split definition process are MSPLIT and KEYSPLIT.
If you type
MSPLIT
the screen will clear and you will be prompted for the number of zones to be used across the keyboard. Having typed this in, you will then be prompted for the number of notes to be used in zone 1 (which is the lowest zone in the keyboard). The code will then wait for you to press the key on the MIDI keyboard that indicates the top of the zone. This definition process will continue until all the zones have been defined.
When MSPLIT finishes, it calls KEYSPLIT and prints out a list of numbers. This sequence of numbers is the input to the routine KEYSPLIT. This is the raw (very!) routine for processing splits. If that exact key split setup is needed again then the string of numbers output can be used to call KEYSPLIT, without having to go through the process again. The words mix1, mix2 and mix3 all illustrate this technique and should be studied in order to fully understand this topic.
A complete listing of all the words used is included in the AMPLE file 'F.Xpander'. Just type 'help!' to get the information.
And now for what the code doesn't do! The code will not allow you to play along with existing music in AMPLE, although I am working on that. I'm afraid this is due to the need for a quick response time in the input routine (the program loops in the assembler domain to save time jumping between AMPLE and the code). It also forbids use of Echo for, I presume, the same reason. Maybe some AMPLINEX members can advise me on this aspect of the code.
Apart from these things, the code does run reasonably reliably and doesn't seem to be prone to leaving 'hanging' notes.
I hope these articles have provided some AMPLINEX members with enough material to experiment with MIDI. The basic code works well, but changes can be made to it to allow further MIDI data to be processed, such as modulation or aftertouch. Any comments on the code or queries could be sent to AMPLINEX or, if preferred, to myself at the address below.
Scott Mackie 48 Milford East Kilbride GLASGOW G75 9BU
Note: An error was spotted in the previous article with reference to the AMPLE hardware paging addresses. It does actually map into the whole of the &FD page, between page numbers &30 and &3F and not &FD30 and &FD3F as stated.

Related files on this disc:
F.Xpander - 'Xpander' AMPLE program
F.Xcode - 'Xpander' machine code
F.Xsource - assembler source for the 'Xpander' machine code (in *EXEC format)

Published in AMPLINEX 007, September 1988