onechannel.c 9.51 KB
/* sequence player test */

#include <em.h>
#include <os.h>
#include <verify.h>
#include <libaudio.h>
#include "onechannel.h"

#define MAX_VOICES      8
#define MAX_UPDATES     64
#define MAX_MIDI_LENGTH 0x10000         /* What should this be ? */
#define EVT_COUNT       32
#define	FRAME_SIZE	160

#define MAX_BUFFER_LENGTH 200

#define	REVERB_DELAY_LENGTH	640

#define	INFO_PHYSADDR	0x00000000

/*
 * Symbol generated by "makerom" to indicate the end of the code segment
 * in virtual (and physical) memory
 */
extern char _codeSegmentEnd[];

/*
 * Symbols generated by "makerom" to tell us where the static segment is
 * in ROM.
 */

extern char _staticSegmentRomStart[], _staticSegmentRomEnd[];
extern char _seqSegmentRomStart[], _seqSegmentRomEnd[];
extern char _bankSegmentRomStart[], _bankSegmentRomEnd[];

/*
 * Stacks for the threads as well as message queues for synchronization
 */

char	bootStack[STACKSIZE];

static void	idle(void *);
static void	mainproc(char *);

static OSThread	idleThread;
static char	idleThreadStack[STACKSIZE];

static OSThread	mainThread;
static char	mainThreadStack[STACKSIZE];

OSMesgQueue	dmaMessageQ, taskMessageQ, retraceMessageQ;
OSMesg		dmaMessageBuf, taskMessageBuf, retraceMessageBuf;
OSMesg		dummyMessage;

/*
 * necessary for RSP connection:
 */
unsigned long int uCode[1024];          /* uCode */
unsigned long int uCodeData[512];       /* Static data for microcode */
unsigned long int uCodeBoot[512];       /* Boot code for microcode */

Task            tlist[2];               /* globaltask list      */

static void meminit(char *ptr, int len);

ALGlobals       g;
ALSynConfig     c;
ALSeqPlayer     sequencePlayer;
ALSeqpConfig    seqc;
ALSeq           sequence;
PVoice          pvoices[MAX_VOICES];
ALVoice         vvoices[MAX_VOICES];
ALParam         updates[MAX_UPDATES];
ALSound         sound;
short		fxBuf[8192];

/*
 * Double buffered storage for wavetable data
 */
char            waveBuffers[2][MAX_VOICES][MAX_BUFFER_LENGTH];
int             nextBuffer = 0;
int             curBuf = 0;

ALEventListItem   evtList[EVT_COUNT];
ALVoiceState      voiceList[MAX_VOICES];

char            seq_array[MAX_MIDI_LENGTH];

int             errno;
void            *__errnoaddr;

/*
 * Double-buffered dynamic segments
 */

Dynamic	dynamicBuffer[2];

int dmaCallBack(int addr, int len)

{
    void * freeBuffer;
    
    if (1){
        freeBuffer = &(waveBuffers[curBuf][nextBuffer][0]);
        osDmaCopy((unsigned int) addr, osVirtualToPhysical(freeBuffer), len);
        nextBuffer++;
        return (int) freeBuffer;
    } else
        return addr;
}

boot(void *arg)
{
    osInitialize();
    osCreateThread(&mainThread, (void(*)(void *))mainproc, arg,
		  mainThreadStack+STACKSIZE, OS_IM_ALL, (OSPri)10);
    osStartThread(&mainThread);
}

static
void mainproc(char *argv)
{
    /*
     * This must be 64 bit aligned
     */
    VerifyInfo	*info = (VerifyInfo *)PHYSICAL_TO_KSEG0(VERIFY_INFO_PHYSADDR);

    ALSeqPlayer *seqp = &sequencePlayer;
    ALSeq       *seq  = &sequence;
    ALSound     *snd  = &sound;
    int         len;
    int         log;
    int         argp = 0;
    int         ftempo = 0;
    int         rspsim = 0;
    char        *ptr;   
    ALBank      *bank=0;
    ALADPCMBook *adpcmTable;
    int         adpcmTableLen;
    int         bankLen;

    char        fname[] = "onechannel";

    ALInstrument  *inst;
    ALSound       *asound;
        
    Task        *tlistp;
    int         frame=0;
    int         clcount;
    int         current = 0;
    char        *staticSegment;
    char        *bankSegment;
    Dynamic     *dynamiccp;
    Acmd        *cmdlp;
    short       *audioOp;

    meminit((char *)&g, sizeof(ALGlobals));
    meminit((char *)&c, sizeof(ALSynConfig));

    meminit((char *)&sequencePlayer, sizeof(sequencePlayer));
    meminit((char *)&sequence, sizeof(sequence));

    if (argv[argp] == 'r'){
        rspsim = 1;
        emPrintf("Using the RSP simulator\n");
        argp++;
    }
    else
        rspsim = 0;

    log = 0;
    if (argv[argp] == 'l'){
        if (rspsim){
            emPrintf("Logging rsp registers to file\n");
            log = 1;
        }
        argp++;
    }

    if (argv[argp] == 'f'){
        ftempo = 1;
        emPrintf("Tempo increased by a factor of 3\n");
        argp++;
    }
    else
        ftempo = 0;

    /*
     * Setup the threads
     */
    
    /*
     * Create idle thread
     */
    osCreateThread(&idleThread, idle, (void *)0, idleThreadStack+STACKSIZE,
		  OS_IM_ALL, (OSPri)0);
    osStartThread(&idleThread);

    osCreateMesgQueue(&dmaMessageQ, &dmaMessageBuf, 1);
    osSetEventMesg(OS_EVENT_PI, &dmaMessageQ, dummyMessage);

    osCreateMesgQueue(&taskMessageQ, &taskMessageBuf, 1);
    osSetEventMesg(OS_EVENT_SP, &taskMessageQ, dummyMessage);

    /* Retrace interrupts aren't used as yet */
    
    osCreateMesgQueue(&retraceMessageQ, &retraceMessageBuf, 1);
    osSetEventMesg(OS_EVENT_VI, &retraceMessageQ, dummyMessage);
    
    /*
     * Put the Bank information right after the code/data segment
     */

    bankSegment = _codeSegmentEnd;
    osDmaCopy((unsigned int)_bankSegmentRomStart,
            osVirtualToPhysical(bankSegment),
            _bankSegmentRomEnd - _bankSegmentRomStart);
    (void) osRecvMesg(&dmaMessageQ, OS_MESG_BLOCK);

    bankLen = _bankSegmentRomEnd - _bankSegmentRomStart;
    
    /*
     * Copy over the sequence into the seq_array
     */

    osDmaCopy((unsigned int)_seqSegmentRomStart,
            osVirtualToPhysical(seq_array),
            _seqSegmentRomEnd - _seqSegmentRomStart);
    (void) osRecvMesg(&dmaMessageQ, OS_MESG_BLOCK);
    ptr = seq_array;

    /* Out by one I think - which way ? */
    len = _seqSegmentRomEnd - _seqSegmentRomStart;
    
    /*
     * initialize simulation
     */

    emAudioInit(fname);
    if (rspsim)
        emRSPInit(&(uCode[0]), &(uCodeData[0]), &(uCodeBoot[0]));
        
    /*************************************************************
     * initialize the Audio Library
     *************************************************************/
    c.maxVVoices = MAX_VOICES;
    c.maxPVoices = MAX_VOICES;
    c.maxUpdates = MAX_UPDATES;
    c.dmaproc    = &dmaCallBack;
    
    alInit(&g, &c);
    
    seqc.maxVoices      = MAX_VOICES;
    
    alSeqpNew(seqp, &seqc);
    
    alSeqNew(seq, ptr, len);    

    alSeqpSetSeq(seqp, seq);
    
    alBnkfNew((ALBankFile *)bankSegment, _staticSegmentRomStart);
    bank = ((ALBankFile *)bankSegment)->bankArray[0];
    alSeqpSetBank(seqp, bank);

    alSeqpPlay(seqp);

    if (ftempo){
        alSeqpSetTempo(seqp, seqp->uspt/3);
    }
    
    while (seqp->state == AL_PLAYING) {
        frame++;
        
        /*
         * Where the task list goes in DRAM
         */
        tlistp = &tlist[current];
        
        /*
         * Swap dynamic buffers
         */
        dynamiccp = &dynamicBuffer[current];

        /*
         * Where the command list goes in DRAM
         */
	cmdlp = dynamiccp->cmdList;       

        /*
         * Where the audio goes in DRAM
         */
        audioOp = (short *) osVirtualToPhysical(dynamiccp->aud.buffer.audio);
        
        /*
         * Tell RCP where each segment is
         */
        
        aSegment(cmdlp++, 0, 0);
        aSegment(cmdlp++, DYNAMIC_SEGMENT,
				osVirtualToPhysical(dynamiccp));
        
        /*
         * Call the frame handler ask for FRAME_SIZE samples 
         */

        cmdlp = alAudioFrame(cmdlp, &clcount, audioOp, FRAME_SIZE);

        /*
         * Build the audio task
         */       

        tlistp->t.dl = (unsigned long) dynamicBuffer[current].cmdList;
        tlistp->t.len = (cmdlp - dynamicBuffer[current].cmdList) * sizeof(Acmd);
        tlistp->t.type = M_AUDTASK;
        tlistp->t.ucode = (unsigned long *)
            osVirtualToPhysical((void *)&(uCode[0]));
        tlistp->t.ucode_data = (unsigned long *)
            osVirtualToPhysical((void *)&(uCodeData[0]));
        tlistp->t.ucode_data_len = 1536;

        /*
         * The new structure which is passed to RSP boot
         */
	info->rspListAddr      = osVirtualToPhysical((void *)tlistp->t.dl);
	info->rspListSize      = tlistp->t.len;
	info->rspListType      = ((4096-128) << 12) | tlistp->t.type;
	info->ucodeTextAddr    = (unsigned int) tlistp->t.ucode;
	info->ucodeDataAddr    = (unsigned int) tlistp->t.ucode_data;
	info->ucodeDataSize    = tlistp->t.ucode_data_len;
        
	info->bootUcodeAddr    = osVirtualToPhysical((void *) &(uCodeBoot[0]));
	info->magicNumber      = MAGICNUMBER; /* Kaelyn's birthday: 0x102594*/
	info->version          = VERSION;
        
        /*
         * Flush the cache
         */

        osWritebackDCacheAll();

        if (rspsim)
            /* Send command list to RSP */
            emRSPAudioFrame("onechannel", frame, (int) audioOp,
                            FRAME_SIZE, log);
        else{
            /* Send command list through the c-simulator */
            emTaskStart(tlistp, 1);
            (void)osRecvMesg(&taskMessageQ, OS_MESG_BLOCK);
        }
        
        /*
         * Stick the output in files
         */
        emAudioWrite(dynamiccp->aud.buffer.audio, FRAME_SIZE);
        
        /* Do some graphics stuff.....but only if there's time! */
        
/*        (void)osRecvMesg(&retraceMessageQ, M_BLOCK); */

        current ^= 1;

        /*
         * Swap buffers for wavetable storage
         */
        curBuf ^= 1;
        nextBuffer = 0;
    }
    emAudioFlush();
    
    alSeqpStop(seqp);

    alClose(&g);
}

static
void idle(void *arg)
{
	for (;;);
}

static
void meminit(char *ptr, int len)
{
    int i;

    for (i = 0; i < len; i++){
        *ptr++ = 0x5a;
    }
}