Appendix 10

Listing for DFM 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 2 /* resource ID of our 56k code algorithm */

WindowPtr myWindow;

MenuHandle myMenus[2];

int OurVolume;

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

short OnLastBuf,dataLoaded=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 = "\pDFM RealTime Console";

console_options.txFont = 1;

console_options.nrows = 30;

console_options.ncols = 60;

console_options.pause_atexit = TRUE;

printf(">>> RealTime 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)

{

/* Memory locations for general use */

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

#define DELAY 0x02

#define CYCLE_A 0x03

#define CYCLE_B 0x04

#define SINE_TABLE_START 0x05

#define SINE_TABLE_END 0x06

#define SINE_TABLE_SIZE 0x07

#define REPEAT_A 0x08

#define REPEAT_COUNTER 0x09

/* Amplitude envelope parameters DFM generator */

#define AMP 0x10

#define AMP_COUNTER 0x11

#define AMP_STATUS 0x12

#define AMP_CURRENT 0x13

#define AMP_RATE12 0x14

#define AMP_DURATION12 0x15

#define AMP_RATE23 0x16

#define AMP_DURATION23 0x17

#define AMP_RATE34 0x18

#define AMP_DURATION34 0x19

#define AMP_RATE45 0x1A

#define AMP_DURATION45 0x1B

#define AMP_RATE56 0x1C

#define AMP_DURATION56 0x1D

/* Parameters for DFM carrier */

#define CARRIER_FREQ 0x20

#define CARRIER_PHASE 0x21

/* Parameters and modulation index envelope for modulator (generator) 1 */

#define MODULATOR1_FREQ 0x30

#define MODULATOR1_INDEX 0x31

#define MODULATOR1_PHASE 0x32

#define INDEX1_COUNTER 0x33

#define INDEX1_STATUS 0x34

#define INDEX1_CURRENT 0x35

#define INDEX1_RATE12 0x36

#define INDEX1_DURATION12 0x37

#define INDEX1_RATE23 0x38

#define INDEX1_DURATION23 0x39

#define INDEX1_RATE34 0x3A

#define INDEX1_DURATION34 0x3B

#define INDEX1_RATE45 0x3C

#define INDEX1_DURATION45 0x3D

#define INDEX1_RATE56 0x3E

#define INDEX1_DURATION56 0x3F

/* Parameters and modulation index envelope for modulator (generator) 2 */

#define MODULATOR2_FREQ 0x40

#define MODULATOR2_INDEX 0x41

#define MODULATOR2_PHASE 0x42

#define INDEX2_COUNTER 0x43

#define INDEX2_STATUS 0x44

#define INDEX2_CURRENT 0x45

#define INDEX2_RATE12 0x46

#define INDEX2_DURATION12 0x47

#define INDEX2_RATE23 0x48

#define INDEX2_DURATION23 0x49

#define INDEX2_RATE34 0x4A

#define INDEX2_DURATION34 0x4B

#define INDEX2_RATE45 0x4C

#define INDEX2_DURATION45 0x4D

#define INDEX2_RATE56 0x4E

#define INDEX2_DURATION56 0x4F

double amplitude,freqC;

double freqM1,alpha1,beta1,modulationIndex1,output1;

double freqM2,alpha2,beta2,modulationIndex2,output2;

long carrier,modulator1,modulator2;

short xyAddress,counter1,counter2,counter3,overflow;

long xyValue;

long sineStartAddress,sineEndAddress,sineSize;

long delay,cycleA,cycleB,repeat,index1Inc;

double time,ampCorrection,freqCorrection,mIndexCorrection;

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

CSoundAccelerator *ourCard; /* our card object */

long amp;

long ampRate12,ampRate23,ampRate34,ampRate45,ampRate56;

long ampDuration12,ampDuration23,ampDuration34,ampDuration45,ampDuration56;

long mIndex1;

long mIndex1Rate12,mIndex1Rate23,mIndex1Rate34,mIndex1Rate45,mIndex1Rate56;

long mIndex1Duration12,mIndex1Duration23,mIndex1Duration34,mIndex1Duration45;

long mIndex1Duration56;

long mIndex2;

long mIndex2Rate12,mIndex2Rate23,mIndex2Rate34,mIndex2Rate45,mIndex2Rate56;

long mIndex2Duration12,mIndex2Duration23,mIndex2Duration34,mIndex2Duration45;

long mIndex2Duration56;

/* 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);

if (dataLoaded == 0)

{

amplitude = 100.0;

freqC = 0.0;

freqM1 = 1000.0; /* resulation = 20 Hz */

modulationIndex1 = 1.0;

freqM2 = 1000.0;

modulationIndex2 = 0.0;

sineStartAddress = 256;

sineSize = 2048;

delay = 117; /* 101 for SACD 1,117 for SACD 2 */

cycleA = 10;

cycleB = 65535/100;

repeat = 50;

sineEndAddress = sineStartAddress + sineSize - 1;

ampCorrection = 8388607.0 / 100.0;

freqCorrection = 20.0;

mIndexCorrection = 1900.0 / (2.8 * 2.0);

amp = (long) (amplitude * ampCorrection);

carrier = (long) (freqC / freqCorrection);

modulator1 = (long) (freqM1 / freqCorrection);

modulator2 = (long) (freqM2 / freqCorrection);

mIndex1 = modulationIndex1 * mIndexCorrection;

mIndex2 = modulationIndex2 * mIndexCorrection;

printf("Loading sine table into Y memory...\n");

ourCard->LoadXY(0,SINE_TABLE_START,sineStartAddress);

ourCard->LoadXY(0,SINE_TABLE_END,sineEndAddress);

ourCard->LoadXY(0,SINE_TABLE_SIZE,sineSize);

for (counter1 = sineStartAddress; counter1 <= sineEndAddress+sineSize; counter1++)

{

temp0 = (double) (counter1 - sineStartAddress) / (double) (sineSize);

temp1 = sin(TWOPI * temp0);

xyValue = (long) (8388607.0 * temp1);

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

}

printf("Sine table loaded.\n");

printf("Now loading algorithm parameters into memory...\n");

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

ourCard->LoadXY(0,CYCLE_A,cycleA);

ourCard->LoadXY(0,CYCLE_B,cycleB);

ourCard->LoadXY(0,REPEAT_A,repeat);

ourCard->LoadXY(0,CARRIER_FREQ,carrier);

ourCard->LoadXY(0,MODULATOR1_FREQ,modulator1);

ourCard->LoadXY(0,MODULATOR1_INDEX,mIndex1);

ourCard->LoadXY(0,MODULATOR2_FREQ,modulator2);

ourCard->LoadXY(0,MODULATOR2_INDEX,mIndex2);

ourCard->LoadXY(0,AMP,amp);

ourCard->LoadXY(0,AMP_RATE12,ampRate12);

ourCard->LoadXY(0,AMP_DURATION12,ampDuration12);

ourCard->LoadXY(0,AMP_RATE23,ampRate23);

ourCard->LoadXY(0,AMP_DURATION23,ampDuration23);

ourCard->LoadXY(0,AMP_RATE34,ampRate34);

ourCard->LoadXY(0,AMP_DURATION34,ampDuration34);

ourCard->LoadXY(0,AMP_RATE45,ampRate45);

ourCard->LoadXY(0,AMP_DURATION45,ampDuration45);

ourCard->LoadXY(0,AMP_RATE56,ampRate56);

ourCard->LoadXY(0,AMP_DURATION56,ampDuration56);

ourCard->LoadXY(0,INDEX1_RATE12,mIndex1Rate12);

ourCard->LoadXY(0,INDEX1_DURATION12,mIndex1Duration12);

ourCard->LoadXY(0,INDEX1_RATE23,mIndex1Rate23);

ourCard->LoadXY(0,INDEX1_DURATION23,mIndex1Duration23);

ourCard->LoadXY(0,INDEX1_RATE34,mIndex1Rate34);

ourCard->LoadXY(0,INDEX1_DURATION34,mIndex1Duration34);

ourCard->LoadXY(0,INDEX1_RATE45,mIndex1Rate45);

ourCard->LoadXY(0,INDEX1_DURATION45,mIndex1Duration45);

ourCard->LoadXY(0,INDEX1_RATE56,mIndex1Duration56);

ourCard->LoadXY(0,INDEX1_DURATION56,mIndex1Duration56);

ourCard->LoadXY(0,INDEX2_RATE12,mIndex2Rate12);

ourCard->LoadXY(0,INDEX2_DURATION12,mIndex2Duration12);

ourCard->LoadXY(0,INDEX2_RATE23,mIndex2Rate23);

ourCard->LoadXY(0,INDEX2_DURATION23,mIndex2Duration23);

ourCard->LoadXY(0,INDEX2_RATE34,mIndex2Rate34);

ourCard->LoadXY(0,INDEX2_DURATION34,mIndex2Duration34);

ourCard->LoadXY(0,INDEX2_RATE45,mIndex2Rate45);

ourCard->LoadXY(0,INDEX2_DURATION45,mIndex2Duration45);

ourCard->LoadXY(0,INDEX2_RATE56,mIndex2Duration56);

ourCard->LoadXY(0,INDEX2_DURATION56,mIndex2Duration56);

printf("Algorithm parameters loaded.\n");

dataLoaded = 1;

}

ourCard->DoHostCmd(0);

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

while (ourCard->TestHF3() IS 1)

{

}

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

}