/************************************************** ERIK S. WHEELER IIR using LINKED LIST Presented: Echo Cancellation Group DSP Project Presentation Conference Mississippi State University 12 / 4 / 95 EE 4733/6733 -- Digital Signal Processing Instructor -- Dr. Joseph Picone Group Members: Vince J. Allen (allen@isip.MsState.Edu) Mark E. Henderson (henders@isip.MsState.Edu) Erik S. Wheeler (wheeler@isip.MsState.Edu) John L. Williams (SPwillia@EE.MsState.Edu) ***************************************************/ #include #include #include #define FALSE 0 #define TRUE 1 #define MAXVALUE 1000 #define MAXLENGTH 32000 #define NTAPS 20 /* Number of Taps */ #define ECHO "xfile.dat" /* Default Values to avoid */ #define FILTER "hfile.dat" /* compiler warnings */ #define OUTPUT "yfile.dat" typedef float datatype; typedef struct listelement_type { datatype dataitem; struct listelement_type *next; struct listelement_type *prev; } listelement; void Usage(char *argv[]) { printf("\nUsage: %s ECHO FILTER OUTPUT [flags]\n", argv[0]); printf("****************************************************\n"); printf("ECHO = Binary file containing echo response of input signal\n"); printf("FILT = Binary file to contain [containing] Filter Coefficients\n"); printf("OUTPUT = Binary file to contain cancelled echo\n"); printf("[-mMAXLENGTH] = Maximum File Length (default = %d) \n",MAXLENGTH); printf("[-nNTAPS] = Number of Filter Taps (default = %d) \n",NTAPS); printf("NOTE:\n\tBrackets [] denote optional\n"); printf("\tALL FILES are SHORT INT (16 bit) (max value = %d)\n\n",10000); printf("\tThere are NO SPACES between the flags and values (i.e. -n1000)\n"); exit(1); } listelement_type * CreateCircularList (int length, float initval) { /* Creates a Circular List and returns a pointer to this list */ listelement_type * listptr =NULL; listelement_type * tempptr1=NULL; listelement_type * tempptr2=NULL; int lcv=0; if ((listptr = (struct listelement_type *) malloc (sizeof (listelement_type))) == NULL) { printf("\nMemory Allocation Error -- Execution Aborted\n"); exit(1); } listptr -> next = NULL; listptr -> prev = NULL; listptr -> dataitem = initval; tempptr1 = listptr; for (lcv=1;lcv next = NULL; tempptr2 -> prev = tempptr1; tempptr2 -> dataitem = initval; tempptr1 -> next = tempptr2; tempptr1 = tempptr2; } tempptr1 -> next = listptr; listptr -> prev = tempptr1; return listptr; } FILE * OpenFile(char * filename, char * mode) { /* Generic Open File function with error checking */ FILE *fp; if ((fp=fopen(filename,mode))==NULL) { printf("Cannot open file %s\n",filename); exit(1); } return fp; } datatype BinFileElement (FILE *fp) { short int hd_data=0; if (fread(&hd_data, sizeof(short int), 1, fp) != 1) { printf("Read Error"); fclose(fp); exit(1); } return ((datatype) hd_data); } void BinFileElementToList(FILE *fp, listelement_type * listptr) { /* Binary File Element To List with error checking */ short int hd_data=0; if (fread(&hd_data, sizeof(short int), 1, fp) != 1) { printf("Read Error"); fclose(fp); exit(1); } listptr -> dataitem = (datatype) hd_data; } void PrintQueueToFile (listelement_type * listptr, FILE *fp) { /* Used only for incrementally printing coefficient data to binary file */ listelement_type * startptr=listptr; short int hd_data; if (listptr == NULL) printf ("Queue is empty!\n"); else { hd_data = (short int)(MAXVALUE*listptr->dataitem); if (fwrite(&hd_data, sizeof(short int), 1, fp) != 1) { printf ("Read Error in Writing COEFF\n"); exit(1); } while (listptr -> next != startptr) { listptr = listptr->next; hd_data = (short int)(MAXVALUE*listptr->dataitem); if (fwrite(&hd_data, sizeof(short int), 1, fp) != 1) { printf ("Read Error in Writing COEFF\n"); exit(1); } } } } void PrintQueue (listelement_type * listptr) { /* Prints Entire circular list to screen (used mostly during debugging) */ listelement_type * startptr=listptr; if (listptr == NULL) printf ("Queue is empty!\n"); else { printf("%f\t", listptr->dataitem); while (listptr -> next != startptr) { listptr = listptr -> next; printf ("%f\t", listptr -> dataitem); } } printf ("\n"); } float Fabs (float x) { /* Returns the absolute value of a floating point number */ /* I have no idea why c doesn't provide a function like this, */ /* or if they do I could not find it. */ return sqrt(x*x); } datatype MultAndSum (listelement_type *x, listelement_type *h, int ntaps) { listelement_type *xs=x, *hs=h; datatype returndata = 0.0; int lcv = 0; x=x->next; h=h->next; while ((x!=xs)||(h!=hs)) { lcv++; returndata += x->dataitem * (+ h->dataitem); /* NEGATIVE COEFFICIENT HANDLED BY GetInitFilt */ x = x->next; h = h->next; } if ((x!=xs)||(h!=hs)||(lcv!=ntaps-1)) printf ("Synchro Error!\n"); return returndata; } void GetInitFilt (char *file, listelement_type *xptr, int length) { /* If Initial Filter Coefficient flag (-f) is set, filter coeffs. */ /* are preset to LAST values of filter file. This file will be */ /* overwritten during excution of code. */ FILE *fp; listelement_type *xstart=xptr; int i=0; fp = OpenFile (file, "rb"); while(idataitem = - xptr->dataitem/MAXVALUE; xptr = xptr->next; i++; } fclose(fp); PrintQueue(xstart); } void PrintToFile (short int hd_data, FILE *fp, char *file) { if (fwrite(&hd_data, sizeof(short int), 1, fp) != 1) { printf ("Read Error in %s\n",file); exit(1); } } int main (int argc, char *argv[]) { /* Main IIR Code */ /* VARIABLES AND INITIALIZATIONS */ FILE *echofp, *outfp; char ch1, ch2; int i, fileflag=0; int maxlength = MAXLENGTH; int ntaps = NTAPS; datatype echo=0.0; listelement_type * delaysp; listelement_type * filtcoeffsp; char *echofile = ECHO; char *outputfile = FILTER; char *filtfile = OUTPUT; /* EVALUATE COMMAND LINE ARGUMENTS */ /* NO SPACES BETWEEN FLAG AND VALUE, AND FILES MUST BE SPECIFIED */ /* Please note: Files must be input in order, but flags may */ /* be input at any time (before, during, or after file inputs). */ /* What do you think, cool huh? */ for (i=1;idataitem=1; echofp = OpenFile(echofile,"rb"); outfp = OpenFile(outputfile,"wb"); for (i=0;idataitem = echo + MultAndSum(delaysp, filtcoeffsp, ntaps); /* Write output to file */ PrintToFile (((short int)delaysp->dataitem),outfp,outputfile); /* Increment delay pointer */ delaysp = delaysp->prev; } /* House Keeping */ fclose (echofp); fclose (outfp); }