home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume5 / fft2 < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  43.6 KB

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