<> <> <> <> DIRECTORY Basics, Complex, FFT, IO, Random, RealFns, Rope; FFTImpl: CEDAR PROGRAM IMPORTS Basics, Complex, IO, Random, RealFns EXPORTS FFT = { OPEN FFT; pi: REAL = 3.14159276; radiansPerDeg: REAL _ pi/180.; TimeToFreq: PUBLIC PROC [ v: CVecRef ] = { p: NAT _ 1; exp: NAT _ 2; -- 2**p WHILE exp> FOR i: NAT IN [0..v.size) DO j: NAT = BitRev[i, p]; IF i> FOR dist: NAT _ 1, 2*dist WHILE dist> w: Complex.VEC = Complex.FromPolar[r: 1.0, radians: pi/dist]; u: Complex.VEC _ [x: 1.0, y: 0.0]; FOR j: NAT IN [0..dist) DO t: Complex.VEC; FOR i: NAT _ j, i+2*dist WHILE i> OPEN Basics; masks: ARRAY [0..4) OF WORD = [5555h, 3333h, 0f0fh, 00ffh]; shift: [1..16] _ 1; c: WORD _ i; FOR i: [0..4) IN [0..4) DO c _ BITOR[BITSHIFT[BITAND[c,masks[i]], shift], BITAND[BITSHIFT[c,-shift],masks[i]]]; shift _ shift+shift; ENDLOOP; RETURN[BITSHIFT[c,width-16]]; }; NewCVec: PUBLIC PROC [ size: NAT _ 32, totalTime: Seconds _ 1.0, like: CVecRef _ NIL ] RETURNS [ v: CVecRef ] = { IF like#NIL THEN {size _ like.size; totalTime _ like.totalTime}; v _ NEW[CVec[size]]; totalTime _ totalTime; FOR i: NAT IN [0..v.size) DO v[i] _ [x: 0, y: 0] ENDLOOP; }; CopyCVec: PUBLIC PROC [ from: CVecRef ] RETURNS [ v: CVecRef ] = { v _ NEW[CVec[from.size]]; v.totalTime _ from.totalTime; FOR i: NAT IN [0..v.size) DO v[i] _ from[i] ENDLOOP; }; AddCosWave: PUBLIC PROC [v: CVecRef, freq: Hz, magnitude: Volts _ 1.0, phase: Degrees _ 0.0 ] = { FOR i: NAT IN [0..v.size) DO v[i].x _ v[i].x+magnitude*RealFns.CosDeg[360.0*i*freq*v.totalTime/v.size+phase]; ENDLOOP; }; AddNoise: PUBLIC PROC [v: CVecRef, powerPerHz: DBM _ 1.0, ohms: REAL _ 50.0 ] = { noise: CVecRef = NewCVec[like: v]; bwPerStep: Hz = noise.size/noise.totalTime; voltagePerStep: Volts = RealFns.SqRt[ohms*bwPerStep*DBMToWatts[powerPerHz]]; FOR i: NAT IN [0..noise.size) DO noise[i] _ Complex.FromPolar[ r: voltagePerStep, radians: radiansPerDeg*Random.ChooseInt[rs, 0, 359]]; ENDLOOP; FreqToTime[noise]; FOR i: NAT IN [0..v.size) DO v[i].x _ v[i].x+noise[i].x; ENDLOOP; }; DBMToWatts: PUBLIC PROC [ dbm: DBM ] RETURNS [ watts: Watts ] = { RETURN[RealFns.Power[base: 10.0, exponent: (dbm-30)/10.0]]; }; WattsToDBM: PUBLIC PROC [ watts: Watts ] RETURNS [ dbm: DBM ] = { RETURN[10.0*RealFns.Log[base: 10.0, arg: watts]+30.0]; }; Print: PUBLIC PROC [ v: CVecRef ] RETURNS [ Rope.ROPE ] = { s: IO.STREAM = IO.ROS[]; FOR i: NAT IN [0..v.size) DO IF i>0 THEN s.PutRope[", "]; s.PutF[format: "%d: %g+j%g", v1: IO.int[i], v2: IO.real[v[i].x], v3: IO.real[v[i].y]]; ENDLOOP; RETURN[IO.RopeFromROS[s]]; }; rs: Random.RandomStream _ Random.Create[]; }.