3-6 Audio Playback Samples
The following code demonstrates how to play a MIDI sequence in your game. Another audio sample on the CD demonstrates how to play sound effects. See [Appendix C Sample Description] about the sample program. os-fuctions and al-functions are included in libraries. 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.
3-6-1 Sequence Playback 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;/* 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;/* 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 Sequence Playback
---------------------------------------------------------------------------*/
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);
/* create message queue for VI retrace */
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;
}
/*-------------------------------------------------------------------------
Playback 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;
}