⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fft.c

📁 Fast Fourier Transform in C
💻 C
📖 第 1 页 / 共 2 页
字号:
	    if (iflag) {		/* calculate and print inverse FFT */	for (n = 0, rsum = 0.; n < len && fscanf(ifile, "%f", &c[n]) == 1; n++)	    ;	if (n == 0) {	    fprintf(stderr, "%s: standard input is empty\n", pname);	    exit(2);	}	ifft();	exit(0);    }    else {			/* calculate and print forward FFT */	if (nflag) {		/* process input in chunks */	    float *s, *t;	    int nf2 = nflag/2;	    for (m = len; m >= nflag; m >>= 1)		;	    m <<= 1;		/* m is now the smallest power of 2 >= nflag */	    if ((s = (float *)calloc(sizeof(float), m)) == NULL ||		(t = (float *)calloc(sizeof(float), m/2)) == NULL) {		fprintf(stderr, "%s: insufficient memory\n", pname);		exit(2);	    }	    for (n = 0; n < nf2 && fscanf(ifile, "%f", &t[n]) == 1; n++)		;	    while (1) {		if (zflag) {		    for (n = 0, rsum = 0.; n < nf2; n++)			rsum += c[n] = t[n];		    for (i=0; n<nflag && fscanf(ifile,"%f",&t[i])==1; i++, n++)			rsum += c[n] = t[i]; /* read input, accumulate sum */		}		else {		    for (n = 0, rsum = 0.; n < nf2; n++)			c[n] = t[n];		    for (i=0; n<nflag && fscanf(ifile,"%f",&t[i])==1; i++, n++)			c[n] = t[i];		    ;		}		if (n < nflag) break;		fft();		if (Nflag)		    fft_out();		else if (Pflag)		    for (i = 0; i < m; i++)			s[i] += c[i]*c[i];		else		    for (i = 0; i < m; i++)			s[i] += c[i];		nchunks++;	    }	    if (nchunks < 1) {		fprintf(stderr, "%s: input series is too short\n", pname);		exit(2);	    }	    if (Nflag == 0 && Pflag)		for (i = 0; i < m; i++)		    c[i] = sqrt(s[i])/nchunks;	    else		for (i = 0; i < m; i++)		    c[i] = s[i]/nchunks;	}	else {	    read_input();	    if (n == 0) {		fprintf(stderr, "%s: standard input is empty\n", pname);		exit(2);	    }	    fft();	}	if (!Nflag)	    fft_out();	exit(0);    }}/* This function detrends (subtracts a least-squares fitted line from) a   a sequence of n uniformily spaced ordinates supplied in c. */detrend(c, n)float *c;int n;{    int i;    double a, b = 0.0, tsqsum = 0.0, ysum = 0.0, t;    for (i = 0; i < n; i++)	ysum += c[i];    for (i = 0; i < n; i++) {	t = i - n/2 + 0.5;	tsqsum += t*t;	b += t*c[i];    }    b /= tsqsum;    a = ysum/n - b*(n-1)/2.0;    for (i = 0; i < n; i++)	c[i] -= a + b*i;    if (b < -0.04 || b > 0.04)	fprintf(stderr,		"%s: (warning) possibly significant trend in input series\n",		pname);}read_input(){    if (zflag)	for (n = 0, rsum = 0.; n < len && fscanf(ifile, "%f", &c[n]) == 1; n++)	    rsum += c[n];	/* read input, accumulate sum */    else	for (n = 0, rsum = 0.; n < len && fscanf(ifile, "%f", &c[n]) == 1; n++)	    ;}fft()		/* calculate forward FFT */{    int i;    if (zflag) {		/* zero-mean the input array */	rmean = rsum/n;	for (i = 0; i < n; i++)	    c[i] -= rmean;		if (zflag == 2)	    detrend(c, n);    }    for (m = len; m >= n; m >>= 1)	;    m <<= 1;		/* m is now the smallest power of 2 >= n; this is the			   length of the input series (including padding) */    if (wflag)			/* apply the chosen windowing function */	for (i = 0; i < m; i++)	    c[i] *= (*window)(i, m);    else	wsum = m;    norm = sqrt(2.0/(wsum*n));    if (fflag) fstep = freq/(2.*m); /* note that fstep is actually half of				       the frequency interval;  it is				       multiplied by the doubled index i				       to obtain the center frequency for				       bin (i/2) */    realft(c-1, m/2, 1);	/* perform the FFT;  see Numerical Recipes */}fft_out()	/* print the FFT */{    int i;    c[m] = c[1];		/* unpack the output array */    c[1] = c[m+1] = 0.;    for (i = 0; i <= m; i += 2*decimation) {	int j;	double pow;	if (fflag) printf("%g\t", i*fstep);	if (cflag) printf("%g\t%g\n", c[i], c[i+1]);	else {	    for (j = 0, pow = 0.0; j < 2*smooth; j += 2)	        pow += (c[i+j]*c[i+j] + c[i+j+1]*c[i+j+1])*norm*norm;	    pow /= smooth/decimation;	    if (Pflag) printf("%g", pow);	    else printf("%g", sqrt(pow));	    if (pflag) printf("\t%g", atan2(c[i+1], c[i]));	    printf("\n");	}    }}ifft()		/* calculate and print inverse FFT */{    int i;    n -= 2;    c[1] = c[n];		/* repack IFFT input array */    if (iflag < 0) {		/* convert polar form input to rectangular */	for (i = 2; i < n; i += 2) {	    float im;	    im = c[i]*sin(c[i+1]);	    c[i] *= cos(c[i+1]);	    c[i+1] = im;	}    }    realft(c-1, n/2, -1);    if (iflag < 0) {	norm = sqrt(2.0);	for (i = 0; i < n; i++)	    printf("%g\n", c[i]*norm);    }    else	for (i = 0; i < n; i++)	    printf("%g\n", c[i]/(n/2.0));}char *prog_name(s)char *s;{    char *p = s + strlen(s);#ifdef MSDOS    while (p >= s && *p != '\\' && *p != ':') {	if (*p == '.')	    *p = '\0';		/* strip off extension */	if ('A' <= *p && *p <= 'Z')	    *p += 'a' - 'A';	/* convert to lower case */	p--;    }#else    while (p >= s && *p != '/')	p--;#endif    return (p+1);}static char *help_strings[] = { "usage: %s [ OPTIONS ...] INPUT-FILE\n", " where INPUT-FILE is the name of a text file containing a time series", " (use `-' to read the standard input), and OPTIONS may be any of:", " -c       Output unnormalized complex FFT (real components in first column,", "          imaginary components in second column).", " -f FREQ  Show the center frequency for each bin in the first column.  The", "          FREQ argument specifies the input sampling frequency;  the center", "          frequencies are given in the same units.", " -h       Print on-line help.", " -i       Perform inverse FFT;  in this case, the standard input should be", "          in the form generated by `fft -c', and the standard output is", "          a series of samples.", " -I       Perform inverse FFT as above, but using input generated by `fft -p'.", " -l LEN   Perform up to LEN-point transforms.  `fft' rounds n up to the next", "          higher power of two unless LEN is already a power of two.  If the", "          input series contains fewer than LEN samples, it is padded with", "          zeros up to the next higher power of two.  Any additional input", "          samples beyond the first LEN are not read.  Default: LEN = 16384.", " -n NN     Process the input in overlapping chunks of N samples and output", "          an averaged spectrum.  If used in combination with -P, the output", "          is the average of the individual squared magnitudes;  otherwise,", "          the output is derived from the averages of the real components and", "          of the imaginary components taken separately.  For best results,", "          NN should be a power of two.", " -N NN    Process the input in overlapping chunks of NN samples and output a", "          spectrum for each chunk.  For best results, NN should be a power", "          of two.", " -p       Show the phase in radians in the last column.", " -P       Generate a power spectrum (print squared magnitudes).", " -s N     Smooth the output by applying an N-point moving average to each bin.", " -S N     Smooth the output by summing sets of N consecutive bins.", " -w WINDOW", "          Apply the specified WINDOW to the input data.  WINDOW may be one", "          of: `Bartlett', `Blackman', `Blackman-Harris', `Hamming',", "          `Hanning', `Parzen', `Square', and `Welch'.", " -z       Zero-mean the input data.", " -Z       Detrend and zero-mean the input data.", NULL};void help(){    int i;    (void)fprintf(stderr, help_strings[0], pname);    for (i = 1; help_strings[i] != NULL; i++) {	(void)fprintf(stderr, "%s\n", help_strings[i]);	if (i % 23 == 0) {	    char b[5];	    (void)fprintf(stderr, "--More--");	    (void)fgets(b, 5, stdin);	    (void)fprintf(stderr, "\033[A\033[2K"); /* erase "--More--";						       assumes ANSI terminal */	}    }}void realft(data,n,isign)float data[];int n,isign;{    int i, i1, i2, i3, i4, n2p3;    float c1 = 0.5, c2, h1r, h1i, h2r, h2i;    double wr, wi, wpr, wpi, wtemp, theta;    void four1();    theta = PI/(double) n;    if (isign == 1) {	c2 = -0.5;	four1(data, n, 1);    }     else {	c2 = 0.5;	theta = -theta;    }    wtemp = sin(0.5*theta);    wpr = -2.0*wtemp*wtemp;    wpi = sin(theta);    wr = 1.0+wpr;    wi = wpi;    n2p3 = 2*n+3;    for (i = 2; i <= n/2; i++) {	i4 = 1 + (i3 = n2p3 - (i2 = 1 + ( i1 = i + i - 1)));	h1r =  c1*(data[i1] + data[i3]);	h1i =  c1*(data[i2] - data[i4]);	h2r = -c2*(data[i2] + data[i4]);	h2i =  c2*(data[i1] - data[i3]);	data[i1] =  h1r + wr*h2r - wi*h2i;	data[i2] =  h1i + wr*h2i + wi*h2r;	data[i3] =  h1r - wr*h2r + wi*h2i;	data[i4] = -h1i + wr*h2i + wi*h2r;	wr = (wtemp = wr)*wpr - wi*wpi+wr;	wi = wi*wpr + wtemp*wpi + wi;    }    if (isign == 1) {	data[1] = (h1r = data[1]) + data[2];	data[2] = h1r - data[2];    } else {	data[1] = c1*((h1r = data[1]) + data[2]);	data[2] = c1*(h1r - data[2]);	four1(data, n, -1);    }}void four1(data, nn, isign)float data[];int nn, isign;{    int n, mmax, m, j, istep, i;    double wtemp, wr, wpr, wpi, wi, theta;    float tempr, tempi;        n = nn << 1;    j = 1;    for (i = 1; i < n; i += 2) {	if (j > i) {	    tempr = data[j];     data[j] = data[i];     data[i] = tempr;	    tempr = data[j+1]; data[j+1] = data[i+1]; data[i+1] = tempr;	}	m = n >> 1;	while (m >= 2 && j > m) {	    j -= m;	    m >>= 1;	}	j += m;    }    mmax = 2;    while (n > mmax) {	istep = 2*mmax;	theta = TWOPI/(isign*mmax);	wtemp = sin(0.5*theta);	wpr = -2.0*wtemp*wtemp;	wpi = sin(theta);	wr = 1.0;	wi = 0.0;	for (m = 1; m < mmax; m += 2) {	    for (i = m; i <= n; i += istep) {		j =i + mmax;		tempr = wr*data[j]   - wi*data[j+1];		tempi = wr*data[j+1] + wi*data[j];		data[j]   = data[i]   - tempr;		data[j+1] = data[i+1] - tempi;		data[i] += tempr;		data[i+1] += tempi;	    }	    wr = (wtemp = wr)*wpr - wi*wpi + wr;	    wi = wi*wpr + wtemp*wpi + wi;	}	mmax = istep;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -