The book includes over a dozen example programs that use the ToolKit as a real-world example of how MIDI applications can be implemented in Windows 95 and Windows NT. The ToolKit includes three DLLs that implement all of the low-level timing, MIDI input and output, and Standard MIDI File support needed for even the most demanding MIDI programs. In addition, seven C++ classes make adding support for MIDI even easier.
Three of the example programs, MidiSpy, SxLib, and MaxSeq, are useful programs as well as excellent starting places for more advanced applications. These three programs can be downloaded here (1.07Mb) so you can see how the ToolKit works.
Here is an overview of each of the programs, along with information about how some of the MIDI features are implemented using the ToolKit. These programs are explored in much greater detail in the book.
MidiSpy
is a MIDI viewer that will display received MIDI events, either in hexadecimal
or as an interpreted trace. It can also echo events out to a select output
device. As a working application, it is useful for testing MIDI instruments,
viewing the output of other MIDI programs (especially when using a multiport
MIDI interface), and as a general-purpose tool for examining MIDI data.
As an example program, MidiSpy implements basic MIDI functions, such as MIDI input, output, and device selection menus. These MIDI device menu lists are implemented using only a few function calls, and allow users to select desired MIDI ports. Opening and closing of MIDI devices is then handled automatically by the menuing code.
For example, to perform MIDI input and output, four TooKit classes are used: CMaxMidiIn and CMaxMidiOut for MIDI input and output, respectively, and CMidiInDeviceMenu and CMidiOutDeviceMenu to implement the input and output menus, like this:
Here, the ProcessMidiData() function passes the received MIDI event (read from the ToolKit DLLs via a call to CMaxMidiIn::Get()), where it is displayed on the application's window and echoed to the MIDI output.
SxLib
is a System Exclusive librarian program that will receive and send sysex
messages and store those messages in binary files. These files, normally
saved with an syx extension, can then be read by many other popular
MIDI programs. SxLib is an excellent starting place when writing a patch
editor or more advanced librarian program. As an example application, it
illustrates how sysex messages are handled in the ToolKit.
Using the ToolKit, each MIDI event is stored in an 8-byte structure,
called a MidiEvent. The structure looks like this:
typedef struct {
MaxSeq
is a multitrack sequencer that allows you to:This program uses all of the techniques that are explored in the book. Here are some examples from the program source code to illustrate how timing and Standard MIDI File support is implemented using the ToolKit.
The current tempo, timing resolution, and timer period can be set in response to menu selections made by the user. For example, to change the tempo the program call the sync device's Tempo() member function:
Here, Tempo() expects the tempo in microseconds per beat, while the TempoDialog dialog box allows the user to enter tempo in fractional beats per minute (e.g., 132.5 bpm). The ToolKit's Convert() function converts the floating point bpm tempo into an integer uS/beat representation.
The MaxSeq program stores MIDI data in tracks, using the CMaxMidiTrack ToolKit class. New tracks are created and attached to the MIDI input and output devices like this:
Any number of tracks can be attached to a particular MIDI output device. During playback, all of the attached tracks are merged automatically by the ToolKit so that they play simultaneously. When recording a new track, the last track attached to the MIDI input device becomes the destination for newly received (and timestamped) events. Once one or more of the tracks contains events, playback is started like this:
Starting record is almost as easy.
Once one or more tracks have been recorded, saving the data to a Standard MIDI File is simple. Here's how MaxSeq does it:
Here, pointers to each of the tracks in the sequence are kept in the pTrackList array. Writing the Standard MIDI File involves no more than creating an instance of CMaxMidiSMF, opening a file for write, attaching each of the track objects, and saving the file.
Reading a file is also simple.
All of the features of the ToolKit are explored more thoroughly in the book. Over a dozen example programs build in logical progression from the simplest MIDI tasks to full-featured, useful applications. The operation of each example is explained in detail, as is the internal working of the ToolKit itself. And all of this code is supplied for you to use, modify, and cannibalize.