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