MIDIFileParser
data structure. This structure keeps track of the overall score parameters as the MIDI data is translated into a Juggler object. These parameters include values such as the clocks-per-second tempo set in the MIDI score. The MIDIFileParser
data structure is defined in the midifile.h header file, and should never be written to directly by a task, the MIDI loading calls use it for their own internal purposes.
MIDIFileParser
data structure and a Juggler sequence in place, you can load a Format 0 MIDI score file using this call:
int32 MFLoadSequence( MIDIFileParser *mfpptr, char *filename, Sequence *SeqPtr )
*mfpptr
, a pointer to the MIDIFileParser
data structure used for translating the MIDI score; *filename
, a pointer to a character string containing the name of the MIDI score file; and *SeqPtr
, a pointer to the Juggler sequence where the translated MIDI score should be stored.
When MFLoadSequence()
executes, it opens the MIDI score file, translates its contents using the MIDIFileParser
data structure, and stores the translated MIDI messages in the specified sequence as MIDI events. It writes information about the MIDI score in the MIDIFileParser
data structure. If successful, MFLoadSequence()
returns 0; if unsuccessful, it returns a negative value (an error code).
To load a Format 1 MIDI score file, you must have a Juggler collection in place (instead of a Juggler sequence used for a Format 0 score). The collection should be empty. Use this call to load the file:
int32 MFLoadCollection( MIDIFileParser *mfpptr, char *filename, Collection *ColPtr )
*mfpptr
, a pointer to the MIDIFileParser
data structure used for translating the MIDI score; *filename
, a pointer to a character string containing the name of the MIDI score file; and *ColPtr
, a pointer to the Juggler collection where the translated MIDI score should be stored.
When MFLoadCollection()
executes, it opens the MIDI score file and translates its contents using the MIDIFileParser
data structure. It creates a Juggler sequence for each track in the MIDI score, and stores the translated contents of each track in a separate Juggler sequence. MFLoadCollection()
writes information about the MIDI score in the MIDIFileParser
data structure.
Note that if MFLoadCollection()
processes a Format 0 MIDI file, it treats it as a
single-track Format 1 MIDI file and turns it into a single-sequence collection. This collection requires more processing overhead than the same score loaded by MFLoadSequence()
as a Juggler sequence. If your MIDI score has only one channel and you can save it as a Format 0 file, then you should always load it as a sequence to save processing overhead.
If successful, MFLoadCollection()
returns 0; if unsuccessful, it returns a negative value (an error code).
If you use data streaming to import the image of a MIDI score file, then use this call to turn the file image into a MIDI collection that can be played by the Juggler:
int32 MFDefineCollection( MIDIFileParser *mfpptr, char *Image, int32 NumBytes, Collection *ColPtr)
*mfpptr
, a pointer to the MIDIFileParser
data structure used for translating the MIDI score; *Image
, a pointer to the file image (which should be a string of bytes); NumBytes
, the size of the MIDI file image in bytes; and *ColPtr
, a pointer to the Juggler collection where the translated MIDI score should be stored.
When MFDefineCollection()
executes, it turns the MIDI file image into a collection just as MFLoadCollection()
turns a MIDI file into a collection. MFDefineCollection()
returns 0 if successful, or a negative value (an error code) if unsuccessful.
SetObjectInfo()
call as described in Creating and Playing Juggler Objects."
The code fragment in Example 3 shows how a collection containing an imported MIDI score is set to point to the score context. CollectionPtr
is a pointer to the collection; SconPtr
is a pointer to the score context.
Example 1: Pointing to a score context.
After the pointer to the score context is set, the object's interpreter procedure can pass the pointer along to other MIDI calls as they execute the MIDI events in the object.
/* Define TagList */
Tags[0].ta_Tag = JGLR_TAG_CONTEXT;
Tags[0].ta_Arg = (void *) SconPtr;
Tags[1].ta_Tag = TAG_END;
SetObjectInfo(CollectionPtr, Tags);
The Interpreter Procedure
When MFLoadSequence()
and MFLoadCollection()
turn a MIDI score into a Juggler object, all translated sequences contain a pointer to an interpreter procedure. This call is the MIDI interpreter procedure:
int32 InterpretMIDIEvent( Sequence *SeqPtr, MIDIEvent *MEvCur, ScoreContext *scon )
*SeqPtr
, a pointer to the sequence for which it interprets; *MEvCur
, a pointer to the current event in the sequence; and *scon
, a pointer to the score context used to play the event.
When executed, InterpretMIDIEvent()
extracts a MIDI message from the current event. The extracted message is string of one-byte values that can be from one to four bytes long. InterpretMIDIEvent()
then calls InterpretMIDIMessage()
and passes the MIDI message and score context pointer along to it.
InterpretMIDIMessage()
looks at the MIDI message to see if it is one of the messages recognized by the Music library. If it is, InterpretMIDIMessage()
calls whichever of these MIDI playback functions is appropriate for carrying out the message: StartScoreNote()
for Note On messages, ReleaseScoreNote()
for Note Off messages, ChangeScoreControl()
for volume or panning messages, ChangeScoreProgram()
for program change messages, or ChangeScorePitchBend()
for pitch bend change messages. Although these functions are called automatically during score playback, they can be used directly by a task, and are described more fully later in this chapter.