Home -> Magazines -> Issues -> Articles in this issue -> View
Lab Notes: MUS1 | |
With the New Miracle Ingredient - STGArticle from Polyphony, April/May 1978 |
With the exception of the bare-bones listing of POLY 1.0 that ran in the last issue, we haven't looked at any software — mainly because there was little to examine.
But MUS1 was just recently finalized, so that situation is beginning to change.
MUS1, for the benefit of those of you who haven't been waiting for it for the last six months, is what many would call "system firmware" — and since that has the sort of technical ring to it that tends to make things interesting, we'll call it that, too.
In almost any computer application there are some programs which, for one reason or another, are best handled as firmware — a name that these days means not software (which must be loaded from some storage media external to the computer) and not hardware (a permanently wired collection of gates, etc. which cause a specific, set sequence of actions to take place) but something betwixt and between; most usually, software that is contained in a PROM somewhere.
The most obvious firmware is a monitor program such as PIEBUG. Since this program is the thing that allows for the entry of data and instructions into the memory of the computer in the first place (as well as usually providing whatever de-bugging and editing features the designer thought were important and/or had room for), it is at least inconvenient to have to load it every time it is needed. Much better to have it in a dedicated PROM where it is always available for immediate use.
The firmware of MUS1 is roughly analogous. These are universally useful routines that, with rare exceptions, will be used with everything we do musically. It's a waste of tine and resources to have to load them to RAM from tape (or worse yet, manually) every time they're needed. A PROM is their happiest home. In our 8700 Computer/Controller, MUS1 is a 1702A PROM that occupies the address range $D00-$DFF (IC-17).
Examples? OK, the keyboard reading routine (LOOK). It isn't particularly long or complicated (a little over 30 bytes) but we're going to need it every time we turn on the system — even if it isn't used to read the keyboard, it's the thing that our protocols dictate will be the tempo-determining element in the system (based on the clock rate of the encoder). At some future date the occasion may arise when we can examine this in detail. Today, it's not the point.
The QuAsh drivers (called NOTE) — same thing — we're going to need them for almost everything we do. Why bother to load them?
In addition to these two routines, MUS1 also contains:
INIT: an initialization routine that takes care of setting various variables and buffer areas to a known, acceptable state (as opposed to the random numbers they will contain when power is first applied.)
POLY: essentially the polyphonic (I still prefer polytonic) allocation algorhythm from POLY1.0, except refined somewhat to take less memory space.
TRGN: The new miracle Ingredient — Software Transient Generators (STG). A routine that will serve as a software substitute for ADSRs.
OPTN: A very simple option selecting program that allows the remaining firmware of MUS1 to be tied together into a 16 voice polyphonic synthesizer with or without software transient generators — without having to load any additional software (though several parameters will need to be initialized manually).
All of this is pretty straight-ahead code that should be understandable from the documented listing that appears at the end of this article — you may need to refer back to previous articles in this series for background information; "In Pursuit of the Wild QuAsh" (reference Polyphony, July '77) and "What the Computer Does" (reference Polyphony 4/76) would be particularly useful ones.
Two exceptions, NOTE and TRGN, need some additional explanation — they introduce some new ideas.
In an embryonic form, NOTE was a part of POLY 1.0. It is the responsibility of this routine to take individual entries from the output buffer area (NTBL), add to it the corresponding entry from the Transpose buffer area (TTBL) and output the results to the QuAsh channels. Some aspects of the significance of the addition that takes place will be seen when we look at TRGN — for now, it will suffice to say that this will be an extraordinarily handy convention in a number of cases.
A more important function of NOTE is to make sure that what comes out of the QuAsh channels has no annoying glitches that may be artefacts of the D/A and multiplexing process. In an earlier story, we looked at one of the annoyances — the fact that our 8780 D/A, though quick, takes a finite amount of time to change from one value to the next and if appropriate settling time is not allowed between writes to the QuAsh channels we will be able to hear the changes as a slight "buzz" in each of the channels. The solution here is to output the data first to a "dummy channel" that is occupied solely by the D/A, with no corresponding QuAsh, followed immediately by a write of the identical information to an output which does correspond to a QuAsh channel. The first write allows the D/A to settle while the second strobes the settled output into the appropriate QuAsh channel.
And here we come face to face with the next problem; the QuAsh really need some settling time since they are at their heart nothing more than an RC circuit.
As long as we are thinking in terms of small systems (8 output channels or less) this is not a big problem since it can be dealt with simply by delaying after writing to one QuAsh but before setting up the next. If the delay is not long enough, we will hear changes from one value to the next not as an instantaneous change, but rather as a series of steps from the initial value to the final one:
In larger systems, this constant delay approach is not a practical solution because there is not enough time during alternate "dummy" scans of the keyboard (the time which our conventions allow for processing, output driving, allocations, etc.) to allow all of the output channels the luxury of a delay. The time comes for the keyboard to be read again (or other things to happen) and the processor is still busy waiting for all of those QuAsh to get to the right value.
The key to the solution of this problem is to notice that there is really only one set of circumstances under which the long QuAsh-settling delay is required, and that's when the output of one of these channels must change from one value to another (which happens only a small percentage of the time) and then, only when the glide of the channel is turned off. (If the glide is on, its integrating action will smooth out the steps; and, in fact, a short write time is preferable here since it will serve to increase the time required for the glide.)
The actual solution is what I feel we should call "DYNAMIC QuAsh DRIVERS" — a small block of programming, more or less in the middle of NOTE.
This part of the program first checks to see if the glide control bit (the most significant bit of the data just written to D/A and S/Hs) was turned on or not. If we are in "glide mode," no delay is required so the program immediately goes to see if there are any channels left to write; if there are, it services them.
If the glide is not on, we have a candidate for dynamic operation so the dynamic mode switch is checked (more later) and if this option is selected the current data is compared to the data that was previously written to this channel (requires a new table that we've generated called "LAST") and if they're different (a change), the program goes into the delay that allows the output of the QuAsh to instantaneously (apparently) step from its previous value to the next one. The new value is saved in LAST (for use next time) and if there are more channels to do — it does them.
Here we begin, for the first time, to replace some of the elements that constitute traditional synthesizer hardware with software that performs the same function (hopefully as well, or better) with less costly hardware. STGs are a good place to start because they're not super difficult to implement.
Just like their hardware equivalents, STGs respond to a note which has just been triggered (pressed on the keyboard) by producing a voltage that rises at a controlled Attack rate. After reaching some peak value, the voltage then drops at a Decay rate until it reaches a pre-set Sustain level where it stays as long as the note remains triggered. When the key is released, the voltage drops to its lowest level at the Release rate.
Computing the number which represents the current value of the transient is only slightly more complicated than adding, subtracting and comparing.
Unlike an ADSR, an STG has no knobs to set, in their place you enter numbers setting Attack rate, etc. into the computer.
Perhaps the biggest problem having to do with STGs is deciding where they should come out. Oh, the QuAsh channels, obviously; but which ones? Of the numerous possibilities, we've selected the convention of having pitch setting voltages (those that correspond to notes) and transient voltages come from alternate QuAsh channels, primarily because this will work nicely with some stuff under development (or consideration, at least), without making obsolete all of the hardware that we've accumulated up to now.
This implies two distinct modes of operation; the first in which the STGs are not asserted and POLY assigns notes to sequential QuAsh channels; and, the second mode (STGs on), in which notes are assigned by POLY* to the odd number QuAsh channels (first, third, etc.) while transients are produced at the even number outputs (second, fourth, etc.).
* Note that POLY checks to see if the STGs are turned on as it assigns notes to outputs.
The note produced at the first QuAsh output has a corresponding transient happening at the second output, and so on. Just as if the trigger from the first channel were patched to the input of an ADSR whose output was somehow tied to the output of the second QuAsh channel.
This would seem a good place to mention (in case it's not already obvious) that in this implementation all of the STGs produce the same kind of transient, and for the kinds of things that we're doing now, this is how it should be. It may also be worth mentioning that while the transients are all the same, they are totally independent where following the triggered and released states of their respective note channels is concerned.
There are also some internal details which muddy the STG waters. For instance, a key that is currently down may require a transient function that is either in the Attack cycle (increasing) or Decay/Sustain cycle (decreasing or holding) depending on its past history (had it already peaked?). Somewhere we need to save information on which cycle the transient is actually in.
Another, somewhat interrelated, problem concerns the smoothing of the transient waveform. Under most conditions, the glide of the QuAsh channels that are being used as transient outputs should be turned on so that a smoothly increasing or decreasing function is produced. But, the glide can't always be on because that would limit the maximum attack rate.
Without having the space to cover it entirely, I can only state that the solution to both of these difficulties lies in the use of the Transpose table and remembering that the data stored in TTBL entries is added to the output parameter in NTBL (where we're storing the actual current value of the transient) before the output operation takes place. Note also that while the data in NTBL is manipulated extensively by POLY and TRGN (as they calculate, allocate, — regurgitate?) TTBL is untouched by computer hands, and this makes it an ideal place to save control type functions. Not only transpositions, but a place that glide and trigger bits and such can be permanently set.
These locations are so handy for this application that in TRGN they have been re-named CWRD (Control-Words... but do not be confused, this is still our old friend TTBL and has no relationship at all to the System Control Word-CTRL) and it is here that we keep track of the A/D/S state of each of the transient channels.
Also, to help me keep things straight in my own mind, the NTBL bytes that are used to store the current value of the transient have been re-named PARM (parameter); but, again, this is the same physical area as NTBL.
Perhaps the best way to begin an essay on how to use MUS1 is to state one of the functions that it was devised to perform. As you are no doubt beginning to realize, we've carefully developed a system that will have applications far beyond what we've discussed to this point. It's complex; and while the complexity implies unmatched versatility, it undeniably has its intimidating aspects.
At one level of use, MUS1 should reduce this intimidation by giving the user an instrument with a specific (though within certain limits alterable) personality the instant that it's turned on, without having to hassle around with loading any additional programs (success) or variables (well...)
Also, these program modules should be written so that they easily interface with future expansions of the system, either hardware or software, so that, when needed, they can be accessed by programs offering distinctly different personalities (success here maybe — only time will really tell).
While we've reduced the intimidation, we've not eliminated it entirely because even when using MUS1 as a stand-alone personality there are some variables which must be initialized before you begin to play — some information that the system must have in order to operate properly. This data could be part of the PROM, but not without significantly compromising versatility.
For instance, we've mentioned in passing a couple of times the System Control Word-CTRL. This is a single word in the computer's RAM memory at location $0E8.
It is most helpful to visualize CTRL as a collection of eight "switches", each bit representing one switch. To MUS1, only two of these switches have any significance — D7, which turns the STGs on and off, and D6, which enables or disables the dynamic mode option. The rest are reserved.
Every time you power up the system, CTRL must be set so that the desired options are selected — there is no default setting that is part of MUS1. If you want dynamic mode (which you should, for now) then bit 7 should be turned on. If you want STGs, bit 8 must be set.
The 4 possible combinations of these 2 bits then have the following significance:
binary | hex | action |
00000000 | $00 | STGs off; dynamic mode off |
01000000 | $40 | STGs off; dynamic mode on |
10000000 | $80 | STGs on; dynamic mode off |
11000000 | $00 | STGs on; dynamic mode on |
CTRL is not the only variable which must be initialized manually. There's also:
Setting PEAK to $BF (non-percussive) produces this result:
Because the glide is now on during the entire attack cycle and the Decay and Sustain portion of the transients are eliminated. Straightforward stuff, really.
We need to cover an example of system set-up before we wind up, but first must notice that the effect of having the PEAK parameter are far more far-reaching than we've been able to cover in detail. A quick example:
ADSR parameters set to $10/$04/$20/$01 and PEAK containing $3F will produce this kind of transient:
which, when heard, starts out with a non-percussive kind of "swell" with a percussive "pip" added at the last instant before the transition to the Decay and Sustain cycles. This would seem to be a unique and useful transient that isn't produced by traditional ADSRs.
Along the same lines, the TSGs can be considered to be "better" than our hardware ADSRs in that they need not finish the Attack cycle before transitioning to the Release state. If a key is released before its transient has gone all the way to PEAK, the transient immediately switches to the release state. This is frequently called "muting' and it offers the possibility of effective control of expression directly from the AGO keyboard.
So, we've gotten our hands on a MUS1 PROM and are ready to start doing things. What has to be done first? Really very little.
First, the System Control Word, Output Delay and number of hardware channels available must be set. For example:
keystrokes | explanation |
0-E-8-DISP | sets monitor pointer to $E8-CTRL |
C-0-ENT | sets $E8-asserts STGs dynamic mode |
3-0-ENT | sets ODLY value |
0-2-ENT | sets output channels at 2 |
these entries define the personality of the instrument as a 2 voice polyphonic synthesizer (notes from channels A & C) with software transient generators (which appear at QuAsh channels B & D).
Next, we must set the transient parameters to the desired values:
keystrokes | explanation |
0-B-A-DISP | sets monitor pointer to $BA — ATCK |
3-F-ENT | sets shortest attack |
0-4-ENT | sets moderate decay |
2-0-ENT | sets moderate sustain |
0-1-ENT | sets slowest release |
3-F-ENT | percussive mode |
and you may recognize these parameters as being those that we examined in the illustration earlier.
Finally, we simply begin running the program:
keystrokes | explanation |
D-0-0-DISP | sets monitor pointer to beginning of OPTN |
RUN | presto — the program runs |
A typical patching configuration that would be consistent with these entries would look something like this:
Oh, yes — I almost forgot. OPTN, like POLY 1.0 , uses the 8700 keyboard to control two important functions. While OPTN is running, touching key 0 of the control keyboard will cause the entire system to be re-initialized. Not the entries that we made manually — those remain unchanged, but all the notes and transients go immediately to zero level.
Similarly, touching key #1 produces a tuning function that makes the synthesizer respond as if all the channels were seeing the second C on a three octave keyboard held down. The transients go, the notes play, etc. After tuning, be sure to re-initialize the system by touching control key #0.
I prefaced one of the earlier paragraphs with "at one level of use." In all of the preceding words, that's all that we've examined — one level of use (the simplest and most obvious level — at that.) . I've also referred in the past to "software modules" which can be strung together in different ways (just as can hardware modules) to produce different effects and personalities. MUS1 is the first set of these modules.
With more regret than you can imagine, I haven't the space here to go into all of the implications of this (even if I knew them all, which I'm sure I don't).
Providing you're more than just casually interested, you should spend some time trying to understand how MUS1 works internally (there are numerous different entry points to the routines that we haven't covered — for instance). I believe that the time investment will be wisely made.
PC Notes |
Apple Notes |
Software Support - Hints, Tips & News From The World Of Music Software |
Atari Notes |
When Is A Computer |
PC Notes |
PC Notes |
PC Notes |
Amiga Notes |
Software Support |
Card Tricks - Music On The PC |
Amiga Notes |
Browse by Topic:
Lab Notes: Blessed are the Seque
(PL Nov 78)
Lab Notes: The Polyphonic Synthesizer
(PL Feb 78)
PAIA 8700 Computer/Controller
(EMM Apr 81)
Browse category: Sequencer > PAIA
Feature by John Simonton
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!
New issues that have been donated or scanned for us this month.
All donations and support are gratefully appreciated - thank you.
Do you have any of these magazine issues?
If so, and you can donate, lend or scan them to help complete our archive, please get in touch via the Contribute page - thanks!