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