test3.c 7.28 KB
/*====================================================================
 * test3.c
 *
 * Synopsis:  This file contains a simple test for the audiotest suite
 *   Test the priority voice stealing functionality. Start by playing
 *   a number of voices at a low priority, and while increasing the
 *   priority of the requested voices, steal the voices. The audio output
 *   should be a slow climb and descent in pitch, with repeated notes 
 *   audible.
 *
 * Copyright 1993, Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics,
 * Inc.; the contents of this file may not be disclosed to third
 * parties, copied or duplicated in any form, in whole or in part,
 * without the prior written permission of Silicon Graphics, Inc.
 *
 * RESTRICTED RIGHTS LEGEND:
 * Use, duplication or disclosure by the Government is subject to
 * restrictions as set forth in subdivision (c)(1)(ii) of the Rights
 * in Technical Data and Computer Software clause at DFARS
 * 252.227-7013, and/or in similar or successor clauses in the FAR,
 * DOD or NASA FAR Supplement. Unpublished - rights reserved under the
 * Copyright Laws of the United States.
 *====================================================================*/
#include "audiotest.h"
#include "audio.h"
#include <libaudio.h>


#define P_FRAME_TIME     250000
#define P_PLAY_TIME     4000000
#define P_STOP_TIME        2000

#define PLYR3_VIRTUAL_VOICES    21
#define PLYR3_PHYSICAL_VOICES   3
#define PLYR3_MAX_FRAMES	100000
#define PLYR3_UPDATES		140


/**** Share the heap with other test files, so have external ****/
extern ALHeap     gHeapRec;
extern u8         gHeapBuf[AUDIO_HEAP_SIZE];
extern u32        gTestDone;


/**** Prototypes and test control structure ****/
void InitTest3 (u32 subTestNum);
void StopTest3 (u32 subTestNum); 
void RetraceTest3 (void *t);

static s32 __freeVoice(s16 priority);
 
ALMicroTime __plyr3VoiceHandler(void *node);

test_cntrl Test3 = {
    &InitTest3,      /* void *InitTest; */
    &StopTest3,      /* void *StopTest; */
    NULL,
    &RetraceTest3,   /* void *retraceProc */
    NULL,            /* void *retraceData */
    1                /* u32  numSubTests */
};


/**** define a player structure for my test to use. ****/
typedef struct {
    ALPlayer            node;           /* note: must be first in structure */
    ALSynth             *drvr;          /* reference to the client driver   */
} player3;

static player3           *plyr3;

enum {
    P_PLAYING,
    P_STOPPING,
    P_STOPPED,
    P_FREE
};

typedef struct {
    ALVoice     voice;
    ALMicroTime timeLeft;
    s32         state;
} VoiceState;

/**** Globals unique to this test ****/
static ALBank           *gMidiBank;
static VoiceState       voiceState[PLYR3_VIRTUAL_VOICES];

static ALVoiceConfig    config = { 64, 0, 0 }; /* priority, fxBus, unityPitchFlag */
static s32              pitchIndex;
static f32              pitch = 1.0f;
static s16              vol = 0x3000;
static u8               pan = 64;
static u8               fxmix = 80;
static ALMicroTime      deltaTime = 0;
static s32              increment = 1;
static s32              centsArray[] = {-1200,-1100,-1000,-900,-800,-700,-600,
                                        -500,-400,-300,-200,-100,0,100,200,
                                        300,400,500,600,700,800,900,1000,
                                        1100,1200};

void InitTest3 (u32 subTestNum) 
{
    ALSynConfig         c;
    u32                 bankLen;
    ALBankFile          *bankPtr;
    amConfig            amc;
    u32                 i;
    VoiceState          *vs;
    
    alHeapInit(&gHeapRec, gHeapBuf, sizeof(gHeapBuf));    

    for (i = 0; i < PLYR3_VIRTUAL_VOICES; i ++) {
        vs = &voiceState[i];
        vs->state = P_STOPPED;
        vs->timeLeft = 0;
    }
    
    /**** Load the bank file from ROM ****/
    bankLen = _midibankSegmentRomEnd - _midibankSegmentRomStart;
    bankPtr = alHeapAlloc(&gHeapRec, 1, bankLen);
    romCopy(_midibankSegmentRomStart, (char *)bankPtr, bankLen);

    alBnkfNew(bankPtr, (u8 *) _miditableSegmentRomStart);
    gMidiBank = bankPtr->bankArray[0];

    /**** Create the Audio Manager ****/
    c.maxVVoices = PLYR3_VIRTUAL_VOICES;
    c.maxPVoices = PLYR3_PHYSICAL_VOICES;
    c.maxUpdates = PLYR3_UPDATES;
    c.dmaproc    = 0;                  /* audio mgr will fill this in */
    c.fxType     = AL_FX_NONE; 
    c.heap       = &gHeapRec;
    
    amc.outputRate = 44100;
    amc.framesPerField = NUM_FIELDS;
    amc.maxACMDSize = MAX_RSP_CMDS;
    amCreateAudioMgr(&c, AUDIO_PRIORITY, &amc);

    /**** Set up the player, and sign in to the driver ****/
    plyr3 = alHeapAlloc(&gHeapRec,1,sizeof(player3));
    plyr3->node.next       = NULL;
    plyr3->node.clientData = plyr3;
    plyr3->drvr = &alGlobals->drvr;
    plyr3->node.handler = __plyr3VoiceHandler;

    alSynAddPlayer(plyr3->drvr, &plyr3->node);
    pitchIndex = 0;
}

void StopTest3(u32 subTestNum)
{
    alSynRemovePlayer(plyr3->drvr, &plyr3->node);
    amDestroyAM();
}

void RetraceTest3(void *t)
{
    /* this test doesn't do anything in the non audio thread retrace */
}

ALMicroTime __plyr3VoiceHandler(void *node)
{
    VoiceState  *vs;
    VoiceState  *vstate = 0;
    ALWaveTable *wavetable;
    s32 i;
    
    wavetable = gMidiBank->instArray[0]->soundArray[0]->wavetable;

    /*
     * handle currently playing voices
     */
    for (i = 0; i < PLYR3_VIRTUAL_VOICES; i++) {
        vs = &voiceState[i];
        
        vs->timeLeft -= P_FRAME_TIME;

        if (vs->timeLeft <= 0) { /* time to take some action */

            switch (vs->state) {
              case (P_PLAYING):
                  alSynSetVol(plyr3->drvr, &vs->voice, 0, P_STOP_TIME);
                  vs->state    = P_STOPPING;
                  vs->timeLeft = P_STOP_TIME;
                  break;

              case (P_STOPPING):
                  osSyncPrintf("freeing voice 0x%x\n", vs->voice);
                  alSynStopVoice(plyr3->drvr, &vs->voice);
                  alSynFreeVoice(plyr3->drvr, &vs->voice);
                  vs->state     = P_STOPPED;
                  vs->timeLeft  = 0;
                  break;

              case (P_STOPPED):
                  vs->timeLeft  = 0;
                  vstate = vs; /* candidate to start later */
                  break;
            }
        }
    }

    /*
     * start a new voice if we can
     */
    if (vstate) {

        if (alSynAllocVoice(plyr3->drvr, &vstate->voice, &config)) {
            if(vstate->voice.pvoice) {

                pitch = alCents2Ratio(centsArray[pitchIndex]);
                alSynStartVoiceParams(plyr3->drvr, &vstate->voice, wavetable,
                                      pitch, vol, pan, fxmix, deltaTime);
                vstate->state    = P_PLAYING;
                vstate->timeLeft = P_PLAY_TIME;

                config.priority++;
                pitchIndex += increment;

                if ((pitchIndex >= 24) || (pitchIndex <= 0)) {
                    increment = -increment;
                }
                    
                osSyncPrintf("starting voice 0x%x %d\n", vstate->voice,
                             pitchIndex);
                
            } else {
                /* couldn't get a physical voice so don't bother */
                alSynFreeVoice(plyr3->drvr, &vstate->voice);
            }
        }
    }
    
    return P_FRAME_TIME;
}