/* calculates the inverse fast Fourier transform of a complex packed array, and stores * it into fft_results. Storage conventions as for complex_fft */ int complex_inverse_fft (size_t N, double *data, double *fft_results) { size_t i; int retcode; /* initialize the data for fft */ for (i=0; i<2*N; i++) fft_results [i] = data [i]; /* use the corresponding routine if N is power of 2 */ if (is_power_of_n (N,2)) { /* perform the fft */ retcode = gsl_fft_complex_radix2_inverse (fft_results, 1, N); } else { /* alloc memory for wavetable and workspace */ gsl_fft_complex_wavetable * wavetable = gsl_fft_complex_wavetable_alloc (N); gsl_fft_complex_workspace * workspace = gsl_fft_complex_workspace_alloc (N); /* perform the fft */ retcode = gsl_fft_complex_inverse (fft_results, 1, N, wavetable, workspace); /* free memory */ gsl_fft_complex_wavetable_free (wavetable); gsl_fft_complex_workspace_free (workspace); } return retcode; }
QuantityType fftgtof(const QuantityType& g, double rstep, double rmin) { if (g.empty()) return g; int padrmin = int(round(rmin / rstep)); int Npad1 = padrmin + g.size(); // pad to the next power of 2 for fast Fourier transformation int Npad2 = (1 << int(ceil(log2(Npad1)))); // sine transformations needs an odd extension // gpadc array has to be doubled for complex coefficients int Npad4 = 4 * Npad2; valarray<double> gpadc(0.0, Npad4); QuantityType::const_iterator gi; // copy the original g signal int ilo = padrmin; for (gi = g.begin(); gi != g.end(); ++gi, ++ilo) { gpadc[2 * ilo] = *gi; } // copy the odd part of g skipping the first point, // because it is periodic image of gpadc[0] int ihi = 2 * Npad2 - 1; for (ilo = 1; ilo < Npad2; ++ilo, --ihi) { gpadc[2 * ihi] = -1 * gpadc[2 * ilo]; } int status; status = gsl_fft_complex_radix2_inverse(&(gpadc[0]), 1, 2 * Npad2); if (status != GSL_SUCCESS) throw invalid_argument(EMSGFFT); QuantityType f(Npad2); for (int i = 0; i < Npad2; ++i) { f[i] = gpadc[2 * i + 1] * Npad2 * rstep; } // real components should be all close to zero assert(fabs(valarray<double>(gpadc[slice(0, 2 * Npad2, 2)]).min()) <= SQRT_DOUBLE_EPS * gpadc.max()); assert(fabs(valarray<double>(gpadc[slice(0, 2 * Npad2, 2)]).max()) <= SQRT_DOUBLE_EPS * gpadc.max()); return f; }
/* * Extracting information from a noisy signal */ void extract_noisy_signal(int count, double *values) { plot_t p; p.outfile = "output5.png"; p.title = "Noisy signal"; p.xlabel = "t [s]"; p.ylabel = "u(t) [m]"; p.xmin = 0; p.xmax = 0; init_gnuplot(&p); gsl_complex_packed_array data = calloc(2*count, sizeof(double)); // Noisy signal BEGIN_SCATTER(p, "u(t)"); double t = 0; for (int i = 0; i < count; i++) { PLOT(p, t, values[i]); data[2*i] = values[i]; t += 1.0/count; } END_PLOT(p); p.outfile = "output6.png"; p.title = "FFT of noisy signal"; p.xlabel = "f [Hz]"; p.ylabel = "U(f) [m]"; p.xmin = -1500; p.xmax = 1500; init_gnuplot(&p); gsl_fft_complex_radix2_forward(data, 1, count); // FFT of noisy signal BEGIN_SCATTER(p, "U(f)"); double f = -count/2; for (int i = count; i < 2*count; i += 2) { double y = data[i]; data[i] = H(f) * data[i]; data[i+1] = H(f) * data[i+1]; PLOT(p, f, y); f += 1.0; } for (int i = 0; i < count; i += 2) { double y = data[i]; data[i] = H(f) * data[i]; data[i+1] = H(f) * data[i+1]; PLOT(p, f, y); f += 1.0; } END_PLOT(p); gsl_fft_complex_radix2_inverse(data, 1, count); p.outfile = "output7.png"; p.title = "Inverse FFT of data"; p.xlabel = "t [s]"; p.ylabel = "u(t) [m]"; p.xmin = 0; p.xmax = 1; init_gnuplot(&p); // Filtered signal BEGIN_PLOT(p, "u(t)"); t = 0; double umax = 0; int periods = 0; char letter = 0; int bits = 0; const double plen = 0.0078; for (int i = 0; i < 2*count; i += 2) { if (t >= plen * (double)periods && t < plen * ((double)periods + 1.0)) { if (data[i] > umax) umax = data[i]; } else { if (umax < 1) letter *= 2; else letter = letter*2 + 1; bits++; if (bits % 8 == 0) { printf("%c", letter); bits = 0; letter = 0; } umax = 0; periods++; } PLOT(p, t, (data[i])); t += 1.0/count; } if (umax < 1) letter *= 2; else letter = letter*2 + 1; printf("%c\n", letter); END_PLOT(p); }