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.
/*---------------- 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; }
Nintendo® Confidential
Copyright © 1999
Nintendo of America Inc. All Rights Reserved
Nintendo and N64 are registered trademarks of Nintendo
Last Updated March, 1999