📄 ufft.c
字号:
/* * fft.c * * Unix Version 2.4 by Steve Sampson, Public Domain, September 1988 * * This program produces a Frequency Domain display from the Time Domain * data input; using the Fast Fourier Transform. * * The Real data is generated by the in-phase (I) channel, and the * Imaginary data is produced by the quadrature-phase (Q) channel of * a Doppler Radar receiver. The middle filter is zero Hz. Closing * targets are displayed to the right, and Opening targets to the left. * * Note: With Imaginary data set to zero the output is a mirror image. * * Usage: fft samples input output * 1. samples is a variable power of two. * 2. Input is (samples * sizeof(double)) characters. * 3. Output is (samples * sizeof(double)) characters. * 4. Standard error is help or debugging messages. * * See also: readme.doc, pulse.c, and sine.c. *//* Includes */#include <stdio.h>#include <malloc.h>#include <math.h>/* Defines */#define TWO_PI (2.0 * 3.14159265358979324) /* alias 360 deg */#define Chunk (Samples * sizeof(double))#define sine(x) Sine[(x)]#define cosine(x) Sine[((x) + (Samples >> 2)) % Samples]/* Globals, Forward declarations */static int Samples, Power;static double *Real, *Imag, Maxn, magnitude();static void scale(), fft(), max_amp(), display(), err_report();static int permute();static double *Sine;static void build_trig();static FILE *Fpi, *Fpo;/* The program */main(argc, argv)int argc;char **argv;{ if (argc != 4) err_report(0); Samples = abs(atoi(*++argv)); Power = log10((double)Samples) / log10(2.0); /* Allocate memory for the variable arrays */ if ((Real = (double *)malloc(Chunk)) == NULL) err_report(1); if ((Imag = (double *)malloc(Chunk)) == NULL) err_report(2); if ((Sine = (double *)malloc(Chunk)) == NULL) err_report(3); /* open the data files */ if ((Fpi = fopen(*++argv, "r")) == NULL) err_report(4); if ((Fpo = fopen(*++argv, "w")) == NULL) err_report(5); /* read in the data from the input file */ fread(Real, sizeof(double), Samples, Fpi); fread(Imag, sizeof(double), Samples, Fpi); fclose(Fpi); build_trig(); scale(); fft(); display(); /* write the frequency domain data to the standard output */ fwrite(Real, sizeof(double), Samples, Fpo); fwrite(Imag, sizeof(double), Samples, Fpo); fclose(Fpo); /* free up memory and let's get back to our favorite shell */ free((char *)Real); free((char *)Imag); free((char *)Sine); exit(0);}static void err_report(n)int n;{ switch (n) { case 0: fprintf(stderr, "Usage: fft samples in_file out_file\n"); fprintf(stderr, "Where samples is a power of two\n"); break; case 1: fprintf(stderr, "fft: Out of memory getting real space\n"); break; case 2: fprintf(stderr, "fft: Out of memory getting imag space\n"); free((char *)Real); break; case 3: fprintf(stderr, "fft: Out of memory getting sine space\n"); free((char *)Real); free((char *)Imag); break; case 4: fprintf(stderr,"fft: Unable to open data input file\n"); free((char *)Real); free((char *)Imag); free((char *)Sine); break; case 5: fprintf(stderr,"fft: Unable to open data output file\n"); fclose(Fpi); free((char *)Real); free((char *)Imag); free((char *)Sine); break; } exit(1);}static void scale(){ register int loop; for (loop = 0; loop < Samples; loop++) { Real[loop] /= Samples; Imag[loop] /= Samples; }}static void fft(){ register int loop, loop1, loop2; unsigned i1; /* going to right shift this */ int i2, i3, i4, y; double a1, a2, b1, b2, z1, z2; i1 = Samples >> 1; i2 = 1; /* perform the butterfly's */ for (loop = 0; loop < Power; loop++) { i3 = 0; i4 = i1; for (loop1 = 0; loop1 < i2; loop1++) { y = permute(i3 / (int)i1); z1 = cosine(y); z2 = -sine(y); for (loop2 = i3; loop2 < i4; loop2++) { a1 = Real[loop2]; a2 = Imag[loop2]; b1 = z1*Real[loop2+i1] - z2*Imag[loop2+i1]; b2 = z2*Real[loop2+i1] + z1*Imag[loop2+i1]; Real[loop2] = a1 + b1; Imag[loop2] = a2 + b2; Real[loop2+i1] = a1 - b1; Imag[loop2+i1] = a2 - b2; } i3 += (i1 << 1); i4 += (i1 << 1); } i1 >>= 1; i2 <<= 1; }}/* * Display the frequency domain. * * The filters are aranged so that DC is in the middle filter. * Thus -Doppler is on the left, +Doppler on the right. */static void display(){ register int loop, offset; int n, x; max_amp(); n = Samples >> 1; for (loop = n; loop < Samples; loop++) { x = (int)(magnitude(loop) * 59.0 / Maxn); printf("%d\t|", loop - n); offset = 0; while (++offset <= x) putchar('='); putchar('\n'); } for (loop = 0; loop < n; loop++) { x = (int)(magnitude(loop) * 59.0 / Maxn); printf("%d\t|", loop + n); offset = 0; while (++offset <= x) putchar('='); putchar('\n'); }}/* * Find maximum amplitude */static void max_amp(){ register int loop; double mag; Maxn = 0.0; for (loop = 0; loop < Samples; loop++) { if ((mag = magnitude(loop)) > Maxn) Maxn = mag; }}/* * Calculate Power Magnitude */static double magnitude(n)int n;{ n = permute(n); return hypot(Real[n], Imag[n]);}/* * Bit reverse the number * * Change 11100000b to 00000111b or vice-versa */static int permute(index)int index;{ register int loop; unsigned n1; int result; n1 = Samples; result = 0; for (loop = 0; loop < Power; loop++) { n1 >>= 1; if (index < n1) continue; /* Unix has a truncation problem with pow() */ result += (int)(pow(2.0, (double)loop) + .05); index -= n1; } return result;}/* * Pre-compute the sine and cosine tables */static void build_trig(){ register int loop; double angle, increment; angle = 0.0; increment = TWO_PI / (double)Samples; for (loop = 0; loop < Samples; loop++) { Sine[loop] = sin(angle); angle += increment; }}/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -