private Complex[] FFT(Complex[] input) { if (input.Length < 2) { return(new Complex[0]); } var arr = new fftwf_complexarray(input); var outArr = new fftwf_complexarray(input.Length); var plan = fftwf_plan.dft_1d(input.Length, arr, outArr, fftw_direction.Forward, fftw_flags.Estimate); plan.Execute(); return(outArr.GetData_Complex()); }
protected override void OnSettingsChanged(SettingsChangedEventArgs e) { while (isProcessing) { Thread.Sleep(100); } int n = settings.FFTSampleCount; timeDomainData = new float[settings.FFTSampleCount]; frequencyDomainData = new float[settings.FFTSampleCount]; // n*2 because we are dealing with complex numbers complexInput = new float[n * 2]; complexOutput = new float[n * 2]; try { mfin = new fftwf_complexarray(complexInput); mfout = new fftwf_complexarray(complexOutput); } catch (DllNotFoundException) { Console.WriteLine("DllNotFoundException: You must copy the native FFTW DLLs (libfftw3-3.dll, libfftw3f-3.dll, libfftw3l-3.dll) into the working directory."); throw; } catch (BadImageFormatException) { Console.WriteLine("BadImageFormatException: This normally means, that you're loading a 32bit DLL into a 64bit process or vice versa."); throw; } plan = fftwf_plan.dft_1d(n, mfin, mfout, settings.IsBackward ? fftw_direction.Backward : fftw_direction.Forward, settings.PlanningRigor == FFTPlanningRigor.Estimate ? fftw_flags.Estimate : settings.PlanningRigor == FFTPlanningRigor.Measure ? fftw_flags.Measure : settings.PlanningRigor == FFTPlanningRigor.Patient ? fftw_flags.Patient : fftw_flags.Estimate); switch (settings.OutputFormat) { case FFTOutputFormat.Raw: this.OutputBlockSize = settings.FFTSampleCount * 2; break; case FFTOutputFormat.RealImaginaryPair: this.OutputBlockSize = settings.FFTSampleCount; break; case FFTOutputFormat.RealOnly: this.OutputBlockSize = settings.FFTSampleCount / 2; break; case FFTOutputFormat.Magnitude: this.OutputBlockSize = settings.FFTSampleCount / 2; break; case FFTOutputFormat.FrequencyMagnitudePair: this.OutputBlockSize = settings.FFTSampleCount; break; default: throw new ArgumentException("The FFT's output format is not supported.", "FFTOutputFormat"); } }
// Initializes FFTW and all arrays // n: Logical size of the transform public FFTWtest(int n) { Console.WriteLine($"Start testing with n = {n.ToString("#,0")} complex numbers. All plans will be executed {repeatPlan.ToString("#,0")} times on a single thread."); Console.WriteLine("Please wait, creating plans..."); fftLength = n; // create two unmanaged arrays, properly aligned pin = fftwf.malloc(n * 8); pout = fftwf.malloc(n * 8); // create two managed arrays, possibly misalinged // n*2 because we are dealing with complex numbers fin = new float[n * 2]; fout = new float[n * 2]; // and two more for double FFTW din = new double[n * 2]; dout = new double[n * 2]; // get handles and pin arrays so the GC doesn't move them hin = GCHandle.Alloc(fin, GCHandleType.Pinned); hout = GCHandle.Alloc(fout, GCHandleType.Pinned); hdin = GCHandle.Alloc(din, GCHandleType.Pinned); hdout = GCHandle.Alloc(dout, GCHandleType.Pinned); // create a few test transforms fplan1 = fftwf.dft_1d(n, pin, pout, fftw_direction.Forward, fftw_flags.Estimate); fplan2 = fftwf.dft_1d(n, hin.AddrOfPinnedObject(), hout.AddrOfPinnedObject(), fftw_direction.Forward, fftw_flags.Estimate); fplan3 = fftwf.dft_1d(n, hout.AddrOfPinnedObject(), pin, fftw_direction.Backward, fftw_flags.Measure); // end with transforming back to original array fplan4 = fftwf.dft_1d(n, hout.AddrOfPinnedObject(), hin.AddrOfPinnedObject(), fftw_direction.Backward, fftw_flags.Estimate); // and check a quick one with doubles, just to be sure fplan5 = fftw.dft_1d(n, hdin.AddrOfPinnedObject(), hdout.AddrOfPinnedObject(), fftw_direction.Backward, fftw_flags.Measure); // create a managed plan as well mfin = new fftwf_complexarray(fin); mfout = new fftwf_complexarray(fout); mdin = new fftw_complexarray(din); mdout = new fftw_complexarray(dout); mplan1 = fftwf_plan.dft_1d(n, mfin, mfout, fftw_direction.Forward, fftw_flags.Estimate); mplan2 = fftwf_plan.dft_1d(n, mfin, mfout, fftw_direction.Forward, fftw_flags.Measure); mplan3 = fftwf_plan.dft_1d(n, mfin, mfout, fftw_direction.Forward, fftw_flags.Patient); mplan4 = fftwf_plan.dft_1d(n, mfout, mfin, fftw_direction.Backward, fftw_flags.Measure); mplan5 = fftw_plan.dft_1d(n, mdin, mdout, fftw_direction.Forward, fftw_flags.Measure); // fill our arrays with an arbitrary complex sawtooth-like signal for (int i = 0; i < n * 2; i++) { fin[i] = i % 50; } for (int i = 0; i < n * 2; i++) { fout[i] = i % 50; } for (int i = 0; i < n * 2; i++) { din[i] = i % 50; } // copy managed arrays to unmanaged arrays Marshal.Copy(fin, 0, pin, n * 2); Marshal.Copy(fout, 0, pout, n * 2); Console.WriteLine(); }