Moxc: Real-Time Programming Package

It is the cause, it is the cause, my soul:
Let me not name it to you, you chaste stars!
It is the cause.
Othello V.2

What Is Moxc?

Moxc is a set of C procedures to help the programmer write programs that perform many tasks simultaneously. The most important procedure is called cause, which allows you to make things happen not now, but in the future. Moxc is a compatible extension of all the programming constructs you learned in the last chapter.

Moxc is derived from a system called Moxie, written by Douglas Collinge of the University of Victoria. The original Moxie runs on a Synclavier I, and another version exists as an extension to the Forth language.

An Example

The following example uses Moxc to implement a simple performance instrument. A blow-by-blow commentary follows the example. Only the important lines are listed here. For a complete but still fairly simple example, see the file moxctest.c.
void keydown(int c, int k, int v)
{
    pnote(k+12, 100);
}

void asciievent(char c) { if (c == 'q') { quit(); } }

void hello() { gprintf(TRANS, "hello\n"); cause(300, hello); }

mainscore() { hello(); }

The procedure keydown is called automatically by Moxc whenever a keyboard key is pressed. Three parameters, the MIDI channel, the key number, and the key velocity are passed to keydown. When a key is pressed, k will have a value where 60 corresponds to middle C, 61 to C-sharp, and so on.

The procedure pnote takes two parameters: pitch and duration, and it is the same procedure described in the last chapter (see Section ``Producing Chords''. Notice how I added 12 to k in the first parameter position to make the pitch always one octave higher than the key that was pressed. The second parameter is always 100, for a duration of one second.

The next procedure definition is for asciievent. This procedure is called whenever a character is typed at the computer. The character typed is passed as a parameter to asciievent. To denote a character value in C, you enclose the character in single quotes as shown in the example. The asciievent in the example only responds to one letter, q, which results in a call to quit, a built-in procedure that tells Moxc to halt execution. Notice that 'q' is written in single quotes to denote the letter ``q''. Without quotes, q would refer to a parameter or procedure name.

With just these two procedures, a simple instrument has been implemented which doubles every note up one octave, and holds the octave for one second.

Moxc provides a few more features. Look at the next procedure definition, for hello. The hello procedure prints hello\n on the terminal. (The \n code at the end means type a newline, putting the cursor at the beginning of the next line.) The next line is the interesting one: cause(300, hello); means that Moxc should, after 300 time units, cause the procedure hello to be called. In other words, travel 3 seconds into the future, call hello, and return to the present. In effect, we have realized time travel in the computer! If this makes you uncomfortable, what really happens is that Moxc saves a record of the procedure to be called, the time to call it, and any parameters that should be passed to it. When the time comes, the call is made automatically by Moxc. In the case of hello, the effect is that every 3 seconds, hello is printed on the screen, and the performer may be simultaneously playing the keyboard. Why does hello print hello repeatedly? Because after each printing, hello uses cause to schedule another call to hello in the future. This call will schedule yet another call, and so on.

How does hello ever get started? It won't, unless someone calls it for the first time. This is done in mainscore, which is always called once at the beginning of the program, and therefore must be present in your program.

More About cause


Previous Section | Next Section | Table of Contents | Index | Title Page