Appendix 5

Listing for AFM Not Realtime.c

#include <QuickDraw.h>

#include <MacTypes.h>

#include <FontMgr.h>

#include <WindowMgr.h>

#include <MenuMgr.h>

#include <TextEdit.h>

#include <DialogMgr.h>

#include <EventMgr.h>

#include <DeskMgr.h>

#include <FileMgr.h>

#include <ToolboxUtil.h>

#include <ControlMgr.h>

#include <console.h>

#include <stdlib.h>

#include <math.h>

#include "Class.h"

#include "Utils.h"

#include "GlobalDefs.h"

#include "CSoundAccelerator.h"

#include "Others.h"

/****************************************************************************/

#define kOurAlgorithmID 1 /* resource ID of our 56k code algorithm */

WindowPtr myWindow;

MenuHandle myMenus[2];

int OurVolume;

short *CurSample = NULL,*LastSample = NULL,*SampBuffer = NULL;

short OnLastBuf,loaded=0;

long MacBufSize,GrowAmt;

/****************************************************************************/

/* Prototypes for all the functions in this file. */

void InitApplication(void);

void CloseApplication(void);

void RunDSP(void);

SetUpMenus(void);

int DoMenuCommand(long mResult);

int MainEventLoop(void);

/****************************************************************************/

void main(void)

{

InitApplication();

while (MainEventLoop()) ;

CloseApplication();

}

/****************************************************************************/

void InitApplication(void)

{

/* Do standard Mac initializations. */

InitGraf(&thePort);

InitFonts();

FlushEvents(everyEvent,0);

InitWindows();

InitMenus();

TEInit();

InitDialogs(0L);

InitCursor();

MaxApplZone();

/* Open up a console window so we can write debugging info.

See Utils.c for details. */

#ifdef DEBUG

console_options.top = 40; /* set options for console window */

console_options.left = 2;

console_options.title = "\pDSPTest Console";

console_options.txFont = 1;

console_options.nrows = 30;

console_options.ncols = 60;

console_options.pause_atexit = TRUE;

printf(">>> DSPTest Up And Running <<<\n");

#endif

/*

/* The following statement is included as a check to see if we can

/* access our program's resources. When the project is run from

/* THINK C, the resource file <project name>.rsrc is automatically

/* opened. When an application is built, these resources are

/* automatically merged with the application.

/*

*/

if (GetResource('MENU', fileID) IS 0) {

SysBeep(20);

return;

}

/* Setup and draw our whopping big menu bar. */

SetUpMenus();

/* Get A5 for slot interrupt routine's use. */

GetOurA5();

/* Initialize the Sound Accelerator driver and class code. */

FailOSErr(InitSoundAcceleratorDriver());

}

/****************************************************************************/

void CloseApplication(void)

{

/* Release our global sample buffer. */

/* if (SampBuffer ISNOT NULL) DisposPtr(SampBuffer); */

}

/***************************************************************************************/

void RunDSP(void)

{

#define WAVE_TABLE_START 0x01 /* these parameters in X memory */

#define WAVE_TABLE_END 0x02

#define WAVE_TABLE_SIZE 0x03

#define WAVE_TABLE_INC 0x04

#define CYCLES 0x05

#define DELAY 0x06

#define AMPLIFICATION 0x07

#define ENVELOPE_TABLE_START 0x21 /* these parameters in X memory */

#define ENVELOPE_TABLE_END 0x22

#define ENVELOPE_TABLE_SIZE 0x23

#define ENVELOPE_TABLE_INC 0x24

double amplitude1,freqC1,freqM1,alpha1,beta1,mIndex1,r1,output1;

double amplitude2,freqC2,freqM2,alpha2,beta2,mIndex2,r2,output2;

short xyAddress,counter1,counter2,counter3,overflow;

short numOfWavePoints,numOfEnvelopePoints;

long xyValue;

double finalAmplitude,finalOutput,time,freqCorrection;

double temp0,temp1,temp2,temp3,maxAmp,maxOutput,maxValue,daOutput;

double factor,*data;

CSoundAccelerator *ourCard; /* our card object */

long waveTableStart,waveTableEnd,waveTableSize,waveTableInc;

long cycles,delay,amplification;

long envelopeTableStart,envelopeTableEnd,envelopeTableSize,envelopeTableInc;

long envelopeValue;

/* Create a card object, allocate a card and load our 56k code from a resource.

Then install the slot interrupt routine. Note that we pass the card object

itself as a value to be loaded into A1 when the slot manager calls the

slot managing routines. This way, the slot routines automatically know

what card is requesting service as well as how to service it. */

ourCard = MakeDirectObject(CSoundAccelerator)();

ourCard->Allocate(kOurAlgorithmID);

freqCorrection = 10.0; /* 10.0 */

finalAmplitude = 41943; /* max = 4194303 */

/* Attack part of pipe organ waveform */

/*

amplitude1 = 100.0;

freqC1 = 440.0;

freqM1 = 440.0;

mIndex1 = 1.7;

r1 = 0.68;

amplitude2 = 8.0;

freqC2 = 220.0;

freqM2 = 0.0;

mIndex2 = 0.0;

r2 = 1.0;

*/

/* Attack to sustain part of pipe organ waveform */

/*

amplitude1 = 100.0;

freqC1 = 440.0;

freqM1 = 440.0;

mIndex1 = 1.7;

r1 = 0.68;

amplitude2 = 8.0;

freqC2 = 220.0;

freqM2 = 0.0;

mIndex2 = 0.0;

r2 = 1.0;

*/

/* Sustain part of pipe organ waveform */

amplitude1 = 100.0;

freqC1 = 440.0;

freqM1 = 440.0;

mIndex1 = 1.7;

r1 = 0.68;

amplitude2 = 8.0;

freqC2 = 220.0;

freqM2 = 0.0;

mIndex2 = 0.0;

r2 = 1.0;

alpha1 = TWOPI * freqC1 / freqCorrection;

beta1 = TWOPI * freqM1 / freqCorrection;

alpha2 = TWOPI * freqC2 / freqCorrection;

beta2 = TWOPI * freqM2 / freqCorrection;

numOfWavePoints = 3800; /* 3800 */

waveTableStart = 0x0200; /* $0200 */

waveTableEnd = (long) numOfWavePoints - 1 + waveTableStart;

waveTableSize =(long) numOfWavePoints;

waveTableInc = 1; /* 1 */

cycles = 8 ; /* freqC */

delay = 220; /* 220 */

amplification = 1;

numOfEnvelopePoints = cycles;

envelopeTableStart = 0x0200;

envelopeTableSize = (long) numOfEnvelopePoints;

envelopeTableEnd = (long) numOfEnvelopePoints + envelopeTableSize - 1;

envelopeTableInc = 1;

xyValue = 0;

overflow = 0;

maxOutput = 0.0;

output1 = 0.0;

output2 = 0.0;

maxAmp = 4194303.0;

if (loaded == 0)

{

loaded=1;

printf("Calculating data using algorithm...\n");

/* Normalized Asymetrical FM synthesis */

data = (double *) calloc(numOfWavePoints + 1,sizeof(double));

/* 1st Asymetrical FM operator */

for (counter1 = 0; counter1 < numOfWavePoints; counter1++)

{

time = (double) counter1 / (double) numOfWavePoints;

temp1 = (exp((mIndex1/2.0) * (r1 - 1/r1) * cos(beta1 * time)));

output1 = temp1 * sin(alpha1 * time + mIndex1/2 * (r1 + 1/r1) * sin(beta1 * time));

temp2 = (exp((mIndex2/2.0) * (r2 - 1/r2) * cos(beta2 * time)));

output2 = temp2 * sin(alpha2 * time + mIndex2/2 * (r2 + 1/r2) * sin(beta2 * time));

*(data + counter1) = (amplitude1 * output1) + (amplitude2 * output2);

temp0 = fabs(*(data + counter1));

if (maxOutput < temp0)

{

maxOutput = temp0;

}

}

printf("End of calculation.\nLoading waveform into DSP Y memory...\n");

for (counter1 = 0; counter1 < numOfWavePoints; counter1++)

{

finalOutput = *(data + counter1)/maxOutput;

xyValue = (long) (finalOutput * finalAmplitude);

ourCard->LoadXY(1,waveTableStart+counter1,xyValue);

}

free(data);

printf("Now loading envelope data into X memory...\n");

for (counter1 = 0; counter1 < numOfEnvelopePoints; counter1++)

{

temp1 = (double) -counter1/numOfEnvelopePoints;

temp2 = 100.0 * exp(2.0*temp1);

temp2 = 100.0;

ourCard->LoadXY(0,envelopeTableStart+counter1,(long) temp2);

}

}

if (overflow == 0)

{

ourCard->LoadXY(0,WAVE_TABLE_START,waveTableStart);

ourCard->LoadXY(0,WAVE_TABLE_END,waveTableEnd);

ourCard->LoadXY(0,WAVE_TABLE_SIZE,waveTableSize);

ourCard->LoadXY(0,WAVE_TABLE_INC,waveTableInc);

ourCard->LoadXY(0,CYCLES,cycles);

ourCard->LoadXY(0,DELAY,delay);

ourCard->LoadXY(0,AMPLIFICATION,amplification);

ourCard->LoadXY(0,ENVELOPE_TABLE_START,envelopeTableStart);

ourCard->LoadXY(0,ENVELOPE_TABLE_END,envelopeTableEnd);

ourCard->LoadXY(0,ENVELOPE_TABLE_SIZE,envelopeTableSize);

ourCard->LoadXY(0,ENVELOPE_TABLE_INC,envelopeTableInc);

printf("All Data loaded.\n");

printf("Playing back data from DSP memory.\n");

ourCard->DoHostCmd(0);

printf("Waiting for HF3...\n");

while (ourCard->TestHF3() IS 1)

{

}

}

else

{

printf ("A register overflow has occured. Some values are too large.\n");

printf ("Aborting operation now.\n");

}

/*

ourCard->RemoveSlotInt();

*/

DestroyDirectObject(ourCard);

ourCard = NULL;

printf("\n");

}

/****************************************************************************

ALL the following procedures are standard Macintosh menu management

and main event loop stuff.

***************************************************************************/

/****************************************************************************/

SetUpMenus(void)

{

int i;

myMenus[appleM] = NewMenu( appleID, "\p\024" );

AddResMenu( myMenus[appleM], 'DRVR' );

myMenus[fileM] = GetMenu(fileID);

for ( (i=appleM); (i<=fileM); i++ ) InsertMenu(myMenus[i], 0) ;

DrawMenuBar();

}

/****************************************************************************/

int DoMenuCommand(long mResult)

{

Str255 name;

switch (HiWord(mResult)) {

case appleID:

GetItem(myMenus[appleM],LoWord(mResult),&name);

OpenDeskAcc(&name);

SetPort(myWindow);

break;

case fileID:

switch (LoWord(mResult)) {

case fmRunDSP:

RunDSP();

break;

case fmQuit:

return(0);

break;

}

break;

}

HiliteMenu(0);

return(1);

}

/****************************************************************************/

int MainEventLoop(void)

{

EventRecord myEvent;

WindowPtr whichWindow;

register char theChar;

SystemTask();

if (GetNextEvent(everyEvent,&myEvent)) {

switch (myEvent.what) {

case keyDown:

case autoKey:

theChar = myEvent.message & charCodeMask;

if ((myEvent.modifiers & cmdKey) ISNOT 0) {

return( DoMenuCommand(MenuKey(theChar)));

} else {

if ((theChar >= '0') AND (theChar <= '9')) {

OurVolume = theChar - '0';

}

}

break;

case mouseDown:

switch (FindWindow(myEvent.where,&whichWindow)) {

case inSysWindow:

SystemClick(&myEvent,whichWindow);

break;

case inMenuBar:

return(DoMenuCommand(MenuSelect(myEvent.where)));

break;

} /* end switch FindWindow */

break;

} /* end of switch myEvent.what */

} /* if */

return(1);

}