You will be concerned with three issues when using sequenced sound on the Nintendo 64:
The Audio Library supports two different sequence players. The first sequence player uses Type 0 MIDI sequences. Sequences are represented at runtime with the ALSeq structure. This structure encapsulates sequence data that conforms to the Standard MIDI Files 1.0 specification for Type 0 MIDI files. The Type 0 MIDI file format contains a time-ordered MIDI message that specifies music events. It is described in detail in the "Standard MIDI Files 1.0" specification published by the MIDI manufacturers association.
The second sequence player uses a compressed format of sequence data unique to the Nintendo 64. This format is detailed in Chapter 19 "Audio File Formats". Sequences are represented at runtime with the ALCSeq structure. Besides differences in the format of the data, the compressed MIDI sequence player handles loops in a different fashion and does not support markers.
To use a Type 0 MIDI sequence in your game, you must first initialize an ALSeq structure with alSeqNew(). To use the compressed MIDI sequence player, you first initialize an ALCSeq structure with alCSeqNew(). After initializing the structure, you can perform sequence operations.
The alSeqNextEvent() call returns the MIDI event at a specified location in the sequence. (Normally, this function is called by a sequence player that users do not need to call.) The alSeqNewMarker() call creates a sequence position marker that can be used in conjunction with the Type 0 Sequence Player to set playback time and loop points. The convenience functions alSeqTicksToSec() and alSeqSecToTicks() convert between seconds and MIDI clock ticks.
Note: Normally, you will not call alSeqNextEvent() directly, because it is called by the Sequence Player during sequence playback.
The sequence calls are described in detail in the reference (man) pages. Brief descriptions are given in the Table 17-2.
|Type 0 MIDI
|alSeqNew||alCSeqNew||Initializes the sequence control structure.|
|alSeqNextEvent||alCSeqNextEvent||Returns the next MIDI event from the sequence.|
|alSeqNewMarker||alCSeqNewMarker||Initializes a marker for a given event time.|
|alSeqGetLoc||alCSeqGetLoc||Sets a marker to the sequence's current location.|
|alSeqSetLoc||alCSeqSetLoc||Sets the sequence to the location specified by the marker.|
|alSeqTicksToSec||alCSeqTicksToSec||Converts a time value from MIDI clock time to microseconds.|
|alSeqSecToTicks||alCSeqSecToTicks||Converts a time value from microseconds to MIDI clock ticks.|
Instruments are represented at runtime by the ALBankFile structure. This structure describes the instruments that sound in response to an event in the sequence. Bank Files are composed of Banks; which are composed of Instruments; which themselves are composed of groups of Sounds, KeyMaps, Envelopes, and gain and pan information. The Bank File format is described in detail Chapter 19 "Audio File Formats".
To use a Bank File in your game, you must first create a runtime structure to represent it. This is accomplished with the alBnkfNew() function as described in the following table. Both sequence players use the same function call for this operation.
|Type 0 MIDI
|alBnkfNew||alBnkfNew||Initializes a collection of banks for use with a Sequence Player.|
The Sequence Player is the mechanism by which the Nintendo 64 Audio Library plays back MIDI sequence files. It is responsible for allocating the hardware and software resources needed to play a sequence and for controlling the performance of the sequence data for the application.
Note: A Sequence Player can play only one sequence at a time.
There are certain steps you must take for your game to play a music sequence. The minimum steps needed to use the Type 0 MIDI sequence player are listed below. Using the compressed MIDI sequence player is identical, only you use the calls specific to the compressed MIDI sequence player.
|Type 0 MIDI
|alSeqpNew||alCSPNew||Initializes a Sequence Player.|
|alSeqpDelete||alCSPDelete||Frees the resource the sequence player has used.|
|alSeqpGetState||alCSPGetState||Returns the current state of the Sequence Player.|
|alSeqpSetBank||alCSPSetBank||Assigns a bank of instruments to the sequence.|
|alSeqpGetSeq||alCSPGetSeq||Gets a reference to the sequence that is currently bound to the Sequence Player.|
|alSeqpSetSeq||alCSPSetSeq||Makes the specified sequence the target sequence.|
|alSeqpPlay||alCSPPlay||Starts the target sequence playing.|
|alSeqpStop||alCSPStop||Stops the target sequence if it is playing.|
|alSeqpGetTempo||alCSPGetTempo||Returns the current playback tempo for the target sequence.|
|alSeqpSetTempo||alCSPSetTempo||Sets the current playback tempo of the target sequence.|
|alSeqpGetVol||alCSPGetVol||Returns the overall volume for the sequence.|
|alSeqpSetVol||alCSPSetVol||Sets the overall volume for the sequence.|
|alSeqpGetChlPan||alCSPGetChlPan||Gets the pan on the specified MIDI channel.|
|alSeqpSetChlPan||alCSPSetChlPan||Sets the pan for the specified MIDI channel.|
|alSeqpGetChlVol||alCSPGetChlVol||Gets the volume for the specified MIDI channel.|
|alSeqpSetChlVol||alCSPSetChlVol||Sets the volume for the specified MIDI channel.|
|alSeqpGetChlProgram||alCSPGetChlProgram||Returns the program assigned to the specified MIDI channel.|
|alSeqpSetChlProgram||alCSPSetChlProgram||Assigns the given program to the specified MIDI channel.|
|alSeqpGetChlFXMix||alCSPGetChlFXMix||Gets the wet/dryFX mix on the specified MIDI channel.|
|alSeqpSetChlFXMix||alCSPSetChlFXMix||Sets the wet/dry FX mix on the specified MIDI channel.|
|alSeqpGetChlPriority||alCSPGetChlPriority||Gets the priority value for the specified MIDI channel.|
|alSeqpSetChlPriority||alCSPSetChlPriority||Sets the priority value for the specified MIDI channel.|
|alSeqpLoop||(Not Supported)||Sets the loop points for the target sequence.|
|alSeqpSendMidi||alCSPSendMidi||Sends the specified MIDI message to the sequence player.|
The way in which loops are handled in the sequence players is different. When using the Type 0 MIDI sequence player, the programmer must create a marker at the loop start point, and a marker at the loop end point. Then the sequence can be looped between these two markers using alSeqpLoop(). Using the compressed MIDI sequence player, loops are constructed by the musician, in the tracks of the sequence by inserting controllers. (This is discussed in Chapter 20 "Using the Audio Tools". This method allows different loops for different tracks, and allows for nesting of loops.
The real-time controllers that the Sequence Player responds to are (control numbers in parenthesis): pan (10), volume (7), priority (16), sustain (64), and reverb amount (91). Note that because only one effect bus is supported, reverb amount is used to control effect amount, no matter what the effect is.
The compact sequence player also uses controllers 102, 103, 104, and 105 for creating loops. Details of this are discussed in Chapter 20 "Using the Audio Tools".