home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hacker Chronicles 2
/
HACKER2.BIN
/
151.SIGNALPR.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-06-15
|
16KB
|
373 lines
UNIT SignalProcessing;
INTERFACE
USES
DOS,
{$IFDEF DOSCrt}
DOSCrt,
{$ELSE}
Crt,
{$ENDIF}
Extended_Reals,
TextOps,
Global,
Transforms;
{----------------------------------------------------------------------------}
{- -}
{- SPS prints the SPS menu, and gives the user the choice of one of -}
{- several signal processing functins: -}
{- -}
{- 1. Integration of time domain data. -}
{- 2. Differentiation of time domain data. -}
{- 3. Fast Fourier Transform of time domain data. -}
{- 4. Adjust (+,-,*,/) time domain amplitude by a constant. -}
{- 5. Multiply time base by a factor. -}
{- 6. Subtract the mean of the time domain waveform. -}
{- -}
{- SPS is called AFTER the data has been fitted, a procedure invoked -}
{- the first time one chooses selection 3 from the Main Menu. -}
{- -}
{----------------------------------------------------------------------------}
PROCEDURE SPS;
(****************************************************************************)
IMPLEMENTATION
{----------------------------------------------------------------------------}
{- -}
{- Fitting accepts for input an array of NumPoints arbitrarily spaced -}
{- data points, and returns as output an array of 2^n evenly spaced -}
{- data points. The method of interpolation used is either linear -}
{- interpolation or natural cubic spline interpolation. -}
{- -}
{----------------------------------------------------------------------------}
PROCEDURE Fitting;
VAR
NewNumPoints : INTEGER; (* Number of points to interpolate to. *)
i : INTEGER; (* Counter variable. *)
j : INTEGER; (* Counter for NewNumPoints. *)
X1 : REAL; (* First x value. *)
x : REAL; (* Frequencies of fitted data. *)
increment : REAL; (* Distance between successive x-coor. *)
Error : BYTE; (* Error code for spline routine. *)
{----------------------------------------------------------------------------}
{- -}
{- Linear performs linear interpolation on the time domain data. -}
{- -}
{----------------------------------------------------------------------------}
PROCEDURE Linear;
VAR
m : REAL; (* Slope of interpolation line. *)
b : REAL; (* Y-intercept of interpolation line. *)
denom : REAL; (* Difference between succesive points. *)
j : INTEGER;
BEGIN {Linear}
i:=0;
X1:=time^[0];
TempXPtr^[0]:=time^[0];
TempYPtr^[0]:=ampl^[0];
increment:=(time^[NumPoints-1]-time^[0])/(NewNumPoints-1);
FOR j:=1 TO NewNumPoints-1 DO BEGIN
x:=X1+j*increment;
WHILE x > time^[i] DO INC (i,1);
(*** Calculate slope and y-intercept ***)
denom:=1/(time^[i]-time^[i-1]);
m:=(ampl^[i]-ampl^[i-1])*denom;
b:=(ampl^[i-1]*time^[i]-ampl^[i]*time^[i-1])*denom;
TempXPtr^[j]:=x;
TempYPtr^[j]:=m*x+b;
END; {FOR}
END; {Linear}
{----------------------------------------------------------------------------}
{- -}
{- CubicSpline performs a Cubic Spline interpolation on the time -}
{- domain data. The algorithm used is a modification of the algorithm -}
{- 3.4 of Numerical Analysis, 3rd ed. by Burden & Faires, p. 122. -}
{- -}
{- Error occurs if there is insufficient memory to perform the cubic -}
{- spline algorithm. -}
{----------------------------------------------------------------------------}
PROCEDURE CubicSpline (Error : BYTE);
VAR
temp : REAL; (* A temporary real variable. *)
b : TNVectorPtr; (* First spline coefficient. *)
c : TNVectorPtr; (* Second spline coefficient. *)
d : TNVectorPtr; (* Third spline coefficient. *)
h : TNVectorPtr; (* Dist. between successive data pts. *)
i : INTEGER;
j : INTEGER;
TopOfHeap : ^INTEGER;
dummy : CHAR;
BEGIN {CubicSpline}
Error:=0;
Mark(TopOfHeap);
IF MaxAvail <= SizeOf(b)
THEN Error:=1
ELSE New (b);
IF MaxAvail <= SizeOf(c)
THEN Error:=1
ELSE New (c);
IF MaxAvail <= SizeOf(d)
THEN Error:=1
ELSE New (d);
IF MaxAvail < SizeOf(h)
THEN Error:=1
ELSE New (h);
{--- If insufficient memory, then display error message and exit ---}
IF Error <> 0 THEN BEGIN
Release (TopOfHeap);
PrintErrorMsg ('Insufficient memory for cubic spline',
StartColumn,23,FALSE,dummy);
Exit;
END; {IF}
{--- Calculate spline coefficients ---}
FOR i:=0 TO NumPoints-2 DO
h^[i]:=time^[i+1]-time^[i];
b^[0]:=1;
OutArrayX^[0]:=0;
OutArrayY^[0]:=0;
FOR i:=1 TO NumPoints-2 DO BEGIN
temp:=3*(ampl^[i+1]*h^[i-1]-ampl^[i]*(time^[i+1]-time^[i-1])
+ampl^[i-1]*h^[i])/(h^[i-1]*h^[i]);
b^[i]:=2*(time^[i+1]-time^[i-1])-h^[i-1]*OutArrayX^[i-1];
OutArrayX^[i]:=h^[i]/b^[i];
OutArrayY^[i]:=(temp-h^[i-1]*OutArrayY^[i-1])/b^[i];
END; {FOR}
c^[NumPoints-1]:=0;
FOR i:=NumPoints-2 DOWNTO 0 DO BEGIN
c^[i]:=OutArrayY^[i]-OutArrayX^[i]*c^[i+1];
b^[i]:=(ampl^[i+1]-ampl^[i])/h^[i]-h^[i]*(c^[i+1]+2*c^[i])/3;
d^[i]:=(c^[i+1]-c^[i])/(3*h^[i]);
END; {FOR}
{--- Create NewNumPoints evenly spaced points ---}
X1:=time^[0];
increment:=(time^[NumPoints-1]-time^[0])/(NewNumPoints-1);
i:=0;
TempXPtr^[0]:=time^[0];
TempYPtr^[0]:=ampl^[0];
FOR j:=1 TO NewNumPoints-1 DO BEGIN
x:=X1+j*increment;
WHILE x > time^[i] DO INC (i,1);
temp:=x-time^[i-1];
TempXPtr^[j]:=x;
TempYPtr^[j]:=ampl^[i-1]+b^[i-1]*temp+c^[i-1]*sqr(temp)
+d^[i-1]*sqr(temp)*temp;
END; {FOR}
Release (TopOfHeap);
END; {CubicSpline}
BEGIN {Fitting}
{--- Calculate number of points to interpolate ---}
{--- to. Must be a power of two. ---}
i:=MinPower;
WHILE NumPoints > Pow2[i] DO INC (i,1);
NumFreqs:=Pow2[i-1];
NewNumPoints:=Pow2[i];
IF SPLINE THEN BEGIN
CubicSpline (Error);
IF Error <> 0 THEN SPLINE:=FALSE;
END; {IF}
IF NOT SPLINE THEN Linear;
NumPoints:=NewNumPoints;
ACCEPT:=true;
time^:=TempXPtr^;
ampl^:=TempYPtr^;
END; {Fitting}
{----------------------------------------------------------------------------}
{- -}
{- Integrate performs numerical integration on the time domain data -}
{- via the trapezoidal rule. Note that this procedure requires -}
{- approximately 2*m additions and 2*m multiplications. -}
{- -}
{----------------------------------------------------------------------------}
PROCEDURE integrate;
VAR
i : INTEGER; (* Counter. *)
h : REAL; (* Distance between successive points. *)
BEGIN {integrate}
h:=(time^[NumPoints-1]-time^[0])/(NumPoints);
TempXPtr^[0]:=0;
FOR i:=1 TO NumPoints-1 DO
TempXPtr^[i]:=TempXPtr^[i-1]+0.5*h*(ampl^[i-1]+ampl^[i]);
ampl^:=TempXPtr^;
END; {integrate}
{----------------------------------------------------------------------------}
{- -}
{- Differentiate performs numerical differentiation via the so-called -}
{- three point formulae. The routine requires approximately 2*m -}
{- additions and 2*m multiplications. -}
{- -}
{----------------------------------------------------------------------------}
PROCEDURE differentiate;
VAR
mm : INTEGER; (* mm = 2*m-1 = Num points in input array. *)
h : REAL; (* Inverse of distance between succ. points. *)
i : INTEGER; (* Counter. *)
BEGIN {differentiate}
mm:=NumPoints-1;
h:=(mm+1)/(time^[mm]-time^[0]);
TempXPtr^[0]:=0.5*(-3*ampl^[0]+4*ampl^[1]-ampl^[2])*h;
TempXPtr^[mm]:=0.5*(3*ampl^[mm]-4*ampl^[mm-1]+ampl^[mm-2])*h;
FOR i:=1 TO mm-1 DO
TempXPtr^[i]:=0.5*(ampl^[i+1]-ampl^[i-1])*h;
ampl^:=TempXPtr^;
END; {differentiate}
{----------------------------------------------------------------------------}
{- -}
{- TransferFunction scales either the x- or y-axis by a constant. The -}
{- first character read will decide upon which axis to act, and the -}
{- next character read will decide the operation to be performed. Only -}
{- the characters '*', '/', '+', and '-' are accepted for operations. -}
{- -}
{----------------------------------------------------------------------------}
PROCEDURE TransferFunction;
VAR
i : INTEGER; (* counter variable *)
s : string;
transfer : REAL; (* scaling factor *)
operation : char; (* operation to be performed *)
X_AXIS : BOOLEAN; (* apply to x or y axis? *)
BEGIN {TransferFunction}
WriteXY ('Apply transfer function to x or y axis? ',StartColumn,22);
REPEAT
operation:=ReadKey;
UNTIL (UpCase(operation) in ['X','Y']);
IF UpCase(operation) = 'X'
THEN X_AXIS:=true
ELSE X_AXIS:=false;
WriteXY ('Factor: ',StartColumn,24); ClrEOL;
REPEAT
operation:=ReadKey;
UNTIL (operation in ['*','/','+','-']);
Write (operation);
ReadLn (s);
String_To_Value (s,transfer,s);
IF X_AXIS
THEN CASE operation OF
'*': FOR i:=0 TO NumPoints-1 DO time^[i]:=time^[i]*transfer;
'/': FOR i:=0 TO NumPoints-1 DO time^[i]:=time^[i]/transfer;
'+': FOR i:=0 TO NumPoints-1 DO time^[i]:=time^[i]+transfer;
'-': FOR i:=0 TO NumPoints-1 DO time^[i]:=time^[i]-transfer;
END {CASE}
ELSE CASE operation OF
'*': FOR i:=0 TO NumPoints-1 DO ampl^[i]:=ampl^[i]*transfer;
'/': FOR i:=0 TO NumPoints-1 DO ampl^[i]:=ampl^[i]/transfer;
'+': FOR i:=0 TO NumPoints-1 DO ampl^[i]:=ampl^[i]+transfer;
'-': FOR i:=0 TO NumPoints-1 DO ampl^[i]:=ampl^[i]-transfer;
END; {CASE}
END; {TransferFunction}
{----------------------------------------------------------------------------}
{- -}
{- RemoveMean calculates the mean of the time domain data and -}
{- subtracts that value from the entire array. -}
{- -}
{----------------------------------------------------------------------------}
PROCEDURE RemoveMean;
VAR
i : INTEGER; (* Counter variable. *)
sum : REAL; (* The mean of the array. *)
BEGIN {RemoveMean}
sum:=0;
FOR i:=0 TO NumPoints-1 DO
sum:=sum+ampl^[i];
sum:=sum/(NumPoints);
FOR i:=0 TO NumPoints-1 DO
ampl^[i]:=ampl^[i]-sum;
END; {RemoveMean}
{----------------------------------------------------------------------------}
PROCEDURE SPS;
VAR
Choice : char;
PROCEDURE SPSMenu;
BEGIN {SPSMenu}
ClrScr;
WriteXY ('Signal Processing Menu',StartColumn+5,3);
WriteXY ('Select Option by typing a number: ',StartColumn,5);
WriteXY ('1. Integrate ',StartColumn+8,8);
WriteXY ('2. Differentiate ',StartColumn+8,10);
WriteXY ('3. FFT ',StartColumn+8,12);
WriteXY ('4. Inverse FFT ',StartColumn+8,14);
WriteXY ('5. Transfer Function ',StartColumn+8,16);
WriteXY ('6. Remove DC Level ',StartColumn+8,18);
WriteXY ('9. Exit to Main Menu ',StartColumn+8,20);
WriteXY ('Your Choice? ',StartColumn,24);
REPEAT
Choice:=ReadKey;
UNTIL Choice IN ['1'..'6','9'];
Write (Choice);
END; {SPSMenu}
BEGIN {SPS}
IF NOT ACCEPT THEN BEGIN
GotoXY (StartColumn,23);
Write ('Interpolation in progress. Please wait ... ');
Fitting;
END; {IF}
REPEAT
SPSMenu;
CASE Choice OF
'1': Integrate;
'2': Differentiate;
'3': BEGIN {Transform}
Transform (Four,Fourward);
TRANS:=TRUE;
ORIG:=FALSE;
END; {Fourier Transform}
'4': IF TRANS THEN BEGIN
Transform (Four,Inverse);
ORIG:=TRUE;
END; {Inverse Transform}
'5': TransferFunction;
'6': RemoveMean;
'9': BEGIN
ClrScr;
Exit;
END;
END; {CASE}
UNTIL FALSE;
END; {SPS}
(****************************************************************************)
BEGIN {Initialization}
END. {UNIT SignalProcessing}