However, you may wish to write more ambitious programs or modify existing programs. To do this effectively, you must understand how the CMT programs are put together. This chapter describes the various components of the CMU MIDI Toolkit from a system programmer's perspective.
The main areas in which
Timing in CMT is probably the most radical departure from MIDI. Whereas
MIDI sequencers normally tend to talk about time in terms of beats, CMT
measures time in units of 0.001 seconds. This is roughly a tenth of the
smallest rhythmic time deviation we can perceive. The rationale behind this
decision is that not all music is measured in beats, and some music has
several tempi going simultaneously. If everything is converted to time in
seconds, then one can freely combine scores with different tempi and meters
as well as scores with timing notated directly in seconds. Another timing
issue is that the MPU-401, Apple MIDI Manager, and other interfaces allow
the host computer to send data in advance of its actual use. For example,
MIDI commands
can be sent to the MPU-401 with a ``time tag'' that tells the MPU-401 when
to send the data to MIDI OUT. This is a nice feature in that it can help a
slow computer achieve tighter real-time performance. On the other hand, it
is not very suitable for interactive real-time programs in which one
normally wants output to occur immediately after data is sent.
Time tags also have the problem that it is hard to stop a
performance immediately, because several seconds of buffered data
will continue to play after the host computer stops sending data.
CMT does not use time tags; MIDI commands are sent immediately.
CMT allows users to redefine the interpretation of pitch numbers.
Within
An interrupt handler is invoked in
Time is implemented in timer.c, which is an assembly language interface to the standard PC/AT timer hardware. The MPU-401 is not used for timing.
Introduction
In general, CMT programs are assembled from a collection of modules,
where a module is a piece of software that performs a set of
related functions. For example, there is a module for parsing
command lines and another module for recording MIDI data. Modules
usually consist of a single ``.c'' file and a related ``.h'' file.
In the following sections, each module is described, and references
to example uses of the modules are given.
Basic MIDI interface
All programs in CMT that send or receive MIDI use the module midifns.c
,
which provides an interface between C programs and the MIDI interface
hardware.
Interface Design Issues
A few words about the overall design of this interface are in order.
To begin with, midifns.c
is neither a complete interface to the MIDI Interface hardware nor to MIDI. Instead, midifns.c
is an attempt at providing the
intended community of users with a rational interface that supports
experimental, real-time computer music functions. One of the reasons
CMT comes with source code is so that if you disagree with these design
decisions, you are free to modify or extend the system to meet your
requirements.
midifns.c
deviates from the ``conventional'' are the
absence of ``tracks'', the way in which time is handled, pitch
specification, and the (current) lack of external synchronization.
Tracks are a concept implemented in most sequencers whereby
several sequences of MIDI data can be merged in real-time. In some
commercial sequencers, the use of tracks allows the sequencer to avoid a lot
of bookkeeping and sorting when several sequences are to be played at the
same time. In CMT, the Adagio compiler sorts its data, so tracks are not
needed to play multiple sequences together. For example, to play two Adagio
scores simultaneously, one can normally just concatenate the files together
and run Adagio on the new file. This approach has the advantages that an
arbitrary number of sequences can be merged.
midifns.c
, there is a table with two entries for each pitch
number. One of these entries specifies a pitch and the other specifies
pitch bend. When the midi
note
routine is called, it uses the
table to translate the pitch parameter into a MIDI pitch number and a pitch
bend. This translation is normally only enabled if the ``-tune
'' option
followed by a file name is specified in the command line.
Interface Implementation For PC/XT/AT Clones
The mpu.c
module is responsible for low-level MIDI input and output. At present, output is performed synchronously; that is, the processor waits for the MPU-401 device to take the data.
mpu.c
whenever the MPU-401 has data ready. The data is read and decoded to
determine what kind of data it is. If the data is a MIDI message (e.g. MIDI
Note-on), the message is inserted into a circular buffer, which can be read
by either the getbuf
or getkey
routines
in midifns.c
. The buffer provides a communication path between the
interrupt handler and the non-interrupt level of CMT programs; it also helps
prevent lost messages when a burst of MIDI events arrives.
System Exclusive Messages
In an earlier implementation of CMT, incoming system exclusive
messages were put into the buffer just like
other MIDI messages. I then discovered that computers often cannot empty the
buffer as fast as the messages came in. This is fine if messages are short,
but some system exclusive messages are much longer than the buffer. Making
the buffer bigger would penalize programs that are not interested in system
exclusive messages by taking up lots of space. Consequently, the current
system does not put system exclusive messages in the buffer. Instead, there
is a call (midi
bufferbuffer
Previous Section | Next Section | Table of Contents | Index | Title Page