3-5 Method of Audio Playback Process


3-5-1 Playing Back Audio Step by Step

The audio playback is provided by the following procedure:

  1. Create the audio heap.
  2. Set the hardware output frequency.
  3. Create a synthesizer.
  4. Create a message queue for receiving the signal that adjusts the timing of the audio process.
  5. Create players (sound player, sequence player, etc.) to be added to the synthesizer.
  6. Initialize the resources allocated to each player.
  7. Create the audio command list.
  8. In RSP, execute the audio task based on the audio command list.
  9. Set the audio DAC.



3-5-2 Setting Up the Synthesizer Step by Step

Before playing back the audio, you first need to set the synthesizer by following this procedure:

1. Initialize the audio heap
For each audio library function, N64 allocates required memory dynamically from the memory area called the audio heap. Therefore, to use the audio library, you must first initialize the audio heap area by using the alHeapInit function.

2. Set the hardware playback rate
To set the hardware playback rate, use the osAiSetFrequency function.

3. Set up the synthesizer driver configuration structure
Before creating the synthesizer, set the parameters such as maxUpdates, in the synthesizer driver configuration structure.

4. Create the synthesizer
Use the alInit function to create the synthesizer.

5. Set up the DMA call back routine
As the occasion demands, to transfer the waveform data in ROM to RDRAM, you must set up the DMA callback routine brought up from the synthesizer driver. To do this, you need to set the pointer to the DMA initialization routine in the synthesizer driver's configuration structure. This DMA initialization routine is brought up once for each physical voice; it initializes the DMA buffer the first time and is set to return the pointer (ALDMAproc) to the function called up when the waveform data actually becomes necessary. ALDMAproc receives the address, length, and state pointer of the required data and returns the pointer to the buffer, storing its data as the return value. Nintendo uses this method in order to give you, the programmer, more freedom. This way, you can customize the algorithm by choosing to externally place either the cache process or the resident process.



3-5-3 Playing Back Sound Effects Step by Step

Sound effects are played back by using a sound player which is a client of the synthesizer. To playback a sound effect, use this procedure:

1. Accept the audio bank from ROM
To play the sound, you need to first use DMA to transfer the control file of the wave table to RDRAM. The following is a typical procedure you can use to complete the DMA transfer of the audio bank. 2. Activate the sound player
Use the alSndpNew function to activate the sound player. This also automatically registers the client player in the synthesizer driver.

3. Initialize the audio bank
Use the alBnkfNew function to initialize the audio bank used to playback the sound effect. Here, "initialize", actually means, "convert from the offset to the pointer" and "convert from the offset to the address."

4. Allocate resources to the sound
Allocate the sound to the player by using the alSndpAllocate function.

5. Choose the sound
Before setting the pan, volume, and so on, you need to choose the sound by using the alSndpSetSound function.

6. Playback the sound
Use the alSndpPlay function to playback the sound.

7. Stop the sound
Use the alSndpStop function to stop the sound.

8. Delete the sound player
If you no longer need the sound player, delete the client from the synthesizer driver by using the alSndpDelete function.



3-5-4 Playing Back Sequences Step by Step

To playback MIDI sequences, you need to use a sequence player which is a client of the synthesizer. Use the audio library, and follow these steps:

1. Accept the audio bank from ROM
This is the same method as for the playback of sound effects.

2. Accept the MIDI sequence from ROM
Before playing back a MIDI sequence, you need to use DMA to transfer the sequence from ROM to RDRAM, which you can do by using the following typical procedure: (In addition, the PI Manager and message queue for the DMA transfer should be already created.) 3. Activate the sequence player
Use the alSeqpNew function (for a Type0 MIDI file) or the alCSPNew function (for a compressed MIDI file) to activate the appropriate sequence player.

4. Initialize the sequence structure
The sequence structure stores the sequence data information needed to playback the MIDI sequence. Use the alSeqNew function (for a Type 0 MIDI file) or the alCSeqNew function (for a compressed MIDI file) to initialize the structure.

5. Set up the sequence in the player
To set up the sequence in the player, use the alSeqpSetSeq function (for a Type 0 MIDI file) or the alCSPSetSeq function (for a compressed MIDI file).

6. Initialize the audio bank
This method is the same as the one for the playback of sound effects.

7. Set up the audio bank
Specify the instrument bank to be used by the sequence player by using the alSeqpSetBank function (for a Type 0 MIDI file) or the alCSPSetBank function (for a compressed MIDI file).

8. Play the sequence
To initiate the sequence playback, use the alSeqpPlay function (for a Type 0 MIDI file) or the alCSPPlay function (for a compressed MIDI file).

9. Stop playing the sequence
To stop playing the sequence, use the alSeqpStop function (for a Type 0 MIDI file) or the alCSPStop function (for a compressed MIDI file).

10. Delete the sequence player
When a sequence player becomes unnecessary, delete it as a client of the synthesizer driver by using the alSeqpDelete function (for a Type 0 MIDI file) or the alCSPDelete function (for a compressed MIDI file).



3-5-5 Executing Audio Tasks Step by Step

1. Ensure that the audio buffers are ready
An audio process generally reserves three audio buffer areas in RDRAM. It also reserves two buffers for the audio command list so that one buffer is always ready to be played. This double buffering helps to prevent sound from pausing by never having to wait for an audio process.

2. Synchronize the retrace and RSP events
To execute an audio task, N64 game programmers usually prepare two message queues -- one to post the VI retrace, and the other to post the completion of the RSP task. Set up the former by using the osViSetEvent function, and set up the latter by using the osSetEventMesg function. Store the event type in OS_EVENT_SP. The VI retrace event is essential to ensure that each audio process is executed for each frame.

3. Regulation of the sample to ensure compatibility with the frame size
To avoid clicking sounds in the music, you need to regulate the processing sample number to ensure that it is compatible with the situation. To do this, use IO_READ (AL_LEN_REG) or the osAiGetLength function. This detects the sample number remaining in the audio buffer without using it, and it regulates the sample so that the newly processing sample number is compatible with the available space and can have a little more room. Because the sample number having room or not varies depending on the program or sound, you need to regulate it by continually caculating the actual amount remaining.

4. Create the audio command list
To create the audio command list, use the alAudioFrame function.

5. Execute the audio task
To have the RSP execute the audio task based on the audio command list and create the waveform data in the audio buffer, use the osSpTaskStart function.

6. Set up the audio DAC
Use DMA to transfer the audio to the audio DAC by using the osAiSetNextBuffer function.