Using n_audio

Changed Functions from the Former Audio Library
The following changes have been made to the the former audio library, for n_audio. Please refer to the N64 Function Reference Manual (man pages), for a complete description of the n_audio functions.

Note: The n_audio library is a separate product from the N64 development environment (ultra.dev). Please be sure to install n_audio prior to using the OS.

Table 1  n_audio Functions Renamed from the Previous Audio Library
Audio Library Functions n_audio Library Functions
alInit() n_alInit()
alClose() n_alClose()
alAudioFrame() n_alAudioFrame()
alSeqNextEvent() n_alSeqNextEvent()
alSeqNewMarker() n_alSeqNewMarker()
alCSeqNew() n_alCSeqNew()
alCSeqNextEvent() n_alCSeqNextEvent()
alCSeqNewMarker() n_alCSeqNewMarker()
alSeqpNew() n_alSeqpNew()
alSeqpPlay() n_alSeqpPlay()
alSeqpStop() n_alSeqpStop()
alSeqpDelete() n_alSeqpDelete()
alSeqpLoop() n_alSeqpLoop()
alSeqpSendMidi() n_alSeqpSendMidi()
alSeqpGetSeq() n_alSeqpGetSeq()
alSeqpGetTempo() n_alSeqpGetTempo()
alSeqpGetVol() n_alSeqpGetVol()
alSeqpGetState() n_alSeqpGetState()
alSeqpSetSeq() n_alSeqpSetSeq()
alSeqpSetTempo() n_alSeqpSetTempo()
alSeqpSetVol() n_alSeqpSetVol()
alSeqpSetBank() n_alSeqpSetBank()
alSeqpGetChlVol() n_alSeqpGetChlVol()
alSeqpGetChlFXMix() n_alSeqpGetChlFXMix()
alSeqpGetChlPan() n_alSeqpGetChlPan()
alSeqpGetChlPriority() n_alSeqpGetChlPriority()
alSeqpGetChlProgram() n_alSeqpGetChlProgram()
alSeqpSetChlVol() n_alSeqpSetChlVol()
alSeqpSetChlFXMix() n_alSeqpSetChlFXMix()
alSeqpSetChlPan() n_alSeqpSetChlPan()
alSeqpSetChlPriority() n_alSeqpSetChlPriority()
alSeqpSetChlProgram() n_alSeqpSetChlProgram()
alCSPNew() n_alCSPNew()
alCSPPlay() n_alCSPPlay()
alCSPStop() n_alCSPStop()
alCSPDelete() n_alCSPDelete()
alCSPSendMidi() n_alCSPSendMidi()
alCSPGetSeq() n_alCSPGetSeq()
alCSPGetTempo() n_alCSPGetTempo()
alCSPGetVol() n_alCSPGetVol()
alCSPGetState() n_alCSPGetState()
alCSPSetSeq() n_alCSPSetSeq()
alCSPSetTempo() n_alCSPSetTempo()
alCSPSetVol() n_alCSPSetVol()
alCSPSetBank() n_alCSPSetBank()
alCSPGetChlVol() n_alCSPGetChlVol()
alCSPGetChlFXMix() n_alCSPGetChlFXMix()
alCSPGetChlPan() n_alCSPGetChlPan()
alCSPGetChlPriority() n_alCSPGetChlPriority()
alCSPGetChlProgram() n_alCSPGetChlProgram()
alCSPSetChlVol() n_alCSPSetChlVol()
alCSPSetChlFXMix() n_alCSPSetChlFXMix()
alCSPSetChlPan() n_alCSPSetChlPan()
alCSPSetChlPriority() n_alCSPSetChlPriority()
alCSPSetChlProgram() n_alCSPSetChlProgram()

In the table above, only the function names have changed . Function arguments and specifications remain the same as in the old audio library.

With regard to the functions listed below, (Table 2) both the function name and its argument have changed.

Table 2  Functions With Name and Argument Changes
Audio Library Functions n_audio Library Functions
alSynNew(ALSynth *, ALSynConfig *) n_alSynNew(ALSynConfig *)
alSynDelete(ALSynth *) n_alSynDelete()
alSynAddPlayer(ALSynth *, ALPlayer *) n_alSynAddPlayer(ALPlayer *)
alSynRemovePlayer(ALSynth *, ALPlayer *) n_alSynRemovePlayer(ALPlayer *)
alSynAllocVoice(ALSynth *, ALVoice *, ALVoiceConfig *) n_alSynAllocVoice(N_ALVoice *, ALVoiceConfig *)
alSynFreeVoice(ALSynth *, ALVoice *) n_alSynFreeVoice(N_ALVoice *)
alSynAllocFX(ALSynth *, s16, ALSynConfig *, ALHeap *) n_alSynAllocFX(s16, ALSynConfig *, ALHeap *)
alSynFreeFX(ALSynth *, ALFxRef *) n_alSynFreeFX(ALFxRef *)
alSynSetVol(ALSynth *, ALVoice *, s16, ALMicroTime) n_alSynSetVol(N_ALVoice *, s16, ALMicroTime)
alSynSetPan(ALSynth *, ALVoice *, ALPan) n_alSynSetPan(N_ALVoice *, u8)
alSynSetPitch(ALSynth *, ALVoice *, f32) n_alSynSetPitch(N_ALVoice *, f32)
alSynSetPriority(N_ALVoice *, s16) n_alSynSetPriority(N_ALVoice *, s16)
alSynSetFXMix(ALSynth *, ALVoice *, u8) n_alSynSetFXMix(N_ALVoice *, u8)
alSynSetFXParam(ALSynth *, ALFxRef, s16, void *) n_alSynSetFXParam(ALFxRef, s16, void *)
alSynGetPriority(ALSynth *, ALVoice *) n_alSynGetPriority(N_ALVoice *)
alSynGetFXRef(ALSynth *, s16, s16) n_alSynGetFXRef(s16, s16)
alSynStartVoice(ALSynth *, ALVoice *, ALWaveTable *) n_alSynStartVoice(N_ALVoice *, ALWaveTable *)
alSynStartVoiceParams(ALSynth *, ALVoice *, ALWaveTable *, f32, s16, ALPan, u8, ALMicroTime) n_alSynStartVoiceParams(N_ALVoice *, ALWaveTable *, f32, s16, ALPan, u8, ALMicroTime)
alSynStopVoice(ALSynth *, ALVoice *) n_alSynStopVoice(N_ALVoice *)
alSndpNew(ALSndPlayer *, ALSndpConfig *) n_alSndpNew(N_ALSndPlayer *, ALSndpConfig *)
alSndpDelete(ALSndPlayer *) n_alSndpDelete()
alSndpAllocate(ALSndPlayer *, ALSound *) n_alSndpAllocate(ALSound *)
alSndpDeallocate(ALSndPlayer *, ALSndId) n_alSndpDeallocate(ALSndId)
alSndpGetState(ALSndPlayer *) n_alSndpGetState()
alSndpPlay(ALSndPlayer *) n_alSndpPlay()
alSndpPlayAt(ALSndPlayer *, ALMicroTime) n_alSndpPlayAt(ALMicroTime)
alSndpStop(ALSndPlayer *) n_alSndpStop()
alSndpSetVol(ALSndPlayer *, s16) n_alSndpSetVol(s16)
alSndpSetPan(ALSndPlayer *, ALPan) n_alSndpSetPan(ALPan)
alSndpSetPitch(ALSndPlayer *, f32) n_alSndpSetPitch(f32)
alSndpSetPriority(ALSndPlayer *, ALSndId, u8) n_alSndpSetPriority(ALSndId, u8)
alSndpSetFXMix(ALSndPlayer *, u8) n_alSndpSetFXMix(u8)
alSndpSetSound(ALSndPlayer *, ALSndId) n_alSndpSetSound(ALSndId)
alSndpGetSound(ALSndPlayer *) n_alSndpGetSound()

Table 3  Additional Functions
Function Name Function
n_alSynAddSeqPlayer(ALPlayer *) Allocate sequence player in synthesis driver
n_alSynAddSndPlayer(ALPlayer *)Allocate sound player

The above functions are differentiated by the type of player that is allocated. Functionally, they are the same as alSynAddPlayer(), and n_alSynAddPlayer(). Please see the explanation for alSynAddPlayer for details.

Structures in which the names have changed are shown in the following table.

Table 4  Structures Which Have Been Renamed
Audio Library Functions n_audio Library Functions
ALVoice N_ALVoice
ALSynth N_ALSynth
ALGlobals N_ALGlobals
ALVoiceState N_ALVoiceState
ALSeqPlayer N_ALSeqPlayer
ALCSPlayer N_ALCSPlayer
ALSoundState N_ALSoundState
ALSndPlayer N_ALSndPlayer
ALSndpEvent N_ALSndpEvent

Usually the program does not handle structure members directly. Therefore, it is necessary for the programmer to be aware of the above changes in defining the variable. When handling these structure members directly, refer to the header file in the n_audio library, n_libaudio.h.

Creating the Application
When using the n_audio library, please include the following header files when recompiling applications that were originally created using the former audio library.

n_libaudio.h The header file for the n_audio library
n_libaudio_s_to_n.h A macro group for converting the former audio library function to the n_audio library function

The header files above are usually installed in the "/usr/include/PR" directory.

Also, link in the following libraries:

libn_audio.a The n_audio library
n_aspMain.o The microcode for the n_audio library

The "libn_audio.a" library will be installed in the "/usr/lib," directory, and the microcode, "n_aspMain.o" will be installed in the "/usr/lib/PR" directory.

Please refer to "Makefile" in the "playseq.naudio" sample program for the directory specification of the header file library, and the method of linking the library.

Note: If you regularly use the n_audio library, please rewrite the (former) audio library function to the n_audio library function directly; do not use the header file "n_libaudio_s_to_n.h."

n-audio Sample Program
The n_audio library sample program "playseq.naudio" is similar to the sample program (playseq.c) used with the former audio library. The changes and additions needed to create the n_audio sample program are detailed below in "blue" type. The n-audio sample sets the number of audio data samples for a game to a multiple of 184. Making the following changes to "playseq.c," (included on the N64 Operating System CD) will result in sample code that is compatible with the n_audio library.

#include "n_libaudio.h" 
/* Include this header file for n_audio.  
You must include it first before including "n_libaudio_s_to_n.h."

#include "n_libaudio_s_to_n.h" /* Include this header file for n_audio.

This file contains a series of macros for converting the former 
audio library functions to library functions compatible 
with n-audio.  
If you regularly use the n_audio library, please rewrite 
each audio library function to the n_audio library function; 
don’t include this file.

#define SAMPLES   184 */ Set the sound processing unit to 184 samples.
#define EXTRA_SAMPLES            0  
*/ If sound skipping is obvious, set this value 
appropriately to adjust for the number surplus 
audio samples.   

static
void gameproc(u8 *argv)
{
       .
       .
       .
   s16
           *audioOp;
   u8
min_only_one = 1,  /* When replay frequency is 32 KHz, 1 frame in 
                      every 10 is needed to adjust for the excess 
                      audio samples.
*ptr,
       *seqPtr,
		*midiBankPtr;
	OSMesgQueue
		seqMessageQ;
			·
			·
			·
	/*
	/* Initialize DAC output rate
	*/
	c.outputRate = osAiSetFrequency(OUTPUT_RATE);
	fsize = (f32) NUM_FIELDS * c.outputRate / (f32) 60;
frameSize = (s32) fsize; /* Get the required number of audio samples
                            per frame */
if (frameSize < fsize)
		frameSize++; 
frameSize = ((frameSize / SAMPLES) +1) *SAMPLES;   
/* Recalculate the required number of samples per frame, 
which was just found above,to be a multiple of 184. 
*/ minFrameSize = frameSize - SAMPLES;   /* frameSize is a multiple of
184 and results in more than the actual required number of samples per frame. 
Therefore excess sample data is generated for each frame. 
Set minFrameSize to adjust this number of excess samples.
 /*
 * Audio synthesizer initialization
 */
c.maxVVoices = MAX_Voices;
c.maxPVoices = MAX_VOICES;
			·
			·
			·
/*
* Note that this must be a do-while in order for seqp’s state
	* to get updated during the alAudioFrame processing.
	*/
	do {
		frame++;
		/*
		 * Where the task list goes in DRAM
		 */
		tlistp = tlist[curBuf];
		cmdlp = cmdList[curBuf];
		/*
		 * Where the audio goes in DRAM
		 */
		buf = curAudioBuf% 3;
		audioOp = (s16 *) osVirtualToPhysical(audioBuffer[buf]);
if((sanpleLeft > (SAMPLES + EXTRA_SAMPLES)) && min_only_one)
            /* If the number of excess samples at the time of retrace is more than 184, you make this frame the "adjustment frame" to adjust
for the excess. In the adjustment frame, the number of samples
equal to minFrameSize is generated. Use min_only_one to ensure
that the adjustment frame is done only once. When sound
break-up is severe, the number of excess samples may be zero.
If that is the case, set EXTRA_SAMPLES to an appropriate value
to adjust the excess sample data. Audio replay cannot be done
properly if the value of EXTRA_SAMPLES is too large. The 
appropriate value depends on the application. */
{
 audioSamples[buf] = minFrameSize;
 min_only_one = 0;
}
else if(samplesLeft > (SAMPLES + EXTRA_SAMPLES))
            /* Normal frames are processed here. In the case of this sample program, it is possible for the frame to appear consecutively
putting in a normal frame under the conditions stated above. In
that case, the value of samplesLeft becomes zero and the sound
breaks up. By adding this conditional decision, this sample
program prevents sound from breaking up. */
{
 audioSamples[buf] = frameSize;
 min_only_one = 1;
}
/*
 * Call the frame handler
 */
cmdlp=alAudioFrame(cmdlp,&clcount,audioOp,
				audioSamples[buf];
/*
 * Build the audio task
 */
tlistp->t.type = M_AUDTASK;
tlistp->t.flags = 0x0;
tlistp->t.ucode_boot = (u64 *) rspbootTextStart;
tlistp->t.ucode_boot_size = ((s32)rspbootTextEnd -
				(s32)rspbootTextStart);
	tlistp->t.ucode = (u64 *) n_aspMainTextStart;
	tlistp->t.ucode_data = (u64 *) n_aspMainDataStart;   /* 
To use the N_Audio microcode, these two lines must be rewritten to n_aspMain.
tlistp->t.ucode_size = 4096;
tlistp->t.ucode_data_size = SP_UCODE_DATA_SIZE;
	tlistp->t.data_ptr = (u64 *) cmdList[curBuf];
	tlistp->t.data_size = (cmdlp - cmdList[curBuf])
					* sizeof(Acmd);
		·
		·
		·
	} while (seqp->state+= AL_STOPPED);
		·
		·
		·
}


Copyright © 1999
Nintendo of America Inc. All Rights Reserved
Nintendo and N64 are registered trademarks of Nintendo
Last Updated December, 1998