# 2.3.5 Audio Reproduction Process

## Reproducing Audio Step by Step

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 adapts the timing of the audio process.
5. Create players (sound player, sequence player, and so on) 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.

## Setting Up the Synthesizer Step by Step

Before reproducing 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 reproduction rate
   To set the hardware reproduction 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. Accommodate the DMA callback routine
   As occasion demands, to transfer the waveform data in ROM to RDRAM, you must accommodate the DMA callback routine called 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 called once for each physical voice; it initializes the DMA buffer with the first call and is set to return the pointer (ALDMAproc) to the function called when actually requiring the waveform data. 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 put either the cache process or the resident process outside.

## Reproducing Sound Effects Step by Step

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

1. Accept the audio bank from ROM
   To reproduce 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. The first three steps are required only with the first setting.
   1. Create the PI Manager by using the osCreatePiManager function. (In the actual game program, you create the PI Manager in the main program, so there is no need to recreate it here; the audio side just uses it.)
   2. Create the message queue to verify the end of the DMA transfer by using the osCreateMesgQueue function.
   3. Reserve the heap area for the audio bank by using the alHeapAlloc function.
   4. Before the DMA transfer, provide for the write back of the CPU cache by using the osWritebackDCache or osWritebackDCacheAll function.
   5. Initiate the DMA transfer by using the osPiStartDma function.
   6. Verify the end of the DMA transfer by using the osRecvMesg function.
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 reproduce 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. Reproduce the sound
   Use the alSndpPlay function to reproduce 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.

## Reproducing Sequences Step by Step

To play 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 step is identical to step 1 for reproducing sound effects. To reproduce a sequence, you need to first use DMA to transfer the control file of the wave table to RDRAM. The following is a typical method you can use to complete the DMA transfer of the audio bank. The first three steps are required only with the first setting.
   1. Create the PI Manager by using the osCreatePiManager function. (In the actual game program, you create the PI Manager in the main program, so you won't need to recreate it here; the audio side just uses it.)
   2. Create the message queue to verify the end of the DMA transfer by using the osCreateMesgQueue function.
   3. Reserve the heap area for the audio bank by using the alHeapAlloc function.
   4. Before the DMA transfer, provide for the write back of the CPU cache by using the osWritebackDCache or osWritebackDCacheAll function.
   5. Initiate the DMA transfer by using the osPiStartDma function.
   6. Verify the end of the DMA transfer by using the osRecvMesg function.
   Now the PI Manager and message queue for DMA transfer are created, so they can be used by step 2 without having to be recreated.
2. Accept the MIDI sequence from ROM
   Before reproducing a MIDI sequence, you need to use DMA to transfer the sequence from ROM to RDRAM, which you can do by following this typical procedure:
   1. Read the first four bytes of the sbk file header. The first two bytes hold the version and the next two bytes hold the number of the sequence. To do this step, you need to first reserve the header area by using the alHeapAlloc function. Then use DMA to transfer the first four bytes.
   2. Use DMA to transfer the entire header including the ALSeqData structure which holds the sequence number.
   3. Initialize the sequence bank file by using the alSeqFileNew function.
   4. Use DMA to transfer the required MIDI sequence information stored in ALSeqData structure.
3. Activate a sequence player
   Use the alSeqpNew function (for a Type 0 MIDI file) or the alCSPNew function (for a compact MIDI file) to activate the appropriate sequence player.
4. Initialize the sequence structure
   The sequence structure stores the sequence data information needed to reproduce the MIDI sequence. Use the alSeqNew function (for a Type 0 MIDI file) or the alCSeqNew function (for a compact 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 compact MIDI file).
6. Initialize the audio bank
   This step is identical to step 3 of the sound effect reproduction procedure. Use the alBnkfNew function to initialize the audio bank used to reproduce the sound effect. Here "initialize" actually means "convert from the offset to the pointer" and "convert from the offset to the address."
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 compact MIDI file).
8. Play the sequence
   To initiate the sequence reproduction, use the alSeqpPlay function (for a Type 0 MIDI file) or the alCSPPlay function (for a compact MIDI file).
9. Stop playing the sequence
   To stop playing sequence, uses the alSeqpStop function (for a Type 0 MIDI file) or the alCSPStop function (for a compact 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 compact MIDI file).

## 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. Regulate the sample to ensure compliance with frame size
   To avoid clicking sounds in the music, you need to regulate the processing sample number to ensure that it is in compliance 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 in compliance with the available space and can have a little more room. Because the sample number having room varies depending on the program or sound, you need to regulate it by continually computing 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.

Nintendo® Confidential
Copyright © 1999
Nintendo of America Inc. All Rights Reserved
Nintendo and N64 are registered trademarks of Nintendo
Last Updated March, 1999