# 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.

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

Nintendo® Confidential
Copyright © 1999
Nintendo of America Inc. All Rights Reserved
Nintendo and N64 are registered trademarks of Nintendo
Last Updated March, 1999