How to Use the Library

Files From Tools

The programmer receives the following types of files from the musician: soundfx.bfx, filename.ptr, filename.wbk, and tune.bin. (Here we use soundfx to indicate the name of a sound effect, filename the name of a sample bank, and tune the name of a song name. The musician would make their own names for these files.) In most projects, the number of .bin files is the same as the number of actual songs created by the musician using the sequencer.

File extension Description
.bfx Binary sound effects created with Nintendo 64 Sound Tools.

The sound effects must be placed in RAM when the sound effect data is being used. This file contains the list of offsets for the sound effects. When the bank is initialized, this list is converted into pointers and the list of default priority settings for each sound effect.
.bin Binary song created with Nintendo 64 Sound Tools.

The song file must be placed in RAM when the song data is being executed. The list of offsets in the song file are converted to pointers when the song is initialized.
.ptr Sample pointer bank created with Nintendo 64 Sound Tools.

This pointer bank file must be stored in RAM during execution of sound data that makes use of samples referenced by the file. The pointers to the offset list and the corresponding wave bank file at the time of initialization are set in this pointer bank file.
.wbk Sample wave bank created with Nintendo 64 Sound Tools.

When the wave bank file is executed, it is stored in either RAM or ROM, as determined by the configuration when the library is initialized.

All files that are accessed from RAM and include offsets that are converted to pointers are directly accessed from the library. Therefore, these files must not be moved (for example, by the relocating memory manager) while they are being used. If these files need to be moved, they should be sent again from RAM or 64DD. This is done in order to reset the original offset value.

Note: All files, when placed in RAM, must be 32-bit aligned at the very least. If a sample wave bank file is stored in RAM, this must be data-cache aligned. (We recommend cache-aligning all RAM-based sound files and data.)

Initializing the Library

You must call the library initialization function MusInitialize() before using any of the API functions. The one exception is the MusSetScheduler() function, which is only effective when called before initialization, and which is used in order to make use of a specific, external scheduler. The programmer should pass the address of the configuration structure to the initialization function. The initialization function configures both the music player and the audio manager.

The current configuration structure is shown below.

typedef struct
{
  unsigned long   control_flag;

  int             channels;
  OSSched         *sched;
  int             thread_priority;
  unsigned char   *heap;
  int             heap_length;

  unsigned char   *ptr;
  unsigned char   *wbk;

  void            *default_fxbank;

  int             fifo_length;

  int             syn_updates;
  int             syn_output_rate;
  int             syn_rsp_cmds;
  int             syn_retraceCount;
  int             syn_num_dma_bufs;
  int             syn_dma_buf_size;
  OSPiHandle      *diskrom_handle;
} musConfig;

The contents of this structure determines the memory size required from the audio heap. Each element of the structure is explained below:

control_flag Library control flag.

control_flag entry is a switching flag for controlling the characteristics of the music library. A sample bank stored in ROM is used for normal playback. For this, the entry is set to 0.

The following characteristic is currently defined by a macro

MUSCONTROL_RAM Specifies a sample stored in RAM.

The values can be OR'ed so the required characteristics can be used.

channels The number of channels.

channels entry represents the number of channels made available to the music player. In calculating the number of channels, one needs to consider how many sounds and sound effects the application might possibly trigger at the same time, and thus how many channels need to be supported. The greater the number of channels, the longer are the CPU time, the RSP time and the DMA time (only when each channel is playing back a different sample), and the more memory is required for the library.

Typical settings for the number of channels are 16, 20 and 24.

sched Address of the scheduler structure.

sched entry includes the address of the scheduler structure initialized by the Nintendo 64 library function osCreateScheduler(). That is to say, it includes the initial parameters of that function. The sched entry is ignored when an external scheduler is used.

Suppose the scheduler starts with this code:

osCreateScheduler(&scheduler,
                  scheduler_stack+(OS_SC_STACKSIZE/8),
                  SCHEDULER_PRIORITY, OS_VI_NTSC_LAN1, 1);

In this case, the configuration structure's sched entry should include the address of the scheduler structure.

thread_priority Thread priority of the music player.

thread_priority entry contains the priority of the required thread related to the scheduler, for the music player and the audio manager. The priority should be higher than that of any other application thread, and as close as possible to the priority of the scheduler.

heap The address of the audio heap.

heap entry represents the address of the memory reserved for the audio heap. We recommend that the memory be cache-aligned.

The audio heap must be large enough to meet the memory requirements of the music player and the audio manager. Unfortunately, there is no easy way to determine what that required amount is. (Moreover, there are clear differences between NTSC/MPAL applications and PAL applications.)

When the library is initialized, the programmer must note the size of the heap used by the library and change the heap size accordingly. The programmer can determine what size heap is being used by noting the value returned by the MusInitialize() function. The audio heap allocation function alHeapAlloc() returns a value for the aligned memory cache, but note that this is based on the audio heap's base address, so the amount of heap used can differ slightly (it can vary by as much as 15 bytes). In the same way, the debug version of the Nintendo 64 library (libultra_d) will allocate slightly more memory. This isis because the alHeapAlloc() function stores information inside the heap that is used to check the validity of the heap.

heap_length The size of the audio heap.

heap_length entry indicates the size of the audio heap in units of bytes. If the audio heap is cache-aligned, this should ideally be a multiple of 16.

The audio heap must be large enough to meet the memory requirements of the music player and the audio manager. Unfortunately, there is no easy way to determine what that required amount is. (Moreover, there are clear differences between NTSC/MPAL applications and PAL applications.)

When the library is initialized, the programmer must note the size of the heap used by the library and change the heap size accordingly. The programmer can determine what size heap is being used by noting the value returned by the MusInitialize() function. The audio heap allocation function alHeapAlloc() returns a value for the aligned memory cache, but note that this is based on the audio heap's base address, so the amount of heap used can differ slightly (it can vary by as much as 15 bytes). In the same way, the debug version of the Nintendo 64 library (libultra_d) will allocate slightly more memory. This isis because the alHeapAlloc() function stores information inside the heap that is used to check the validity of the heap.

fifo_length The size of the library's FIFO buffer.

fifo_length entry holds the number of commands that be used for each music update in the music library FIFO buffer. The FIFO buffer is used to execute commands that should be processed on the player thread instead of on the application thread. Currently it is used by the pause/unpause functions and the function to change the FX type of the audio library.

Currently, the minimum setting for this entry is 64. The memory needed for the FIFO buffer is obtained from the audio heap.

ptr The address of the default sample pointer bank.

ptr entry is the default sample pointer file. That is to say, it contains the address to the Nintendo 64 Sound Tools .ptr file located with 32-bit alignment (or better yet, cache-aligned) in RAM. During the initialization process, the list of offsets in this file is converted to pointers. If the ptr entry or the wbk entry is set to NULL, then the library is initialized without a sample bank.

wbk The address of the default sample wave bank.

wbk entry is the default sample waveform file. That is to say, it contains the address to the Nintendo 64 Sound Tools .wbk file located in ROM or in RAM (if configured for RAM-based samples). This is the actual sample data: the data copied to RAM (if located in ROM) via the DMA buffer when sound output is generated. If the wbk entry or the ptr entry is set to NULL, then the library is initialized without a sample bank.

default_fxbank The address of the sound effect bank.

default_fxbank entry is the default sound effect bank file. That is to say, it contains the address to the Nintendo 64 Sound Tools .bfx file located with 32-bit alignment (or better yet, cache-aligned) in RAM. During the initialization process, the list of offsets in this file is converted to pointers, and the sample bank override (the region temporarily set as the sample bank) is cleared. If this entry is set to NULL, then the library is initialized without a default sound effect bank.

syn_updates The number of synthesizer updates.

syn_updates entry contains the number of times the synthesizer can be updated. This entry is passed to the alInit() function as the maxUpdates parameter of the configuration structure.

syn_output_rate The playback rate.

syn_output_rate entry contains the hardware output rate of the synthesizer. This entry is passed to the alInit() function as the outputRate parameter of the configuration structure.

The hardware playback rate must be the same rate as the sound data created with Nintendo 64 Sound Tools.

syn_rsp_cmds The number of RSP commands.

syn_rsp_cmds entry contains the size of the buffer to be allocated for the placement of RSP commands created by the library. We recommend that this value be at least 2048 per video frame. (For example, if syn_retraceCount is 1, then it should be at least 2048. If syn_retraceCount is 2, then the value should be at least 4096.)

syn_retraceCount The number of frames per VSYNC message.

syn_retraceCount entry contains the number of V-Syncs per retrace message sent by the scheduler. This value must be the same as the retraceCount sent to the osCreateScheduler() function (or the number of video frames set to be processed by an external scheduler). We recommend the value be set to 1.

If this value is not set to 1, then the programmer should consider increasing the number of DMA buffers, the number of RSP commands and the number of updates in the configuration structure.

syn_num_dma_bufs The number of DMA buffers.

syn_num_dma_bufs entry contains the number of DMA buffers made available to the audio manager. The programmer should include in the calculation a consideration of how many DMAs will be needed to supply sample data to the channels supported by the music player.

This value should not be smaller than the number of channels, and if possible we recommend making it a little larger. If the audio manager cannot allocate a DMA buffer, then there will be "gaps" in the sound when the buffer is required.

syn_dma_buf_size The length of each DMA buffer.

syn_dma_buf_size entry contains the size of each buffer made available to the audio manager. The larger the buffer size, the less necessary DMAs become, but then much more memory is required. We recommend never setting this value below 0x400.

diskrom_handle Information regarding the 64DD ROM hardware settings.

diskrom_handle entry contains the hardware information needed to use the ROM in the 64DD drive. If the 64DD ROM will not be used, then nothing needs to be specified for this setting. But if the 64DD ROM is to be used, then pass the value returned by the osDriveRomInit() function.