home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume05 / fft2 < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  43.8 KB

  1. From decwrl!purdue!mailrus!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery Sat Dec 17 21:43:57 PST 1988
  2. Article 756 of comp.sources.misc:
  3. Path: granite!decwrl!purdue!mailrus!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
  4. From: sampson@killer.DALLAS.TX.US (Steve Sampson)
  5. Newsgroups: comp.sources.misc
  6. Subject: v05i080: Unix and Turbo-C General Purpose FFT
  7. Message-ID: <6370@killer.DALLAS.TX.US>
  8. Date: 14 Dec 88 02:53:36 GMT
  9. Sender: allbery@ncoast.UUCP
  10. Reply-To: sampson@killer.DALLAS.TX.US (Steve Sampson)
  11. Organization: The Unix(R) Connection, Dallas, Texas
  12. Lines: 1824
  13. Approved: allbery@ncoast.UUCP
  14.  
  15. Posting-number: Volume 5, Issue 80
  16. Submitted-by: "Steve Sampson" <sampson@killer.DALLAS.TX.US>
  17. Archive-name: fft2
  18.  
  19. This archive contains source for both a Unix and MS-DOS General Purpose
  20. FFT program.  I've posted earlier versions before, but consider them
  21. obsolete.  This all can be improved on I'm sure.  Have fun with it.
  22.  
  23. #! /bin/sh
  24. # Contents:  uread.doc ufft.c usine.c upulse.c read.doc makefile fft.c
  25. #   sine.c pulse.c
  26. # Wrapped by sampson@killer.DALLAS.TX on Fri Dec 09 23:04:22 1988
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f uread.doc -a "${1}" != "-c" ; then 
  29.   echo shar: Will not over-write existing file \"uread.doc\"
  30. else
  31. echo shar: Extracting \"uread.doc\" \(5220 characters\)
  32. sed "s/^X//" >uread.doc <<'END_OF_uread.doc'
  33. X5 September 1988
  34. X
  35. XFFT Program for Unix C compiler
  36. XSteve Sampson, Box 45668, Tinker AFB, OK 73145
  37. Xsampson@killer    (TAC Trained)
  38. X
  39. X
  40. X   This Unix version of the FFT program uses a general purpose display routine,
  41. Xand the number of samples is based on the amount of memory.  This version can
  42. Xalso be used in MS-DOS (if you change the file modes to "rb" and "wb").
  43. X
  44. XThe original Byte Magazine program (see references below) was designed for real
  45. Xdata only.  In my experiments I needed to preserve both real and imaginary
  46. Xdata.  If you feed the FFT real data only, then the output will be a mirror
  47. Ximage, and you can ignore the left side.  Two signal generators are included.
  48. XOne generates sine waves (sine) and the other generates pulses (pulse).  Some
  49. Xpapers I found on the subject of FFTs are included at the end.  There are
  50. Xseveral books devoted to the subject also.
  51. X
  52. XFor the Unix example try:
  53. X
  54. X    sine 16 in
  55. X    1000
  56. X    3000
  57. X
  58. XWhich will sample the 1 Khz data every 333 microseconds (1 / 3 Khz).  Note: The
  59. Xsample frequency should be greater than 2 times the input frequency (Nyquist
  60. Xand all that...).
  61. X
  62. XThen run fft:
  63. X
  64. X    fft 16 in out
  65. X
  66. XAnd you should see a display like so:
  67. X
  68. X0    |=======                      (-1500.0 Hz)
  69. X1    |=====                          (-1312.5 Hz)
  70. X2    |====                          (-1125.0 Hz)
  71. X3    |====                           (-937.0 Hz)
  72. X4    |===                           (-750.0 Hz)
  73. X5    |===                           (-562.5 Hz)
  74. X6    |===                           (-375.0 Hz)
  75. X7    |===                           (-187.5 Hz)
  76. X8    |====        <-------   DC            (000.0 Hz)
  77. X9    |====        <-------   Fundamental        (187.5 Hz)
  78. X10    |======        <-------   Second Harmonic    (375.0 Hz)
  79. X11    |========                    (562.5 Hz)
  80. X12    |==============                    (750.0 Hz)
  81. X13    |========================================================
  82. X14    |============================            (1125.0 Hz)    ^
  83. X15    |===========                    (1312.5 Hz)    |
  84. X                                |
  85. X                [13 - 8 (center)] * 187.5 = 937.0 Hz
  86. X
  87. XThe fundamental display frequency is:
  88. X
  89. X    T  = Time Increment Between Samples
  90. X    N  = Number Of Samples
  91. X    Tp = N * T
  92. X
  93. X    Then F = 1 / Tp
  94. X
  95. X    In the example above, the time increment between samples is
  96. X    1 / 3000 or 333 microseconds.  N = 16, so Tp = 5333 microseconds
  97. X    and 1 / .005333 is 187.5 Hz.
  98. X
  99. X    Therefore each filter is a multiple of 187.5 Hertz.  Filter 8 in this
  100. X    example is center, so that would be zero, 9 would be one, etc.
  101. X
  102. XIn this case the sample interval didn't work so good for the frequency and
  103. Xshows the limitation of the Discrete Fourier Transform in representing a
  104. Xcontinuous signal.  A better sample rate for 1000 Hz would be 4000 Hz,
  105. Xin which case T = 250 ms, Tp = 4 ms, and F = 250 Hz.  1000 / 250 = 4.  The
  106. Xpower should all be in filter 12 (8 + 4) in this example.
  107. X
  108. XLet's run it and see:
  109. X
  110. X    sine 16 in
  111. X    1000
  112. X    4000
  113. X
  114. X    fft 16 in out
  115. X
  116. X0    |
  117. X1    |
  118. X2    |
  119. X3    |
  120. X4    |
  121. X5    |
  122. X6    |
  123. X7    |
  124. X8    |
  125. X9    |
  126. X10    |
  127. X11    |
  128. X12    |========================================================
  129. X13    |
  130. X14    |
  131. X15    |
  132. X
  133. XWell what do you know...
  134. X
  135. XThe output data file can be used by other programs as needed.
  136. X
  137. XBy using negative frequencies in 'sine' you can generate opening targets:
  138. X
  139. X    sine 16 in
  140. X    -1000
  141. X    3000
  142. X
  143. X    fft 16 in out
  144. X
  145. XProduces:
  146. X
  147. X0    |=======
  148. X1    |===========
  149. X2    |============================
  150. X3    |=======================================================
  151. X4    |==============
  152. X5    |========
  153. X6    |======
  154. X7    |====
  155. X8    |====        <-------- Zero Hertz (DC)
  156. X9    |===
  157. X10    |===
  158. X11    |===
  159. X12    |===
  160. X13    |====
  161. X14    |====
  162. X15    |=====
  163. X
  164. XYou can see in these examples where weighting functions would be nice.
  165. X
  166. XFor an example of what happens when the imaginary data is not input
  167. X(ie, zeros put in) for a 1000 Hz frequency at 3000 Hz sample rate:
  168. X
  169. X0    |===============
  170. X1    |==================
  171. X2    |===================================
  172. X3    |========================================================
  173. X4    |===========
  174. X5    |====
  175. X6    |==
  176. X7    |=                Delete this part
  177. X---------------------------------------------------------------------
  178. X8    |
  179. X9    |=
  180. X10    |==
  181. X11    |====
  182. X12    |===========
  183. X13    |=======================================================
  184. X14    |===================================
  185. X15    |==================
  186. X
  187. XThe left side is redundant and can be deleted.  This is what the original
  188. XByte Magazine article did.
  189. X
  190. XFor generating pulses, a second program 'pulse' is provided.  It pre-loads
  191. Ximaginary data with zeros.   For example:
  192. X
  193. X    pulse 16 in
  194. X    .000006
  195. X    .0000008
  196. X
  197. XIs a radar with a 6 microsecond pulse and 800 nanosecond range gates.
  198. X
  199. X    fft 16 in out
  200. X
  201. XWill produce:
  202. X
  203. X0    |
  204. X1    |=======
  205. X2    |
  206. X3    |========
  207. X4    |
  208. X5    |============
  209. X6    |
  210. X7    |===================================
  211. X8    |========================================================
  212. X9    |===================================
  213. X10    |
  214. X11    |============
  215. X12    |
  216. X13    |========
  217. X14    |
  218. X15    |=======
  219. X
  220. XThe more filters you use, the prettier it looks.
  221. X
  222. X
  223. XFFT References
  224. X--------------
  225. X
  226. X1.    Fast Fourier Transforms On Your Home Computer, William D. Stanley,
  227. X    Steven J. Peterson, BYTE Magazine, December 1978.  Basic idea comes
  228. X    from this program.
  229. X
  230. X2.    8052 Microcomputer simplifies FFT Design, Arnold Rosenberg,
  231. X    Electronics, May 5, 1983.  Used a bit reverse table idea based on the
  232. X    routine in this program.
  233. X
  234. X3.    A Fast Fourier Transform for the 8080, Robert D. Fusfeld,
  235. X    Dr. Dobbs, Number 44.  Gave me some ideas.
  236. X
  237. X4.    A Guided Tour of the Fast Fourier Transform, G. D. Bergland,
  238. X    IEEE Spectrum, July 1969.  Math!
  239. X
  240. X5.    FFT - Shortcut to Fourier Analysis, Richard Klahn, Richard R. Shively,
  241. X    Electronics, April 15 1968. Math!
  242. X
  243. X/* EOF */
  244. END_OF_uread.doc
  245. if test 5220 -ne `wc -c <uread.doc`; then
  246.     echo shar: \"uread.doc\" unpacked with wrong size!
  247. fi
  248. # end of overwriting check
  249. fi
  250. if test -f ufft.c -a "${1}" != "-c" ; then 
  251.   echo shar: Will not over-write existing file \"ufft.c\"
  252. else
  253. echo shar: Extracting \"ufft.c\" \(5897 characters\)
  254. sed "s/^X//" >ufft.c <<'END_OF_ufft.c'
  255. X/*
  256. X *    fft.c
  257. X *
  258. X *    Unix Version 2.4 by Steve Sampson, Public Domain, September 1988
  259. X *
  260. X *    This program produces a Frequency Domain display from the Time Domain
  261. X *    data input; using the Fast Fourier Transform.
  262. X *
  263. X *    The Real data is generated by the in-phase (I) channel, and the
  264. X *    Imaginary data is produced by the quadrature-phase (Q) channel of
  265. X *    a Doppler Radar receiver.  The middle filter is zero Hz.  Closing
  266. X *    targets are displayed to the right, and Opening targets to the left.
  267. X *
  268. X *    Note: With Imaginary data set to zero the output is a mirror image.
  269. X *
  270. X *    Usage:    fft samples input output
  271. X *        1. samples is a variable power of two.
  272. X *        2. Input is (samples * sizeof(double)) characters.
  273. X *        3. Output is (samples * sizeof(double)) characters.
  274. X *        4. Standard error is help or debugging messages.
  275. X *
  276. X *    See also: readme.doc, pulse.c, and sine.c.
  277. X */
  278. X
  279. X/* Includes */
  280. X
  281. X#include <stdio.h>
  282. X#include <malloc.h>
  283. X#include <math.h>
  284. X
  285. X/* Defines */
  286. X
  287. X#define    TWO_PI    (2.0 * 3.14159265358979324)    /* alias 360 deg */
  288. X#define    Chunk    (Samples * sizeof(double))
  289. X
  290. X#define    sine(x)        Sine[(x)]
  291. X#define    cosine(x)    Sine[((x) + (Samples >> 2)) % Samples]
  292. X
  293. X/* Globals, Forward declarations */
  294. X
  295. Xstatic int    Samples, Power;
  296. Xstatic double    *Real, *Imag, Maxn, magnitude();
  297. Xstatic void    scale(), fft(), max_amp(), display(), err_report();
  298. X
  299. Xstatic int    permute();
  300. Xstatic double    *Sine;
  301. Xstatic void    build_trig();
  302. X
  303. Xstatic FILE    *Fpi, *Fpo;
  304. X
  305. X
  306. X/* The program */
  307. X
  308. Xmain(argc, argv)
  309. Xint    argc;
  310. Xchar    **argv;
  311. X{
  312. X    if (argc != 4)
  313. X        err_report(0);
  314. X
  315. X    Samples = abs(atoi(*++argv));
  316. X    Power = log10((double)Samples) / log10(2.0);
  317. X
  318. X    /* Allocate memory for the variable arrays */
  319. X
  320. X    if ((Real = (double *)malloc(Chunk)) == NULL)
  321. X        err_report(1);
  322. X
  323. X    if ((Imag = (double *)malloc(Chunk)) == NULL)
  324. X        err_report(2);
  325. X
  326. X    if ((Sine = (double *)malloc(Chunk)) == NULL)
  327. X        err_report(3);
  328. X
  329. X    /* open the data files */
  330. X
  331. X    if ((Fpi = fopen(*++argv, "r")) == NULL)
  332. X        err_report(4);
  333. X
  334. X    if ((Fpo = fopen(*++argv, "w")) == NULL)
  335. X        err_report(5);
  336. X
  337. X    /* read in the data from the input file */
  338. X
  339. X    fread(Real, sizeof(double), Samples, Fpi);
  340. X    fread(Imag, sizeof(double), Samples, Fpi);
  341. X    fclose(Fpi);
  342. X
  343. X    build_trig();
  344. X    scale();
  345. X    fft();
  346. X    display();
  347. X
  348. X    /* write the frequency domain data to the standard output */
  349. X
  350. X    fwrite(Real, sizeof(double), Samples, Fpo);
  351. X    fwrite(Imag, sizeof(double), Samples, Fpo);
  352. X    fclose(Fpo);
  353. X
  354. X    /* free up memory and let's get back to our favorite shell */
  355. X
  356. X    free((char *)Real);
  357. X    free((char *)Imag);
  358. X    free((char *)Sine);
  359. X
  360. X    exit(0);
  361. X}
  362. X
  363. X
  364. Xstatic void err_report(n)
  365. Xint    n;
  366. X{
  367. X    switch (n)  {
  368. X    case 0:
  369. X        fprintf(stderr, "Usage: fft samples in_file out_file\n");
  370. X        fprintf(stderr, "Where samples is a power of two\n");
  371. X        break;
  372. X    case 1:
  373. X        fprintf(stderr, "fft: Out of memory getting real space\n");
  374. X        break;
  375. X    case 2:
  376. X        fprintf(stderr, "fft: Out of memory getting imag space\n");
  377. X        free((char *)Real);
  378. X        break;
  379. X    case 3:
  380. X        fprintf(stderr, "fft: Out of memory getting sine space\n");
  381. X        free((char *)Real);
  382. X        free((char *)Imag);
  383. X        break;
  384. X    case 4:
  385. X        fprintf(stderr,"fft: Unable to open data input file\n");
  386. X        free((char *)Real);
  387. X        free((char *)Imag);
  388. X        free((char *)Sine);
  389. X        break;
  390. X    case 5:
  391. X        fprintf(stderr,"fft: Unable to open data output file\n");
  392. X        fclose(Fpi);
  393. X        free((char *)Real);
  394. X        free((char *)Imag);
  395. X        free((char *)Sine);
  396. X        break;
  397. X    }
  398. X
  399. X    exit(1);
  400. X}
  401. X
  402. X
  403. Xstatic void scale()
  404. X{
  405. X    register int    loop;
  406. X
  407. X    for (loop = 0; loop < Samples; loop++)  {
  408. X        Real[loop] /= Samples;
  409. X        Imag[loop] /= Samples;
  410. X    }
  411. X}
  412. X
  413. X
  414. Xstatic void fft()
  415. X{
  416. X    register int    loop, loop1, loop2;
  417. X    unsigned    i1;            /* going to right shift this */
  418. X    int        i2, i3, i4, y;
  419. X    double        a1, a2, b1, b2, z1, z2;
  420. X
  421. X    i1 = Samples >> 1;
  422. X    i2 = 1;
  423. X
  424. X    /* perform the butterfly's */
  425. X
  426. X    for (loop = 0; loop < Power; loop++)  {
  427. X        i3 = 0;
  428. X        i4 = i1;
  429. X
  430. X        for (loop1 = 0; loop1 < i2; loop1++)  {
  431. X            y = permute(i3 / (int)i1);
  432. X            z1 =  cosine(y);
  433. X            z2 = -sine(y);
  434. X
  435. X            for (loop2 = i3; loop2 < i4; loop2++)  {
  436. X
  437. X                a1 = Real[loop2];
  438. X                a2 = Imag[loop2];
  439. X
  440. X                b1  = z1*Real[loop2+i1] - z2*Imag[loop2+i1];
  441. X                b2  = z2*Real[loop2+i1] + z1*Imag[loop2+i1];
  442. X
  443. X                Real[loop2] = a1 + b1;
  444. X                Imag[loop2] = a2 + b2;
  445. X
  446. X                Real[loop2+i1] = a1 - b1;
  447. X                Imag[loop2+i1] = a2 - b2;
  448. X            }
  449. X
  450. X            i3 += (i1 << 1);
  451. X            i4 += (i1 << 1);
  452. X        }
  453. X
  454. X        i1 >>= 1;
  455. X        i2 <<= 1;
  456. X    }
  457. X}
  458. X
  459. X/*
  460. X *    Display the frequency domain.
  461. X *
  462. X *    The filters are aranged so that DC is in the middle filter.
  463. X *    Thus -Doppler is on the left, +Doppler on the right.
  464. X */
  465. X
  466. Xstatic void display()
  467. X{
  468. X    register int    loop, offset;
  469. X    int        n, x;
  470. X
  471. X    max_amp();
  472. X    n = Samples >> 1;
  473. X
  474. X    for (loop = n; loop < Samples; loop++)  {
  475. X        x = (int)(magnitude(loop) * 59.0 / Maxn);
  476. X        printf("%d\t|", loop - n);
  477. X        offset = 0;
  478. X        while (++offset <= x)
  479. X            putchar('=');
  480. X
  481. X        putchar('\n');
  482. X    }
  483. X
  484. X    for (loop = 0; loop < n; loop++)  {
  485. X        x = (int)(magnitude(loop) * 59.0 / Maxn);
  486. X        printf("%d\t|", loop + n);
  487. X        offset = 0;
  488. X        while (++offset <= x)
  489. X            putchar('=');
  490. X
  491. X        putchar('\n');
  492. X    }
  493. X}
  494. X
  495. X/*
  496. X *    Find maximum amplitude
  497. X */
  498. X
  499. Xstatic void max_amp()
  500. X{
  501. X    register int    loop;
  502. X    double        mag;
  503. X
  504. X    Maxn = 0.0;
  505. X    for (loop = 0; loop < Samples; loop++)  {
  506. X        if ((mag = magnitude(loop)) > Maxn)
  507. X            Maxn = mag;
  508. X    }
  509. X}
  510. X
  511. X/*
  512. X *    Calculate Power Magnitude
  513. X */
  514. X
  515. Xstatic double magnitude(n)
  516. Xint    n;
  517. X{
  518. X    n = permute(n);
  519. X    return hypot(Real[n], Imag[n]);
  520. X}
  521. X
  522. X/*
  523. X *    Bit reverse the number
  524. X *
  525. X *    Change 11100000b to 00000111b or vice-versa
  526. X */
  527. X
  528. Xstatic int permute(index)
  529. Xint    index;
  530. X{
  531. X    register int    loop;
  532. X    unsigned    n1;
  533. X    int        result;
  534. X
  535. X    n1 = Samples;
  536. X    result = 0;
  537. X
  538. X    for (loop = 0; loop < Power; loop++)  {
  539. X        n1 >>= 1;
  540. X        if (index < n1)
  541. X            continue;
  542. X
  543. X        /* Unix has a truncation problem with pow() */
  544. X
  545. X        result += (int)(pow(2.0, (double)loop) + .05);
  546. X        index -= n1;
  547. X    }
  548. X
  549. X    return result;
  550. X}
  551. X
  552. X/*
  553. X *    Pre-compute the sine and cosine tables
  554. X */
  555. X
  556. Xstatic void build_trig()
  557. X{
  558. X    register int    loop;
  559. X    double        angle, increment;
  560. X
  561. X    angle = 0.0;
  562. X    increment = TWO_PI / (double)Samples;
  563. X
  564. X    for (loop = 0; loop < Samples; loop++)  {
  565. X        Sine[loop] = sin(angle);
  566. X        angle += increment;
  567. X    }
  568. X}
  569. X
  570. X/* EOF */
  571. END_OF_ufft.c
  572. if test 5897 -ne `wc -c <ufft.c`; then
  573.     echo shar: \"ufft.c\" unpacked with wrong size!
  574. fi
  575. # end of overwriting check
  576. fi
  577. if test -f usine.c -a "${1}" != "-c" ; then 
  578.   echo shar: Will not over-write existing file \"usine.c\"
  579. else
  580. echo shar: Extracting \"usine.c\" \(1763 characters\)
  581. sed "s/^X//" >usine.c <<'END_OF_usine.c'
  582. X/*
  583. X *    sine.c
  584. X *
  585. X *    Unix Version 2.4 by Steve Sampson, Public Domain, September 1988
  586. X *
  587. X *    This program is used to generate time domain sinewave data
  588. X *    for fft.c.  If you want an opening target - negate the
  589. X *    test frequency.
  590. X */
  591. X
  592. X#include <stdio.h>
  593. X#include <malloc.h>
  594. X#include <math.h>
  595. X
  596. X#define    TWO_PI    (2.0 * 3.14159265358979324)
  597. X#define Chunk    (Samples * sizeof(double))
  598. X
  599. Xstatic double    Sample, Freq, Time, *Real, *Imag;
  600. Xstatic int    Samples;
  601. Xstatic void    err_report();
  602. Xstatic FILE    *Fp;
  603. X
  604. X
  605. Xmain(argc, argv)
  606. Xint    argc;
  607. Xchar    **argv;
  608. X{
  609. X    register int    loop;
  610. X
  611. X    if (argc != 3)
  612. X        err_report(0);
  613. X
  614. X    Samples = abs(atoi(*++argv));
  615. X
  616. X    if ((Real = (double *)malloc(Chunk)) == NULL)
  617. X        err_report(1);
  618. X
  619. X    if ((Imag = (double *)malloc(Chunk)) == NULL)
  620. X        err_report(2);
  621. X
  622. X    printf("Input The Test Frequency (Hz) ? ");
  623. X    scanf("%lf", &Freq);
  624. X    printf("Input The Sampling Frequency (Hz) ? ");
  625. X    scanf("%lf", &Sample);
  626. X    Sample = 1.0 / Sample;
  627. X
  628. X    Time = 0.0;
  629. X    for (loop = 0; loop < Samples; loop++)  {
  630. X        Real[loop] =  sin(TWO_PI * Freq * Time);
  631. X        Imag[loop] = -cos(TWO_PI * Freq * Time);
  632. X        Time += Sample;
  633. X    }
  634. X
  635. X    if ((Fp = fopen(*++argv, "w")) == NULL)
  636. X        err_report(3);
  637. X
  638. X    fwrite(Real, sizeof(double), Samples, Fp);
  639. X    fwrite(Imag, sizeof(double), Samples, Fp);
  640. X    fclose(Fp);
  641. X
  642. X    putchar('\n');
  643. X
  644. X    free((char *)Real);
  645. X    free((char *)Imag);
  646. X
  647. X    exit(0);
  648. X}
  649. X
  650. X
  651. Xstatic void err_report(n)
  652. Xint    n;
  653. X{
  654. X    switch (n)  {
  655. X    case 0:
  656. X        fprintf(stderr,"Usage: sine samples output_file\n");
  657. X        fprintf(stderr,"Where samples is a power of two\n");
  658. X        break;
  659. X    case 1:
  660. X        fprintf(stderr,"sine: Out of memory getting real space\n");
  661. X        break;
  662. X    case 2:
  663. X        fprintf(stderr,"sine: Out of memory getting imag space\n");
  664. X        free((char *)Real);
  665. X        break;
  666. X    case 3:
  667. X        fprintf(stderr,"sine: Unable to create write file\n");
  668. X    }
  669. X
  670. X    exit(1);
  671. X}
  672. X
  673. X/* EOF */
  674. END_OF_usine.c
  675. if test 1763 -ne `wc -c <usine.c`; then
  676.     echo shar: \"usine.c\" unpacked with wrong size!
  677. fi
  678. # end of overwriting check
  679. fi
  680. if test -f upulse.c -a "${1}" != "-c" ; then 
  681.   echo shar: Will not over-write existing file \"upulse.c\"
  682. else
  683. echo shar: Extracting \"upulse.c\" \(1613 characters\)
  684. sed "s/^X//" >upulse.c <<'END_OF_upulse.c'
  685. X/*
  686. X *    pulse.c
  687. X *
  688. X *    Unix Version 2.4 by Steve Sampson, Public Domain, September 1988
  689. X *
  690. X *    This program is used to generate time domain pulse data    for fft.c.
  691. X */
  692. X
  693. X#include <stdio.h>
  694. X#include <malloc.h>
  695. X
  696. X#define    Chunk    (Samples * sizeof(double))
  697. X
  698. Xstatic double    Sample, Pw, Time, *Real, *Imag;
  699. Xstatic int    Samples;
  700. Xstatic void    err_report();
  701. Xstatic FILE    *Fp;
  702. X
  703. X
  704. Xmain(argc, argv)
  705. Xint    argc;
  706. Xchar    **argv;
  707. X{
  708. X    register int    loop;
  709. X
  710. X    if (argc != 3)
  711. X        err_report(0);
  712. X
  713. X    Samples = abs(atoi(*++argv));
  714. X
  715. X    if ((Real = (double *)malloc(Chunk)) == NULL)
  716. X        err_report(1);
  717. X
  718. X    if ((Imag = (double *)malloc(Chunk)) == NULL)
  719. X        err_report(2);
  720. X
  721. X    printf("Input The Pulse Width (Seconds) ? ");
  722. X    scanf("%lf", &Pw);
  723. X    printf("Input The Sampling Time (Seconds) ? ");
  724. X    scanf("%lf", &Sample);
  725. X
  726. X    Time = 0.0;
  727. X    for (loop = 0; loop < Samples; loop++)  {
  728. X        if (Time < Pw)
  729. X            Real[loop] = 1.0;
  730. X        else
  731. X            Real[loop] = 0.0;
  732. X
  733. X        Imag[loop] = 0.0;
  734. X        Time += Sample;
  735. X    }
  736. X
  737. X    if ((Fp = fopen(*++argv, "w")) == NULL)
  738. X        err_report(3);
  739. X
  740. X    fwrite(Real, sizeof(double), Samples, Fp);
  741. X    fwrite(Imag, sizeof(double), Samples, Fp);
  742. X    fclose(Fp);
  743. X
  744. X    putchar('\n');
  745. X
  746. X    free((char *)Real);
  747. X    free((char *)Imag);
  748. X
  749. X    exit(0);
  750. X}
  751. X
  752. X
  753. Xstatic void err_report(n)
  754. Xint    n;
  755. X{
  756. X    switch (n)  {
  757. X    case 0:
  758. X        fprintf(stderr,"Usage: pulse samples output_file\n");
  759. X        fprintf(stderr,"Where samples is a power of two\n");
  760. X        break;
  761. X    case 1:
  762. X        fprintf(stderr,"pulse: Out of memory getting real space\n");
  763. X        break;
  764. X    case 2:
  765. X        fprintf(stderr,"pulse: Out of memory getting imag space\n");
  766. X        free((char *)Real);
  767. X        break;
  768. X    case 3:
  769. X        fprintf(stderr,"pulse: Unable to create write file\n");
  770. X    }
  771. X
  772. X    exit(1);
  773. X}
  774. X
  775. X/* EOF */
  776. END_OF_upulse.c
  777. if test 1613 -ne `wc -c <upulse.c`; then
  778.     echo shar: \"upulse.c\" unpacked with wrong size!
  779. fi
  780. # end of overwriting check
  781. fi
  782. if test -f read.doc -a "${1}" != "-c" ; then 
  783.   echo shar: Will not over-write existing file \"read.doc\"
  784. else
  785. echo shar: Extracting \"read.doc\" \(5665 characters\)
  786. sed "s/^X//" >read.doc <<'END_OF_read.doc'
  787. X
  788. X
  789. X                 FFT Program for Turbo-C
  790. X
  791. X                       By
  792. X
  793. X                     Steve Sampson
  794. X
  795. X
  796. X               Version 2.6, November 1988
  797. X
  798. X
  799. X   The FFT program and test signal generators included in the archive, can be
  800. Xused to perform signal analysis in the frequency domain, using samples in the
  801. Xtime domain.  Historically the applications have ranged from music to radar.
  802. XI recently have been doing some research in the radar field using this FFT to
  803. Xperform relative velocity measurements.  This program can be further refined
  804. Xto meet your needs.
  805. X
  806. X   I initially uploaded a fairly basic program, and through feedback have
  807. Xmade some improvements.  It's pretty complete now as far as a start for making
  808. Xyour own specific version.  Earlier Unix compatability has been removed in
  809. Xfavor of IBM graphics adaptors.
  810. X
  811. X   This program uses graphics to present a 256 filter window.  My current
  812. Xapplication required complex data and resulted in 256 complex points.  You may
  813. Xuse this with real data which results in 128 significant points.  If you feed
  814. Xthe FFT real data only (Imaginary data set to zero), then the output will be a
  815. Xmirror image, and you can ignore the left side.
  816. X
  817. XSome papers I found on the subject of FFTs are included at the end.  There are
  818. Xseveral books devoted to the subject also.
  819. X
  820. XFor an example try:
  821. X
  822. X    sine in
  823. X    1000
  824. X    3000
  825. X
  826. XWhich will sample the 1 Khz data every 333 microseconds (1 / 3 Khz).  Note: The
  827. Xsample frequency should be greater than 2 times the input frequency (Nyquist
  828. Xand all that...).
  829. X
  830. XThen run fft like so:
  831. X
  832. X    fft in
  833. X
  834. XAnd you should see a graphics display which has filters 0 through 255 on the
  835. XX axis, and power on the Y axis.  All DC power in the time samples will appear
  836. Xin filter 128.  The fundamental display frequency is shown in filter 129 and
  837. Xcan be computed as follows:
  838. X
  839. X    T  = Time Increment Between Samples
  840. X    N  = Number Of Samples (256)
  841. X    Tp = N * T
  842. X
  843. X    Then F = 1 / Tp
  844. X
  845. X    In the example above, the time increment between samples is
  846. X    1 / 3000 or 333 microseconds.  N = 256, so Tp = 85 milliseconds
  847. X    and 1 / .005333 is 11.7 Hz per filter.
  848. X
  849. X    Therefore each filter is a multiple of 11.7 Hertz.
  850. X
  851. X    Filter 126            -23.4 Hz
  852. X    Filter 127            -11.7 Hz
  853. X    Filter 128    DC         00.0 Hz
  854. X    Filter 129    Fundamental     11.7 Hz
  855. X    Filter 130    Second Harmonic  23.4 Hz
  856. X
  857. XIn this case you'll find the sampling interval didn't work very well for the
  858. Xinput frequency.  The display shows the power spread out over several filters.
  859. XThis is a limitation of the Discrete Fourier Transform in representing a
  860. Xcontinuous signal.
  861. X
  862. XA better sample rate for 1000 Hz would be 4000 Hz, in which case T = 250 ms,
  863. XTp = 64 milliseconds, and F = 15.625 Hz.  1000 / 15.625 = 64.  All of the
  864. Xpower should then appear in filter 192 (128 + 64) in this example.
  865. X
  866. XRun it and see using:
  867. X
  868. X    sine in
  869. X    1000
  870. X    4000
  871. X
  872. X    fft in
  873. X
  874. XBy using negative frequencies in 'sine' you can generate opening targets:
  875. X
  876. X    sine in
  877. X    -1000
  878. X    3000
  879. X
  880. X    fft in
  881. X
  882. XYou can see in these examples where weighting functions would be useful.  For
  883. Xinstance using weighting you could greatly attenuate the sidebands.  Usually
  884. Xthe main lobe becomes a little wider however.  The current version does not
  885. Xperform any weighting.
  886. X
  887. XFor generating pulses, a second program 'pulse' is provided.  It pre-loads
  888. Ximaginary data with zeros.   For example:
  889. X
  890. X    pulse in
  891. X    .000006
  892. X    .0000008
  893. X
  894. X    fft in
  895. X
  896. XSimulates a radar with a 6 microsecond pulse and 800 nanosecond range gates,
  897. Xand produces the typical pulse spectrum display.
  898. X
  899. X
  900. XHow to run the FFT program
  901. X--------------------------
  902. X
  903. XThe program auto-detects CGA, EGA, and VGA graphics adaptors.  The CGA version
  904. Xcursor line is hard to see though.  VGA is untested.
  905. X
  906. XWhen the program is run, a ruler line is drawn with tick marks every 5 filters.
  907. XAlso "Computing FFT" is displayed at the top of the screen.  The program is now
  908. Xbusy computing the FFT and will not do anything useful until finished.
  909. X
  910. XWhen the FFT computation is complete, the power plot will be performed and a
  911. Xverticle cursor line will appear.  "Computing FFT" will be replaced with
  912. X"Filter # 128".  The program is then ready for input of commands.
  913. X
  914. XThe commands are:
  915. X
  916. X    ESC        Escapes back to MS-DOS
  917. X    LEFT        Moves the cursor left
  918. X    RIGHT        Moves the cursor right
  919. X    CTRLLEFT    Moves the cursor 10 filters left
  920. X    CTRLRIGHT    Moves the cursor 10 filters right
  921. X    HOME        Moves the cursor to filter 0
  922. X    END        Moves the cursor to filter 255
  923. X    F1        Prints the display on an Epson/IBM Compatable printer
  924. X
  925. XA bee-bop when F1 is pressed means the printer has a problem (paper, power...).
  926. X
  927. X
  928. XHow to compile the programs
  929. X---------------------------
  930. X
  931. XI use a Hard Disk configured per the Borland Manuals.  If this is your settup
  932. Xalso; do this:
  933. X
  934. X    1.  Copy the archive contents into any directory.
  935. X    2.  Run \TURBOC\MAKE
  936. X    3.  Three programs are made: fft.exe, sine.exe, and pulse.exe.
  937. X
  938. XIf you have any other system specific changes, then consult the makefile and
  939. XBorland manuals.  I can also be reached at the address below.
  940. X
  941. X
  942. XFFT References
  943. X--------------
  944. X
  945. X1.    Fast Fourier Transforms On Your Home Computer, William D. Stanley,
  946. X    Steven J. Peterson, BYTE Magazine, December 1978.  Basic idea comes
  947. X    from this program.
  948. X
  949. X2.    8052 Microcomputer simplifies FFT Design, Arnold Rosenberg,
  950. X    Electronics, May 5, 1983.  Used a bit reverse table based on the
  951. X    routine in this program.
  952. X
  953. X3.    A Fast Fourier Transform for the 8080, Robert D. Fusfeld,
  954. X    Dr. Dobbs, Number 44.  Gave me some ideas.
  955. X
  956. X4.    A Guided Tour of the Fast Fourier Transform, G. D. Bergland,
  957. X    IEEE Spectrum, July 1969.
  958. X
  959. X5.    FFT - Shortcut to Fourier Analysis, Richard Klahn, Richard R. Shively,
  960. X    Electronics, April 15 1968.
  961. X
  962. X---
  963. XAll programs are entered into the Public Domain, No rights reserved.
  964. XSteve Sampson, Box 45668, Tinker AFB, OK, 73145
  965. X75136,626
  966. END_OF_read.doc
  967. if test 5665 -ne `wc -c <read.doc`; then
  968.     echo shar: \"read.doc\" unpacked with wrong size!
  969. fi
  970. # end of overwriting check
  971. fi
  972. if test -f makefile -a "${1}" != "-c" ; then 
  973.   echo shar: Will not over-write existing file \"makefile\"
  974. else
  975. echo shar: Extracting \"makefile\" \(874 characters\)
  976. sed "s/^X//" >makefile <<'END_OF_makefile'
  977. X#
  978. X#    Makefile for FFT small model
  979. X#
  980. X#    Version 2.6, Public Domain by Steve Sampson, November 1988
  981. X#
  982. X#    See readme.doc file
  983. X#
  984. X
  985. XMOD = s
  986. XLIB = \turboc\lib
  987. XINC = \turboc\include
  988. X
  989. Xall:
  990. X    make fft
  991. X    make sine
  992. X    make pulse
  993. X    make clean
  994. X
  995. Xfft:    fft.obj
  996. X    tcc -c -f -m$(MOD) -L$(LIB) -I$(INC) fft.c
  997. X    \turboc\bgiobj \turboc\examples\cga
  998. X    \turboc\bgiobj \turboc\examples\egavga
  999. X    tlink /x /c $(LIB)\C0$(MOD) fft cga egavga, fft,, \
  1000. X    $(LIB)\emu $(LIB)\math$(MOD) $(LIB)\C$(MOD) $(LIB)\graphics
  1001. X
  1002. Xsine:    sine.obj
  1003. X    tcc -c -f -m$(MOD) -L$(LIB) -I$(INC) sine.c
  1004. X    tlink /x /c $(LIB)\C0$(MOD) sine, sine,, \
  1005. X    $(LIB)\emu $(LIB)\math$(MOD) $(LIB)\C$(MOD)
  1006. X
  1007. Xpulse:    pulse.obj
  1008. X    tcc -c -f -m$(MOD) -L$(LIB) -I$(INC) pulse.c
  1009. X    tlink /x /c $(LIB)\C0$(MOD) pulse, pulse,, \
  1010. X    $(LIB)\emu $(LIB)\math$(MOD) $(LIB)\C$(MOD)
  1011. X
  1012. Xclean:
  1013. X    del *.obj
  1014. X
  1015. X#
  1016. X#    Dependancies
  1017. X#
  1018. X
  1019. Xfft.obj: fft.c
  1020. Xsine.obj: sine.c
  1021. Xpulse.obj: pulse.c
  1022. X
  1023. X# EOF
  1024. END_OF_makefile
  1025. if test 874 -ne `wc -c <makefile`; then
  1026.     echo shar: \"makefile\" unpacked with wrong size!
  1027. fi
  1028. # end of overwriting check
  1029. fi
  1030. if test -f fft.c -a "${1}" != "-c" ; then 
  1031.   echo shar: Will not over-write existing file \"fft.c\"
  1032. else
  1033. echo shar: Extracting \"fft.c\" \(15702 characters\)
  1034. sed "s/^X//" >fft.c <<'END_OF_fft.c'
  1035. X/*
  1036. X *    fft.c
  1037. X *
  1038. X *    Version 2.6 by Steve Sampson, Public Domain, November 1988
  1039. X *
  1040. X *    This program produces a Frequency Domain display from the Time Domain
  1041. X *    data input; using the Fast Fourier Transform.
  1042. X *
  1043. X *    Runs in @ 30 seconds on a 5 MHz PC XT Clone without 8087.
  1044. X *
  1045. X *    The Real data is generated by the in-phase (I) channel, and the
  1046. X *    Imaginary data is produced by the quadrature-phase (Q) channel of
  1047. X *    a Doppler Radar receiver.  The middle filter is zero Hz.  Closing
  1048. X *    targets are displayed to the right, and Opening targets to the left.
  1049. X *
  1050. X *    Note: With Imaginary data set to zero the output is a mirror image.
  1051. X *
  1052. X *    Usage:    fft input
  1053. X *        1. samples is 256.
  1054. X *        2. Input is (samples * sizeof(double)) characters.
  1055. X *        3. Standard error is help or debugging messages.
  1056. X *
  1057. X *    Auto detects CGA, EGA, and VGA in Turbo-C graphics mode.
  1058. X *
  1059. X *    See also: readme.doc, pulse.c, and sine.c.
  1060. X */
  1061. X
  1062. X/* Includes */
  1063. X
  1064. X#include <stdio.h>
  1065. X#include <alloc.h>
  1066. X#include <math.h>
  1067. X
  1068. X#include <conio.h>
  1069. X#include <dos.h>
  1070. X#include <bios.h>
  1071. X#include <graphics.h>
  1072. X#include <string.h>
  1073. X#include <stdlib.h>
  1074. X
  1075. X/* Defines */
  1076. X
  1077. X#define    SAMPLES        256
  1078. X#define    POWER        8    /* 2 to the 8th power is 256 */
  1079. X
  1080. X#define ESC        27    /* exit program */
  1081. X#define LEFTKEY        331    /* cursor left */
  1082. X#define RIGHTKEY    333    /* cursor right */
  1083. X#define CTRLLEFTKEY    371    /* cursor 10 left */
  1084. X#define CTRLRIGHTKEY    372    /* cursor 10 right */
  1085. X#define HOMEKEY        327    /* cursor at filter 0 */
  1086. X#define ENDKEY        335    /* cursor at filter 255 */
  1087. X#define F1        315    /* print screen */
  1088. X
  1089. X#define    TOP        50
  1090. X#define    LEFT        64
  1091. X#define    RIGHT        575
  1092. X#define    MIDDLE        192
  1093. X#define    TEXTX        160
  1094. X#define    TEXTXN        304
  1095. X#define    TEXTY        25
  1096. X
  1097. X/*
  1098. X *    Fixed constants should be used in the macros for speed.
  1099. X *
  1100. X *    A cosine wave leads a sine wave by 90 degrees, so offset into
  1101. X *    the lookup table 1/4 the way into it (256 / 4 = 64).  Using
  1102. X *    modulo 256, lookups will wrap around to zero for numbers greater
  1103. X *    than 255.  (cosine(200) = Sine[264 % 256] = Sine[8]).
  1104. X */
  1105. X
  1106. X#define    permute(x)    Br_table[(x)]
  1107. X#define    sine(x)        Sine[(x)]
  1108. X#define cosine(x)    Sine[((x) + 64) % 256]
  1109. X
  1110. X/* Globals, Forward declarations */
  1111. X
  1112. Xdouble    Real[SAMPLES], Imag[SAMPLES], Maxn, magnitude();
  1113. Xint    GraphDriver = DETECT, GraphMode, Primary, Cursor, Length;
  1114. Xint    Bottom, Left, PrintChar(), PrintScreen(), getkey();
  1115. Xvoid    *Save, quit(), beep(), build_window(), commands(), bee_bop();
  1116. Xvoid    scale(), fft(), max_amp(), display();
  1117. X
  1118. X/*
  1119. X *    Bit Reverse Table for size 256
  1120. X *    Lookup saves 20 seconds in Turbo-C over the pow() function.
  1121. X *
  1122. X *    Br_table[x] = x inverted (eg. 00000001 flipped to 10000000)
  1123. X */
  1124. X
  1125. Xunsigned char Br_table[] = {
  1126. X    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
  1127. X    0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
  1128. X    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
  1129. X    0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
  1130. X    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
  1131. X    0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
  1132. X    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
  1133. X    0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
  1134. X    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
  1135. X    0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
  1136. X    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
  1137. X    0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
  1138. X    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
  1139. X    0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
  1140. X    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
  1141. X    0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
  1142. X    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
  1143. X    0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
  1144. X    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
  1145. X    0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
  1146. X    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
  1147. X    0x3f, 0xbf, 0x7f, 0xff
  1148. X};
  1149. X
  1150. X/*
  1151. X *    Sine/Cosine Table for size 256, Lookup saves 9 seconds in Turbo-C
  1152. X *
  1153. X *    Sine[n] = sin(x), x = x + (2Pi / 256)
  1154. X */
  1155. X
  1156. Xfloat    Sine[] = {
  1157. X    0.000000, 0.024541, 0.049068, 0.073565,    0.098017, 0.122411,
  1158. X    0.146730, 0.170962, 0.195090, 0.219101, 0.242980, 0.266713,
  1159. X    0.290285, 0.313682, 0.336890, 0.359895, 0.382683, 0.405241,
  1160. X    0.427555, 0.449611, 0.471397, 0.492898, 0.514103, 0.534998,
  1161. X    0.555570, 0.575808, 0.595699, 0.615232,    0.634393, 0.653173,
  1162. X    0.671559, 0.689541, 0.707107, 0.724247, 0.740951, 0.757209,
  1163. X    0.773010, 0.788346, 0.803208, 0.817585, 0.831470, 0.844854,
  1164. X    0.857729, 0.870087, 0.881921, 0.893224, 0.903989, 0.914210,
  1165. X    0.923880, 0.932993, 0.941544, 0.949528,    0.956940, 0.963776,
  1166. X    0.970031, 0.975702, 0.980785, 0.985278, 0.989177, 0.992480,
  1167. X    0.995185, 0.997290, 0.998795, 0.999699,    1.000000, 0.999699,
  1168. X    0.998795, 0.997290, 0.995185, 0.992480, 0.989177, 0.985278,
  1169. X    0.980785, 0.975702, 0.970031, 0.963776,    0.956940, 0.949528,
  1170. X    0.941544, 0.932993, 0.923880, 0.914210, 0.903989, 0.893224,
  1171. X    0.881921, 0.870087, 0.857729, 0.844854,    0.831470, 0.817585,
  1172. X    0.803208, 0.788346, 0.773010, 0.757209, 0.740951, 0.724247,
  1173. X    0.707107, 0.689541, 0.671559, 0.653173,    0.634393, 0.615232,
  1174. X    0.595699, 0.575808, 0.555570, 0.534998, 0.514103, 0.492898,
  1175. X    0.471397, 0.449611, 0.427555, 0.405241, 0.382683, 0.359895,
  1176. X    0.336890, 0.313682, 0.290285, 0.266713, 0.242980, 0.219101,
  1177. X    0.195090, 0.170962, 0.146730, 0.122411,    0.098017, 0.073565,
  1178. X    0.049068, 0.024541, 0.000000, -0.024541, -0.049068, -0.073565,
  1179. X    -0.098017, -0.122411, -0.146730, -0.170962, -0.195090, -0.219101,
  1180. X    -0.242980, -0.266713, -0.290285, -0.313682, -0.336890, -0.359895,
  1181. X    -0.382683, -0.405241, -0.427555, -0.449611, -0.471397, -0.492898,
  1182. X    -0.514103, -0.534998, -0.555570, -0.575808, -0.595699, -0.615232,
  1183. X    -0.634393, -0.653173, -0.671559, -0.689541, -0.707107, -0.724247,
  1184. X    -0.740951, -0.757209, -0.773010, -0.788346, -0.803208, -0.817585,
  1185. X    -0.831470, -0.844854, -0.857729, -0.870087, -0.881921, -0.893224,
  1186. X    -0.903989, -0.914210, -0.923880, -0.932993, -0.941544, -0.949528,
  1187. X    -0.956940, -0.963776, -0.970031, -0.975702, -0.980785, -0.985278,
  1188. X    -0.989177, -0.992480, -0.995185, -0.997290, -0.998795, -0.999699,
  1189. X    -1.000000, -0.999699, -0.998795, -0.997290, -0.995185, -0.992480,
  1190. X    -0.989177, -0.985278, -0.980785, -0.975702, -0.970031, -0.963776,
  1191. X    -0.956940, -0.949528, -0.941544, -0.932993, -0.923880, -0.914210,
  1192. X    -0.903989, -0.893224, -0.881921, -0.870087, -0.857729, -0.844854,
  1193. X    -0.831470, -0.817585, -0.803208, -0.788346, -0.773010, -0.757209,
  1194. X    -0.740951, -0.724247, -0.707107, -0.689541, -0.671559, -0.653173,
  1195. X    -0.634393, -0.615232, -0.595699, -0.575808, -0.555570, -0.534998,
  1196. X    -0.514103, -0.492898, -0.471397, -0.449611, -0.427555, -0.405241,
  1197. X    -0.382683, -0.359895, -0.336890, -0.313682, -0.290285, -0.266713,
  1198. X    -0.242980, -0.219101, -0.195090, -0.170962, -0.146730, -0.122411,
  1199. X    -0.098017, -0.073565, -0.049068, -0.024541
  1200. X};
  1201. X
  1202. XFILE    *Fpi, *Fpo;
  1203. X
  1204. X
  1205. X/* The program */
  1206. X
  1207. Xmain(argc, argv)
  1208. Xint    argc;
  1209. Xchar    **argv;
  1210. X{
  1211. X    if (argc != 2)  {
  1212. X        fprintf(stderr, "Usage: fft input_file\n");
  1213. X        exit(1);
  1214. X    }
  1215. X
  1216. X    setcbrk(1);        /* Allow Control-C checking */
  1217. X    ctrlbrk(quit);        /* Execute quit() if Control-C detected */
  1218. X
  1219. X    /* open the data file */
  1220. X
  1221. X    if ((Fpi = fopen(*++argv, "rb")) == NULL)  {
  1222. X        fprintf(stderr,"fft: Unable to open data input file\n");
  1223. X        exit(1);
  1224. X    }
  1225. X
  1226. X    /* read in the data */
  1227. X
  1228. X    fread(Real, sizeof(double), SAMPLES, Fpi);
  1229. X    fread(Imag, sizeof(double), SAMPLES, Fpi);
  1230. X    fclose(Fpi);
  1231. X
  1232. X    build_window();
  1233. X    scale();
  1234. X    fft();
  1235. X    display();
  1236. X
  1237. X    /* wait for keyboard commands */
  1238. X
  1239. X    commands();
  1240. X}
  1241. X
  1242. X
  1243. Xvoid scale()
  1244. X{
  1245. X    register int    loop;
  1246. X
  1247. X    for (loop = 0; loop < SAMPLES; loop++)  {
  1248. X        Real[loop] /= SAMPLES;
  1249. X        Imag[loop] /= SAMPLES;
  1250. X    }
  1251. X}
  1252. X
  1253. X
  1254. Xvoid fft()
  1255. X{
  1256. X    register int    loop, loop1, loop2;
  1257. X    unsigned    i1;            /* going to right shift this */
  1258. X    int        i2, i3, i4, y;
  1259. X    double        a1, a2, b1, b2, z1, z2;
  1260. X
  1261. X    i1 = SAMPLES >> 1;
  1262. X    i2 = 1;
  1263. X
  1264. X    /* perform the butterfly's */
  1265. X
  1266. X    for (loop = 0; loop < POWER; loop++)  {
  1267. X        i3 = 0;
  1268. X        i4 = i1;
  1269. X
  1270. X        for (loop1 = 0; loop1 < i2; loop1++)  {
  1271. X            y = permute(i3 / (int)i1);
  1272. X            z1 =  cosine(y);
  1273. X            z2 = -sine(y);
  1274. X
  1275. X            for (loop2 = i3; loop2 < i4; loop2++)  {
  1276. X
  1277. X                a1 = Real[loop2];
  1278. X                a2 = Imag[loop2];
  1279. X
  1280. X                b1  = z1*Real[loop2+i1] - z2*Imag[loop2+i1];
  1281. X                b2  = z2*Real[loop2+i1] + z1*Imag[loop2+i1];
  1282. X
  1283. X                Real[loop2] = a1 + b1;
  1284. X                Imag[loop2] = a2 + b2;
  1285. X
  1286. X                Real[loop2+i1] = a1 - b1;
  1287. X                Imag[loop2+i1] = a2 - b2;
  1288. X            }
  1289. X
  1290. X            i3 += (i1 << 1);
  1291. X            i4 += (i1 << 1);
  1292. X        }
  1293. X
  1294. X        i1 >>= 1;
  1295. X        i2 <<= 1;
  1296. X    }
  1297. X}
  1298. X
  1299. X/*
  1300. X *    Display the frequency domain.
  1301. X *
  1302. X *    The filters are aranged so that DC is in the middle filter.
  1303. X *    Thus -Doppler is on the left, +Doppler on the right.
  1304. X */
  1305. X
  1306. Xvoid display()
  1307. X{
  1308. X    register int    loop, offset;
  1309. X    int        n, x;
  1310. X
  1311. X    n = SAMPLES >> 1;
  1312. X    max_amp();
  1313. X
  1314. X    /*
  1315. X     *    Graphics screen horizontal configuration:
  1316. X     *
  1317. X     *    | 64 pixels | 512 pixels | 64 pixels |
  1318. X     *    |   margin  |   picture  |   margin  |
  1319. X     *
  1320. X     *    Spectral lines are two bits wide
  1321. X     */
  1322. X
  1323. X    for (loop = n, offset = LEFT; loop < SAMPLES; loop++, offset++)  {
  1324. X        x = (int)(magnitude(loop) * Length / Maxn);
  1325. X        bar((offset + loop - n), Bottom - x, (offset + loop - n) + 1, Bottom);
  1326. X    }
  1327. X
  1328. X    for (loop = 0, offset = MIDDLE; loop < n; loop++, offset++)  {
  1329. X        x = (int)(magnitude(loop) * Length / Maxn);
  1330. X        bar((offset + loop + n), Bottom - x, (offset + loop + n) + 1, Bottom);
  1331. X    }
  1332. X}
  1333. X
  1334. X/*
  1335. X *    Find maximum amplitude
  1336. X */
  1337. X
  1338. Xvoid max_amp()
  1339. X{
  1340. X    register int    loop;
  1341. X    double        mag;
  1342. X
  1343. X    Maxn = 0.0;
  1344. X    for (loop = 0; loop < SAMPLES; loop++)  {
  1345. X        if ((mag = magnitude(loop)) > Maxn)
  1346. X            Maxn = mag;
  1347. X    }
  1348. X}
  1349. X
  1350. X/*
  1351. X *    Calculate Power Magnitude
  1352. X */
  1353. X
  1354. Xdouble magnitude(n)
  1355. Xint    n;
  1356. X{
  1357. X    n = permute(n);
  1358. X    return hypot(Real[n], Imag[n]);
  1359. X}
  1360. X
  1361. Xvoid build_window()
  1362. X{
  1363. X    unsigned i_size;
  1364. X
  1365. X    /* settup graphics mode */
  1366. X
  1367. X    registerbgidriver(CGA_driver);
  1368. X    registerbgidriver(EGAVGA_driver);
  1369. X
  1370. X    initgraph(&GraphDriver, &GraphMode, "");
  1371. X
  1372. X    if (graphresult() != grOk)  {
  1373. X        fprintf(stderr, "fft: %s\n", grapherrormsg(graphresult()));
  1374. X        exit(1);
  1375. X    }
  1376. X
  1377. X    if ((i_size = getgraphmode()) != CGAHI)
  1378. X        setbkcolor(BLACK);
  1379. X
  1380. X    switch (i_size)  {
  1381. X    case CGAHI:
  1382. X        Primary = WHITE;
  1383. X        Cursor  = WHITE;
  1384. X        Length  = 100.0;
  1385. X        Bottom  = 150;
  1386. X        break;
  1387. X    case EGAHI:
  1388. X        Primary = LIGHTGRAY;
  1389. X        Cursor  = LIGHTGREEN;
  1390. X        Length  = 250.0;
  1391. X        Bottom  = 300;
  1392. X        break;
  1393. X    case VGAHI:
  1394. X        Primary = LIGHTGRAY;
  1395. X        Cursor  = LIGHTGREEN;
  1396. X        Length  = 380.0;
  1397. X        Bottom  = 430;
  1398. X    }
  1399. X
  1400. X    setcolor(Primary);
  1401. X    setfillstyle(SOLID_FILL, Primary);
  1402. X    settextjustify(LEFT_TEXT, TOP_TEXT);
  1403. X    settextstyle(DEFAULT_FONT, HORIZ_DIR, 2);
  1404. X
  1405. X    cleardevice();
  1406. X
  1407. X    outtextxy(TEXTX, TEXTY, "Computing FFT");
  1408. X
  1409. X    /* Draw ruler line */
  1410. X
  1411. X    line(LEFT, Bottom + 5, RIGHT, Bottom + 5);
  1412. X    for (i_size = LEFT; i_size <= RIGHT ; i_size += 10)  {
  1413. X        line(i_size, Bottom + 5, i_size, Bottom + 10);
  1414. X        line(i_size + 1, Bottom + 5, i_size + 1, Bottom + 10);
  1415. X    }
  1416. X
  1417. X    /* create under-cursor memory */
  1418. X
  1419. X    i_size = imagesize(LEFT, TOP, LEFT + 1, Bottom);
  1420. X    Save   = malloc(i_size);
  1421. X}
  1422. X
  1423. Xvoid commands()
  1424. X{
  1425. X    int    key, filter;
  1426. X    char    string[4];
  1427. X
  1428. X    setcolor(BLACK);    /* erase text */
  1429. X    outtextxy(TEXTX, TEXTY, "Computing FFT");
  1430. X    setcolor(Primary);
  1431. X
  1432. X    Left   = 320;
  1433. X    filter = 128;
  1434. X    strcpy(string, "128");
  1435. X    outtextxy(TEXTX, TEXTY, "Filter # 128");
  1436. X    getimage(Left, TOP, Left + 1, Bottom, Save);
  1437. X    setfillstyle(SOLID_FILL, Cursor);
  1438. X    bar(Left, TOP, Left + 1, Bottom);
  1439. X
  1440. X    for (;;)  {
  1441. X        while (bioskey(1) == 0)        /* wait for key press */
  1442. X            ;
  1443. X        key = getkey();
  1444. X
  1445. X        switch(key)  {        /* find out which key was pressed */
  1446. X        case HOMEKEY:
  1447. Xj1:            putimage(Left, TOP, Save, COPY_PUT);
  1448. X            filter = 0;
  1449. X            Left = LEFT;
  1450. X            getimage(Left, TOP, Left + 1, Bottom, Save);
  1451. X            bar(Left, TOP, Left + 1, Bottom);
  1452. X
  1453. X            setcolor(BLACK);    /* erase old text */
  1454. X            outtextxy(TEXTXN, TEXTY, string);
  1455. X            setcolor(Primary);
  1456. X
  1457. X            sprintf(string, "%d", filter);
  1458. X            outtextxy(TEXTXN, TEXTY, string);
  1459. X            break;
  1460. X        case ENDKEY:
  1461. Xj2:            putimage(Left, TOP, Save, COPY_PUT);
  1462. X            filter = 255;
  1463. X            Left = RIGHT - 1;
  1464. X            getimage(Left, TOP, Left + 1, Bottom, Save);
  1465. X            bar(Left, TOP, Left + 1, Bottom);
  1466. X
  1467. X            setcolor(BLACK);    /* erase old text */
  1468. X            outtextxy(TEXTXN, TEXTY, string);
  1469. X            setcolor(Primary);
  1470. X
  1471. X            sprintf(string, "%d", filter);
  1472. X            outtextxy(TEXTXN, TEXTY, string);
  1473. X            break;
  1474. X        case CTRLLEFTKEY:
  1475. X            if (filter <= 9)
  1476. X                goto j1;
  1477. X
  1478. X            putimage(Left, TOP, Save, COPY_PUT);
  1479. X            Left -= 20;
  1480. X            filter -= 10;
  1481. X            getimage(Left, TOP, Left + 1, Bottom, Save);
  1482. X            bar(Left, TOP, Left + 1, Bottom);
  1483. X
  1484. X            setcolor(BLACK);    /* erase old text */
  1485. X            outtextxy(TEXTXN, TEXTY, string);
  1486. X            setcolor(Primary);
  1487. X
  1488. X            sprintf(string, "%d", filter);
  1489. X            outtextxy(TEXTXN, TEXTY, string);
  1490. X            break;
  1491. X        case LEFTKEY:
  1492. X            if (filter <= 0)  {
  1493. X                beep();
  1494. X                break;
  1495. X            }
  1496. X
  1497. X            putimage(Left, TOP, Save, COPY_PUT);
  1498. X            Left -= 2;
  1499. X            filter--;
  1500. X            getimage(Left, TOP, Left + 1, Bottom, Save);
  1501. X            bar(Left, TOP, Left + 1, Bottom);
  1502. X
  1503. X            setcolor(BLACK);    /* erase old text */
  1504. X            outtextxy(TEXTXN, TEXTY, string);
  1505. X            setcolor(Primary);
  1506. X
  1507. X            sprintf(string, "%d", filter);
  1508. X            outtextxy(TEXTXN, TEXTY, string);
  1509. X            break;
  1510. X        case CTRLRIGHTKEY:
  1511. X            if (filter >= 245)
  1512. X                goto j2;
  1513. X
  1514. X            putimage(Left, TOP, Save, COPY_PUT);
  1515. X            Left += 20;
  1516. X            filter += 10;
  1517. X            getimage(Left, TOP, Left + 1, Bottom, Save);
  1518. X            bar(Left, TOP, Left + 1, Bottom);
  1519. X
  1520. X            setcolor(BLACK);    /* erase old text */
  1521. X            outtextxy(TEXTXN, TEXTY, string);
  1522. X            setcolor(Primary);
  1523. X
  1524. X            sprintf(string, "%d", filter);
  1525. X            outtextxy(TEXTXN, TEXTY, string);
  1526. X            break;
  1527. X        case RIGHTKEY:
  1528. X            if (filter >= 255)  {
  1529. X                beep();
  1530. X                break;
  1531. X            }
  1532. X
  1533. X            putimage(Left, TOP, Save, COPY_PUT);
  1534. X            Left += 2;
  1535. X            filter++;
  1536. X            getimage(Left, TOP, Left + 1, Bottom, Save);
  1537. X            bar(Left, TOP, Left + 1, Bottom);
  1538. X
  1539. X            setcolor(BLACK);    /* erase old text */
  1540. X            outtextxy(TEXTXN, TEXTY, string);
  1541. X            setcolor(Primary);
  1542. X
  1543. X            sprintf(string, "%d", filter);
  1544. X            outtextxy(TEXTXN, TEXTY, string);
  1545. X            break;
  1546. X        case F1:
  1547. X            if (PrintScreen())
  1548. X                bee_bop();
  1549. X            break;
  1550. X        case ESC:
  1551. X            quit();
  1552. X        default:
  1553. X            beep();
  1554. X        }
  1555. X    }
  1556. X}
  1557. X
  1558. Xvoid beep()
  1559. X{
  1560. X    sound(200);
  1561. X    delay(125);
  1562. X    nosound();
  1563. X}
  1564. X
  1565. Xvoid bee_bop()
  1566. X{
  1567. X    sound(1000);
  1568. X    delay(80);
  1569. X    sound(200);
  1570. X    delay(160);
  1571. X    sound(1000);
  1572. X    nosound();
  1573. X}
  1574. X
  1575. X/*
  1576. X *    Return to MS-DOS operating system
  1577. X */
  1578. X
  1579. Xvoid quit()
  1580. X{
  1581. X    sound(1000);
  1582. X    delay(250);
  1583. X    nosound();
  1584. X
  1585. X    closegraph();
  1586. X
  1587. X    free((char *)Save);
  1588. X
  1589. X    exit(0);
  1590. X}
  1591. X
  1592. X/*
  1593. X *    Dumps a screen to printer in Double Density landscape format.
  1594. X *    This routine is from the Borland Programming Forum on CompuServe.
  1595. X *
  1596. X *    returns TRUE on error
  1597. X */
  1598. X
  1599. Xint PrintScreen()
  1600. X{
  1601. X    int            X,Y,YOfs;
  1602. X    int            BitData,MaxBits;
  1603. X    unsigned int        Height,Width;
  1604. X    struct viewporttype     Vport;
  1605. X
  1606. X    getviewsettings(&Vport);
  1607. X    Width  = Vport.bottom - Vport.top;
  1608. X    Height = (Vport.right + 1) - Vport.left;
  1609. X
  1610. X    if (PrintChar(27))
  1611. X        return (1);
  1612. X
  1613. X    if (PrintChar('3'))
  1614. X        return (1);
  1615. X
  1616. X    if (PrintChar(24))    /* 24/216 inch line spacing */
  1617. X        return (1);
  1618. X
  1619. X    Y = 0;
  1620. X    while (Y < Height)  {
  1621. X        if (PrintChar(27))
  1622. X            return (1);
  1623. X
  1624. X        if (PrintChar('L'))    /* Double Density */
  1625. X            return (1);
  1626. X
  1627. X        if (PrintChar(Width & 0xff))
  1628. X            return (1);
  1629. X
  1630. X        if (PrintChar(Width >> 8))
  1631. X            return (1);
  1632. X
  1633. X        for (X = Width - 1; X >= 0; X--)  {
  1634. X            BitData = 0;
  1635. X            if ((Y + 7) <= Height)
  1636. X                MaxBits = 7;
  1637. X            else
  1638. X                MaxBits = Height - Y;
  1639. X
  1640. X            for (YOfs = 0; YOfs <= MaxBits; YOfs++)  {
  1641. X                BitData = BitData << 1;
  1642. X                if (getpixel(YOfs + Y, X) > 0)
  1643. X                    BitData++;
  1644. X            }
  1645. X
  1646. X            if (PrintChar(BitData))
  1647. X                return (1);
  1648. X        }
  1649. X
  1650. X        if (PrintChar('\r'))
  1651. X            return (1);
  1652. X
  1653. X        if (PrintChar('\n'))
  1654. X            return (1);
  1655. X
  1656. X        Y += 8;
  1657. X    }
  1658. X
  1659. X    PrintChar(12);        /* formfeed */
  1660. X
  1661. X    return (0);
  1662. X}
  1663. X
  1664. X/*
  1665. X *    returns TRUE on error
  1666. X */
  1667. X
  1668. Xint PrintChar(out)
  1669. Xint    out;
  1670. X{
  1671. X    unsigned char    ret;
  1672. X
  1673. X    ret = biosprint(0, out, 0);
  1674. X    if ((ret & 0x29) || !(ret & 0x10))
  1675. X        return 1;
  1676. X    else
  1677. X        return 0;
  1678. X}
  1679. X
  1680. Xint getkey()
  1681. X{
  1682. X    int    key, lo, hi;
  1683. X
  1684. X    key = bioskey(0);
  1685. X    lo = key & 0x00FF;
  1686. X    hi = (key & 0xFF00) >> 8;
  1687. X
  1688. X    return((lo == 0) ? hi + 256 : lo);
  1689. X}
  1690. X
  1691. X/* EOF */
  1692. END_OF_fft.c
  1693. if test 15702 -ne `wc -c <fft.c`; then
  1694.     echo shar: \"fft.c\" unpacked with wrong size!
  1695. fi
  1696. # end of overwriting check
  1697. fi
  1698. if test -f sine.c -a "${1}" != "-c" ; then 
  1699.   echo shar: Will not over-write existing file \"sine.c\"
  1700. else
  1701. echo shar: Extracting \"sine.c\" \(1139 characters\)
  1702. sed "s/^X//" >sine.c <<'END_OF_sine.c'
  1703. X/*
  1704. X *    sine.c
  1705. X *
  1706. X *    Version 2.6 by Steve Sampson, Public Domain, November 1988
  1707. X *
  1708. X *    This program is used to generate time domain sinewave data
  1709. X *    for fft.c.  If you want an opening target - negate the
  1710. X *    test frequency.
  1711. X */
  1712. X
  1713. X#include <stdio.h>
  1714. X#include <alloc.h>
  1715. X#include <math.h>
  1716. X
  1717. X#define    SAMPLES    256
  1718. X#define    TWO_PI    (2.0 * 3.14159265358979324)
  1719. X
  1720. Xdouble    Sample, Freq, Time, Real[SAMPLES], Imag[SAMPLES];
  1721. XFILE    *Fp;
  1722. X
  1723. X
  1724. Xmain(argc, argv)
  1725. Xint    argc;
  1726. Xchar    **argv;
  1727. X{
  1728. X    register int    loop;
  1729. X
  1730. X    if (argc != 2)  {
  1731. X        fprintf(stderr,"Usage: sine output_file\n");
  1732. X        exit(1);
  1733. X    }
  1734. X
  1735. X    printf("Input The Test Frequency (Hz) ? ");
  1736. X    scanf("%lf", &Freq);
  1737. X    printf("Input The Sampling Frequency (Hz) ? ");
  1738. X    scanf("%lf", &Sample);
  1739. X
  1740. X    Sample = 1.0 / Sample;
  1741. X    Time   = 0.0;
  1742. X
  1743. X    for (loop = 0; loop < SAMPLES; loop++)  {
  1744. X        Real[loop] =  sin(TWO_PI * Freq * Time);
  1745. X        Imag[loop] = -cos(TWO_PI * Freq * Time);
  1746. X        Time += Sample;
  1747. X    }
  1748. X
  1749. X    if ((Fp = fopen(*++argv, "wb")) == NULL)  {
  1750. X        fprintf(stderr,"sine: Unable to create write file\n");
  1751. X        exit(1);
  1752. X    }
  1753. X
  1754. X    fwrite(Real, sizeof(double), SAMPLES, Fp);
  1755. X    fwrite(Imag, sizeof(double), SAMPLES, Fp);
  1756. X    fclose(Fp);
  1757. X
  1758. X    putchar('\n');
  1759. X
  1760. X    exit(0);
  1761. X}
  1762. END_OF_sine.c
  1763. if test 1139 -ne `wc -c <sine.c`; then
  1764.     echo shar: \"sine.c\" unpacked with wrong size!
  1765. fi
  1766. # end of overwriting check
  1767. fi
  1768. if test -f pulse.c -a "${1}" != "-c" ; then 
  1769.   echo shar: Will not over-write existing file \"pulse.c\"
  1770. else
  1771. echo shar: Extracting \"pulse.c\" \(985 characters\)
  1772. sed "s/^X//" >pulse.c <<'END_OF_pulse.c'
  1773. X/*
  1774. X *    pulse.c
  1775. X *
  1776. X *    Version 2.6 by Steve Sampson, Public Domain, November 1988
  1777. X *
  1778. X *    This program is used to generate time domain pulse data    for fft.c.
  1779. X */
  1780. X
  1781. X#include <stdio.h>
  1782. X#include <alloc.h>
  1783. X
  1784. X#define SAMPLES    256
  1785. X
  1786. Xdouble    Sample, Pw, Time, Real[SAMPLES], Imag[SAMPLES];
  1787. XFILE    *Fp;
  1788. X
  1789. X
  1790. Xmain(argc, argv)
  1791. Xint    argc;
  1792. Xchar    **argv;
  1793. X{
  1794. X    register int    loop;
  1795. X
  1796. X    if (argc != 2)  {
  1797. X        fprintf(stderr,"Usage: pulse output_file\n");
  1798. X        exit(1);
  1799. X    }
  1800. X
  1801. X    printf("Input The Pulse Width (Seconds) ? ");
  1802. X    scanf("%lf", &Pw);
  1803. X    printf("Input The Sampling Time (Seconds) ? ");
  1804. X    scanf("%lf", &Sample);
  1805. X
  1806. X    Time = 0.0;
  1807. X
  1808. X    for (loop = 0; loop < SAMPLES; loop++)  {
  1809. X        if (Time < Pw)
  1810. X            Real[loop] = 1.0;
  1811. X        else
  1812. X            Real[loop] = 0.0;
  1813. X
  1814. X        Imag[loop] = 0.0;
  1815. X        Time += Sample;
  1816. X    }
  1817. X
  1818. X    if ((Fp = fopen(*++argv, "wb")) == NULL)  {
  1819. X        fprintf(stderr,"pulse: Unable to create write file\n");
  1820. X        exit(1);
  1821. X    }
  1822. X
  1823. X    fwrite(Real, sizeof(double), SAMPLES, Fp);
  1824. X    fwrite(Imag, sizeof(double), SAMPLES, Fp);
  1825. X    fclose(Fp);
  1826. X
  1827. X    putchar('\n');
  1828. X
  1829. X    exit(0);
  1830. X}
  1831. END_OF_pulse.c
  1832. if test 985 -ne `wc -c <pulse.c`; then
  1833.     echo shar: \"pulse.c\" unpacked with wrong size!
  1834. fi
  1835. # end of overwriting check
  1836. fi
  1837. echo shar: End of shell archive.
  1838. exit 0
  1839.  
  1840.  
  1841.