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; }