29.3 n_audio Library

The following changes have been made to past audio libraries, for n_audio. Please refer to the N64 Function Reference Manual (man pages), for a complete description of the n_audio functions. All functions that the former audio library supports are supported in the n_audio library.

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

UP


29.3.1 n_audio Functions Renamed from Previous Audio Libraries

Table 29-2 lists the functions in the n_audio library whose names are different from before.

Table 29-2 n_audio Functions Renamed from the Previous Audio Library
Audio Library Functionsn_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 past audio libraries.

With regard to the functions listed below, in (Table 29-3), both the function names and arguments have changed.

Table 29-3 Functions With Name and Argument Changes
Audio Library Functionsn_audio Library Functions
alSynNew(ALSynth *, ALSynConfig *)n_alSynNew(ALSynConfig *)
alSynNew(ALSynth *, ALSynConfig *)n_alSynDelete()
alSynDelete(ALSynth *)n_alSynAddPlayer(ALPlayer *)
alSynAddPlayer(ALSynth *, ALPlayer *)n_alSynRemovePlayer(ALPlayer *)
alSynRemovePlayer(ALSynth *, ALPlayer *)n_alSynAllocVoice(N_ALVoice *, ALVoiceConfig *)
alSynAllocVoice(ALSynth *, ALVoice *, ALVoiceConfig *)n_alSynFreeVoice(N_ALVoice *)
alSynFreeVoice(ALSynth *, ALVoice *)n_alSynAllocFX(s16, ALSynConfig *, ALHeap *)
alSynAllocFX(ALSynth *, s16, ALSynConfig *, ALHeap *)n_alSynFreeFX(ALFxRef *)
alSynFreeFX(ALSynth *, ALFxRef *)n_alSynSetVol(N_ALVoice *, s16, ALMicroTime)
alSynSetVol(ALSynth *, ALVoice *, s16, ALMicroTime)n_alSynSetPan(N_ALVoice *, u8)
alSynSetPan(ALSynth *, ALVoice *, ALPan)n_alSynSetPitch(N_ALVoice *, f32)
alSynSetPitch(ALSynth *, ALVoice *, f32)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()

There is no functional change from the old audio library in the functions listed above.

Additional functions are listed in Table 29-4.

Table 29-4 Additional Functions
Function NameFunction
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 Table 29-5.

Table 29-5 Structures Which Have Been Renamed
Audio Library Functionsn_audio Library Functions
ALVoiceN_ALVoice
ALSynthN_ALSynth
ALGlobalsN_ALGlobals
ALVoiceStateN_ALVoiceState
ALSeqPlayerN_ALSeqPlayer
ALCSPlayerN_ALCSPlayer
ALSoundStateN_ALSoundState
ALSndPlayerN_ALSndPlayer
ALSndpEventN_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.

UP


29.3.2 Creating the Application

When using the n_audio library, please include the following header files when recompiling applications that were originally created using the old 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 old 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."

UP


29.3.3 n_audio Sample Program

To illustrate using the n_audio library, the following example shows the changes and additions needed to modify the sample program (playseq.c) so that it uses the n_audio library (playseq.naudio). The following shows places that need to be changed in the program.

File : playseq.c
################ Start of sample program ##################

		*
		*

##### Changes(1) begin #####
#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. 	

		
##### Changes(1) end #####

		*
		*
		*
		*

static
void gameproc(u8 *argv)
{
		*
		*

    s16
    *audioOp;
    u8
##### Changes(2) begin #####
        min_only_one = 1,
			When replay frequency is 32 KHz, 1 frame in
			every 10 is needed to adjust for the excess 
			audio samples.
			
##### Changes(2) end #####
        *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++;

#####  Changes(3) begin  #####
    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.

#####  Changes(3) end  #####

    /*
     * 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]);

#####  Changes(4) begin  #####
        if((samplesLeft > (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;
        else
            Normal frames are here.
        {
            audioSamples[buf] = frameSize;
            min_only_one = 1;
        }
#####  Changes(4) end  #####

        /*
         * Call the frame handler
         */
        cmdlp=n_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);
#####  Changes(5) begin  #####
        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.
#####  Changes(5) end  #####
        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);

		*
		*
		*

}

################## End of sample program ##################
      

UP