17.3 Sequenced Sound Playback

You will be concerned with three issues when using sequenced sound on the Nintendo 64:

UP

17.3.1 Representing the Sequence

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.

Table 17-2 Sequence Functions
Type 0 MIDI
Sequence Player
Compact MIDI
Sequence Player
Function
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.
UP

17.3.2 Representing Instruments

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.

Table 17-3 Bank Functions
Type 0 MIDI
Sequence Player
Compact MIDI
Sequence Player
Function
alBnkfNew alBnkfNew Initializes a collection of banks for use with a Sequence Player.
UP

17.3.3 Playing Sequences

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.

  1. Create and initialize the basic resources described in the section "Generating Audio Output".

  2. Initialize the sequence by using alSeqNew().

  3. Load the bank file .ctl file into RAM, and initialize the bank by calling alBnkfNew().

  4. Initialize the sequence by using alSeqpNew()

  5. Set the sequence player's bank by using alSeqpSetBank().

  6. Set the sequence player's target sequence by using alSeqpSetSeq().

  7. Play the sequence by using alSeqpPlay().

  8. Stop the sequence when you are finished with it, by using alSeqpStop().

  9. If the sequence player is no longer needed it can be removed from the Synthesis Driver's client list by using alSeqpDelete()

Table 17-4 Sequence Player Functions
Type 0 MIDI
Sequence Player
Compact MIDI
Sequence Player
Function
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.

UP

17.3.4 Loops in Sequence Players

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.

UP

17.3.5 Controllers in Sequence Players

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".

UP