Interactive
Music Sequencer Design
Making a Computer
Music Language
Event
Blocks
Music
can be described as events or commands occurring over time. We can
build our music command language with "event blocks" composed
of three elements: time, event type, and event details. The time is
stored relative to previous events and is called a delta-time, the
event type is identified with a number, and the event details are
zero or more parameters that are defined by the event type.
Figure
1 - Event Block
| Delta-Time |
Event
Type |
Event
Parameters |
With
this basic design we can describe any groupings of events and time
intervals. Building our computer music language is now a task of choosing
how to store the delta-time, what event types, and what details are
needed for each event type.
MIDI
(Musical Instrument Digital Interface) Music
The MIDI specification has been around for a long time. Most
composition and sequencing software provides compatibility with MIDI
input and output ports, and these products also provide options to
save and load MIDI files.
Since
the MIDI specification defines a delta-time storage format and a useful
set of event types and parameters, we should start with this model
as a reference. This will make it easier to convert the MIDI language
to our custom music language.
Keep
in mind that our goal is to create music directly on a machine with
audio capabilities, so we want to take what is useful from the MIDI
design, but not restrict ourselves to its features. We are also likely
to get music from composers in the MIDI file format, so we will want
to convert the MIDI file music language to our own custom language.
MIDI
Events
The MIDI specification defines several events called the channel
voice messages, and there are also meta-events defined in the MIDI
file format 1.0 specification. Some of the meta-events simply contain
text string data. I summarize the MIDI events and meta-events we are
interested in Table 1, Table 2, and Table 3.
Table
1 - MIDI Channel Voice Message
| Event
Type |
Event
Parameters |
| Note
Off |
Note
Number |
| Release
Velocity |
| Note
On |
Note
Number |
| Attack
Velocity |
| Pitch
Wheel |
Pitch
Bend LSB |
| Pitch
Bend MSB |
| Control
Change |
Controller
ID |
| Controller
Value |
| Program
Change |
Program
Number |
| Poly
Key Pressure |
Note
Number |
| Pressure
Value |
| Channel
Pressure |
Pressure
Value |
Table
2 - Basic MIDI Event Types
| Meta
Event Type |
Meta
Event Parameters |
| End
of Track |
|
| Set
Tempo |
Tempo
Number |
| Time
Signature |
Numerator |
| Denominator |
| MIDI
Clocks per Metronome Click |
| 32nd
Notes in a MIDI Quarter Note |
| Key
Signature |
Sharps/Flats
Indicator |
| Major
or Minor Indicator |
Table
3 - Text MIDI Event Types
| Meta
Event Type |
| Text
Event |
| Sequence/Track
Name |
| Instrument
Name |
| Lyric |
| Marker |
| Cue
Point |
Of the
MIDI channel voice messages, the control change event is unique in
that it specifies an additional event identifier, the controller ID.
Examples of common controller ID numbers are 7, which refers to volume
and 10, which refers to pan position. Many controller ID numbers are
not commonly used and we can have musicians insert control change
messages with controller IDs to mark the music in special ways.
The
basic meta-events listed give us ways to get time organization details
and tempo changes. The text meta-events give us ways to get custom
data embedded in strings. Composers can put special track settings
in the track name strings or special kinds of playback commands in
lyric strings. These methods will save us from having to write custom
tools for composers when deadlines are looming.
MIDI
Channel and Tracks
The "channel" in MIDI channel voice messages refers
to the fact that these messages are sent with a channel number from
1 to 16 (0 to 15). The channel number is used by MIDI devices to route
commands. We are not routing commands to MIDI gear, so we won't talk
about channels anymore. Type 1 MIDI files have any number of tracks
where each track contains a series of event blocks. It is the track
concept that is useful for our data organization.
Sequences,
Tracks, Events, Instruments, and Voices
This is where we leave the world of MIDI and talk about our
custom music sequencer language. A quick summary of the terminology
used in the rest of this paper is in order: A Sequence is a collection
of Tracks that run simultaneously. Each Track is a sequence of Events
that control the current Instrument. Certain types of Track Events
will turn on and off Voices of the current Instrument. Some types
of Track Events will modify all active Track Voices. You can think
of an Instrument as the default settings given to a Voice that is
turned on with a NoteOn Event. I will present a list of class definitions
that display this structure in the implementation section.
Event
Type Possibilities
Table
4 lists many event type ideas so you can get a taste of the possibilities.
There are a lot of details that could be discussed ast to how these
event types might be implemented, but I will just mention the options
here and move on to the other parts of this discussion.
Table
4 - Event Type Ideas
| Event
Type |
Notes |
| Basic |
These
are like traditional MIDI events. |
| Note
Off |
Note
Number |
| Release
Velocity Optional |
| Note
On |
Note
Number |
| Attack
Velocity |
| SetTrackVolume |
Value |
| SetTrackPitchBend |
Value |
| SetTrackPan |
Value |
| SetTrackEffect |
Any
Effect Type |
| Value |
| SetInstrument |
Program
Change |
| Track
End |
Loop
to Start if the Sequence is Flagged |
| |
|
| Test
Values |
We
can have an array of test values at the sequence level or track
level (the value could have a name and have the string mapped
to a lookup number) |
| Set
Test Value |
Sequence
or Track Test Value |
| Test
Value ID |
| Value |
| Inc
Test Value |
Sequence
or Track Test Value |
| Dec
Test Value |
Sequence
or Track Test Value |
| DecZ
Test Value |
Do
Not Decrement Below Zero |
| |
|
| Advanced |
|
| SetSequenceVolume |
Value |
| SetSequenceEffect |
Any
Effect Type |
| Value |
| SetListenerWorldPosition
|
Sets
3D Pan and Volume |
| SetTrackWorldPosition |
Sets
3D Pan and Volume |
| SetInstrument
If |
Sequence
or Track Test Value |
| Position
Marker |
Marker
Name (String Mapped to Number) |
| Jump
to Position Marker |
Marker
Name (String Mapped to Number) |
| Jump
to Position Marker If |
Sequence
or Track Test Value |
| Marker
Name (String Mapped to Number) |
| |
|
| State
Change |
Fades,
Ducking, Mute Groups |
| Change
Sequence State |
Set
immediate state or set a target state and interpolation time |
| Change
Sequence State If |
Sequence
or Track Test Value |
| Change
Track State |
Set
immediate state or set a target state and interpolation time |
| Change
Track State If |
Sequence
or Track Test Value |
| Change
Voice State |
Set
immediate state or set a target state and interpolation time |
| Change
Voice State If |
Sequence
or Track Test Value |
| |
|
| Arrangement |
|
| Jump
to Track |
Jump
to a New Track Data |
| Jump
to Track If |
Sequence
or Track Test Value |
| Gosub
to Track |
Jump
to New Track Data, Returns When Done |
| Gosub
to Track If |
Sequence
or Track Test Value |
|
|
| Callback |
|
| Callback |
Calls
Game Code, Could Change Test Values |
| Callback
If |
Sequence
or Track Test Value |