2.3.6 Audio Reproduction Samples

The following code demonstrates how to play a MIDI sequence in your game. This code is also available in the \N64Manuals\pc\allman\samples\Sequence directory of this CD.

Another audio sample on the CD demonstrates how to play sound effects. It is located in the \N64Manuals\pc\allman\samples\Effect subdirectory.

Note that all the os and al functions in the following code are included in the library. You can look them up in the N64 Function Reference Manual for more information. All other functions are defined for this sample only; they are not part of the os or al libraries.

Illustration

Sequence Reproduction Sample Code

/*----------------
 The main process
------------------*/
void mainproc(void* arg)
{
/* Initialize each type */
InitMain( );

/* The main loop */
while(1){
switch(main_no){
case GM_MAIN:
main_no = main00(&sched);
break;
}
}
}

/*-------------------
Initialize each type
---------------------*/
void InitMain(void)
{
/* Initialize the audio player */
auAudioInit( );

/* Initialize the sequence player */
auSeqPlayerInit(_midibankSegmentRomStart,
_midibankSegmentRomEnd,
_seqSegmentRomStart,
_seqSegmentRomEnd,
_miditableSegmentRomStart);

/* Create the scheduler thread */
nnScCreateScheduler(&sched, OS_VI_NTSC_LAN1, 1);

/* Create the audio thread */
auCreateAudioThread(&sched);

main_no = GM_MAIN;
}

/*---------------------------------------
  Allocate each buffer and initialize the
  parameter used in the audio library
-----------------------------------------*/
void auAudioInit(void)
{
/*initialize audio heap */
alHeapInit(&audio_heap, audio_heap_buf,
   AUDIO_HEAP_SIZE);

/* create command list buffer */
audio_cmdlist_ptr[0] = alHeapAlloc(&audio_heap,

   1,AUDIO_CLIST_SIZE_MAX*sizeof(Acmd));
audio_cmdlist_ptr[1] = alHeapAlloc(&audio_heap,

   1,AUDIO_CLIST_SIZE_MAX*sizeof(Acmd));

/* create task list buffer */
audio_tlist_ptr[0] = alHeapAlloc(&audio_heap,

   1, sizeof(OSTask));
audio_tlist_ptr[1] = alHeapAlloc(&audio_heap,

   1, sizeof(OSTask));

/* create audio buffer */
audio_buffer_ptr[0] = alHeapAlloc(&audio_heap,

   1,sizeof(s32)*AUDIO_BUFFER_MAX);
audio_buffer_ptr[1] = alHeapAlloc(&audio_heap,

   1,sizeof(s32)*AUDIO_BUFFER_MAX);
audio_buffer_ptr[2] = alHeapAlloc(&audio_heap,

   1,sizeof(s32)*AUDIO_BUFFER_MAX);

/* create message queue for DMA */
osCreateMesgQueue(&audioDmaMessageQ,

&audioDmaMessageBuf,1);
osCreateMesgQueue(&audioRomMessageQ,

&audioRomMessageBuf, 1);

/* Clear initialization flag of DMABuffer*/
dmaState.initialized = 0;

/* initialize audio library */
audio_config.outputRate= 
osAiSetFrequency(AUDIO_OUTPUT_RATE);
audio_config.maxVVoices =
AUDIO_VVOICE_MAX; /* max virtual voices */
audio_config.maxPVoices =
AUDIO_PVOICE_MAX;  /* max physical voices */
audio_config.maxUpdates = AUDIO_UPDATE_MAX;  
audio_config.dmaproc = &dmaNew;
/* DMA callback function */
audio_config.fxType = AL_FX_SMALLROOM;
/* effect type */
audio_config.heap = &audio_heap;
/* audio heap */
audio_config.params = 0;
/* custom effect */

/* Create the synthesizer (initialize
   the audio library) */
alInit(&audio_global, &audio_config);
}

/*---------------------------------------------
Initialize the sequence player
input
midi_start: The header ROM address of the
            bank file (.ctl)
midi_end: The end ROM address of the bank
          file (.ctl)
seqheader_start: The header ROM address of
                 the sequence file (.sbk)
seqheader_end: The end ROM address of the
               sequence file (.sbl)
midi_table_star: The header ROM address of
                 the wave table file (.tbl)
-----------------------------------------------*/
void auSeqPlayerInit(u8* midi_start, u8* midi_end,
u8* seqheader_start, u8* seqheader_end,
u8* midi_table_start) 
{
ALBank *midiBank_ptr;
u32 size;

/* create sequence data buffer */
seqplayer[0].seqdata_ptr =
alHeapAlloc(&audio_heap, 1,
   AUDIO_SEQDATA_SIZE_MAX);
seqplayer[1].seqdata_ptr =
alHeapAlloc(&audio_heap, 1,
   AUDIO_SEQDATA_SIZE_MAX);

/* initialize sequence player 0 */
seqplayer[0].seqconfig.maxVoices =
AUDIO_SEQ_VVOICE_MAX; /* max virtual voices */
seqplayer[0].seqconfig.maxEvents =
AUDIO_SEQ_EVTCOUNT_MAX; /* max inside events */
seqplayer[0].seqconfig.maxChannels = 
AUDIO_SEQ_CHANNEL_MAX; /* max MIDI channels */
seqplayer[0].seqconfig.heap = &audio_heap;
seqplayer[0].seqconfig.initOsc = 0;
seqplayer[0].seqconfig.updateOsc = 0;
seqplayer[0].seqconfig.stopOsc = 0;
seqplayer[0].seqconfig.debugFlags = 0;

#ifdef _AUDIO_COMPACTMIDI_
alCSPNew(&seqplayer[0].seqplayer,

   &seqplayer[0].seqconfig);
#else
alSeqpNew(&seqplayer[0].seqplayer,

   &seqplayer[0].seqconfig);
#endif /* _AUDIO_COMPACTMIDI_ */

/* initialize sequence player 1 */
seqplayer[1].seqconfig.maxVoices =
AUDIO_SEQ_VVOICE_MAX; /* max virtual voices */
seqplayer[1].seqconfig.maxEvents =
AUDIO_SEQ_EVTCOUNT_MAX; /* max inside events */
seqplayer[1].seqconfig.maxChannels =
AUDIO_SEQ_CHANNEL_MAX; /* max MIDI channels */
seqplayer[1].seqconfig.heap = &audio_heap;
seqplayer[1].seqconfig.initOsc = 0;
seqplayer[1].seqconfig.updateOsc = 0;
seqplayer[1].seqconfig.stopOsc = 0;
seqplayer[1].seqconfig.debugFlags = 0;

#ifdef _AUDIO_COMPACTMIDI_
alCSPNew(&seqplayer[1].seqplayer,

   &seqplayer[1].seqconfig);
#else
alSeqpNew(&seqplayer[1].seqplayer,

   &seqplayer[1].seqconfig);
#endif /* _AUDIO_COMPACTMIDI_ */

/* read seqfileheader data */
auReadSeqFileHeader((u32)seqheader_start);
alSeqFileNew(seqHeaderfile_ptr, seqheader_start);

/* read midi bank data */
size = (u32)midi_end-(u32)midi_start;
midi_buffer_ptr = alHeapAlloc(&audio_heap, 1, size);
auRomRead((u32)midi_start, midi_buffer_ptr, size);

/* Specify the instrument bank used by
   the sequencer */
alBnkfNew(midi_buffer_ptr, midi_table_start);
midiBank_ptr = midi_buffer_ptr->bankArray[0];

#ifdef _AUDIO_COMPACTMIDI_
alCSPSetBank(&seqplayer[0].seqplayer,

   midiBank_ptr);
alCSPSetBank(&seqplayer[1].seqplayer,

   midiBank_ptr);
#else
alSeqpSetBank(&seqplayer[0].seqplayer,

   midiBank_ptr);
alSeqpSetBank(&seqplayer[1].seqplayer,

   midiBank_ptr);
#endif /* _AUDIO_COMPACTMIDI_ */

}

/*-----------------------------------
Create and activate the audio thread
-------------------------------------*/
void auCreateAudioThread(NNSched *sched)
{
osCreateThread(&audioThread, AUDIO_THREAD_ID,
 audioProc, 
(void *)sched,
(audioThreadStack+AUDIO_STACKSIZE/sizeof(u64)),
AUDIO_THREAD_PRI);
osStartThread(&audioThread);
}

/*------------------------------
Main of the sequence reprodction
--------------------------------*/
int main00(NNSched* sched)
{
OSMesgQueue msgQ;
OSMesg msgbuf[MAX_MESGS];
NNScClient client;
u32 seqno;

/* create message queue for VI retrace */
osCreateMesgQueue(&msgQ, msgbuf, MAX_MESGS);

/* Set sequence O to sequence player O */
auSeqPlayerSetFile(0,2);

/* add client to shceduler */
nnScAddClient(sched, &client, &msgQ);

seqno = 0;
auSeqPlayerPlay(seqno);
while(1){
(void) osRecvMesg(&msgQ, NULL, OS_MESG_BLOCK);
/* If the sequence has stopped, repeat it */
if(auSeqPlayerState(0) == AL_STOPPED){
auSeqPlayerPlay(seqno);
}
}

/* exit label */
return MAIN_01;
}

/*---------------------------------------------
Reproduce the sequence
Input:
seqplayer_no: The sequence player number that
starts the reproduction.
If the sequence player is not in AL_STOPPED
state, return FALSE.
----------------------------------------------*/
int auSeqPlayerPlay(u32 seqplayer_no)
{
#ifndef _AUDIO_COMPACTMIDI_
s32 seqdata_len;
u32 seqno;
#endif /* _AUDIO_COMPACTMIDI_ */

#ifdef _AUDIO_DEBUG_
if(seqplayer_no > 1){
osSyncPrintf("seqplayer_no over!!\n");
return FALSE;
}
#endif /* _AUDIO_DEBUG_ */

/* check seqplayer state. */
if(seqplayer[seqplayer_no].seqplayer.state
   != AL_STOPPED){
#ifdef _AUDIO_DEBUG_
osSyncPrintf
   ("sequence player %d is playing\n",seqplayer_no);
#endif /* _AUDIO_DEBUG_ */
return FALSE;
}

#ifdef _AUDIO_COMPACTMIDI_
alCSeqNew(&seqplayer[seqplayer_no].sequence, 
seqplayer[seqplayer_no].seqdata_ptr);
alCSPSetSeq(&seqplayer[seqplayer_no].seqplayer, 
&seqplayer[seqplayer_no].sequence);
alCSPPlay(&seqplayer[seqplayer_no].seqplayer);
#else
seqno = seqplayer[seqplayer_no].seqno;
seqdata_len = seqHeaderfile_ptr->seqArray[seqno].len;
alSeqNew(&seqplayer[seqplayer_no].sequence,

seqplayer[seqplayer_no].seqdata_ptr, seqdata_len);
alSeqpSetSeq(&seqplayer[seqplayer_no].seqplayer,

&seqplayer[seqplayer_no].sequence);
alSeqpPlay(&seqplayer[seqplayer_no].seqplayer);
#endif /* _AUDIO_COMPACTMIDI_ */
return TRUE;
}