// Inplace version of rearrange function public void Rearrange(complex *Data, uint N) { // Swap position uint Target = 0; // Process all positions of input signal for (uint Position = 0; Position < N; ++Position) { // Only for not yet swapped entries if (Target > Position) { // Swap entries complex Temp = Data[Target]; Data[Target] = Data[Position]; Data[Position] = Temp; } // Bit mask uint Mask = N; // While bit is set while ((Target & (Mask >>= 1)) != 0) { // Drop bit Target &= ~Mask; } // The current bit is 0 - set it Target |= Mask; } }
public static complex[] to_complex(short[] src, uint l) { complex[] c1 = new complex[l]; fixed(complex *c = c1) { uint i; for (i = 0; i < l; i++) { c[i].a = (double)src[i]; } } return(c1); }
// FFT implementation public void Perform(complex *Data, uint N, bool Inverse /* = false */) { double pi = Inverse ? 3.14159265358979323846 : -3.14159265358979323846; // Iteration through dyads, quadruples, octads and so on... for (uint Step = 1; Step < N; Step <<= 1) { // Jump to the next entry of the same transform factor uint Jump = Step << 1; // Angle increment double delta = pi / (double)Step; // Auxiliary sin(delta / 2) double Sine = System.Math.Sin(delta * .5); // Multiplier for trigonometric recurrence complex Multiplier = complex.create(-2.0 * Sine * Sine, System.Math.Sin(delta)); // Start value for transform factor, fi = 0 complex Factor = complex.create(1.0); // Iteration through groups of different transform factor for (uint Group = 0; Group < Step; ++Group) { // Iteration within group for (uint Pair = Group; Pair < N; Pair += Jump) { // Match position uint Match = Pair + Step; // Second term of two-point transform complex Product = Factor * Data[Match]; // Transform for fi + pi Data[Match] = Data[Pair] - Product; // Transform for fi Data[Pair] += Product; } // Successive transform factor via trigonometric recurrence Factor = Multiplier * Factor + Factor; } } }
public static complex[] to_complex(short[] src, uint l) { complex[] c1 = new complex[l]; fixed (complex* c = c1) { uint i; for (i = 0; i < l; i++) { c[i].a = (double)src[i]; } } return c1; }
public static void inverse(complex[] srcdst) { FFT f = new FFT(); fixed (complex* _srcdst = srcdst) { f.Inverse(_srcdst, (uint)srcdst.Length, true); } }
public static void inverse(complex[] src, complex[] dst) { uint l = (uint)System.Math.Min(src.Length, dst.Length); FFT f = new FFT(); fixed (complex* _src = src) fixed (complex* _dst = dst) { f.Inverse(_src, _dst, l, true); } }
public static void forward(complex[] srcdst) { FFT f = new FFT(); fixed (complex* _srcdst = srcdst) { f.Forward(_srcdst, (uint)srcdst.Length); } }
public static void forward(complex[] src, complex[] dst) { uint l = (uint)System.Math.Min(src.Length, dst.Length); fixed (complex* _src = src) fixed (complex* _dst = dst) { f.Forward(_src, _dst, l); } }
public static void to_short(short* s, complex[] c, uint l) { uint i; for (i = 0; i < l; i++) { s[i] = (short)(System.Math.Sqrt((c[i].a * c[i].a) + (c[i].b * c[i].b))); } }
// Rearrange function public void Rearrange(complex* Input, complex* Output, uint N) { // Data entry position uint Target = 0; // Process all positions of input signal for (uint Position = 0; Position < N; ++Position) { // Set data entry Output[Target] = Input[Position]; // Bit mask uint Mask = N; // While bit is set while ((Target & (Mask >>= 1)) != 0) // Drop bit Target &= ~Mask; // The current bit is 0 - set it Target |= Mask; } }
// FFT implementation public void Perform(complex* Data, uint N, bool Inverse /* = false */) { double pi = Inverse ? 3.14159265358979323846 : -3.14159265358979323846; // Iteration through dyads, quadruples, octads and so on... for (uint Step = 1; Step < N; Step <<= 1) { // Jump to the next entry of the same transform factor uint Jump = Step << 1; // Angle increment double delta = pi / (double)Step; // Auxiliary sin(delta / 2) double Sine = System.Math.Sin(delta * .5); // Multiplier for trigonometric recurrence complex Multiplier = complex.create(-2.0 * Sine * Sine, System.Math.Sin(delta)); // Start value for transform factor, fi = 0 complex Factor = complex.create(1.0); // Iteration through groups of different transform factor for (uint Group = 0; Group < Step; ++Group) { // Iteration within group for (uint Pair = Group; Pair < N; Pair += Jump) { // Match position uint Match = Pair + Step; // Second term of two-point transform complex Product = Factor * Data[Match]; // Transform for fi + pi Data[Match] = Data[Pair] - Product; // Transform for fi Data[Pair] += Product; } // Successive transform factor via trigonometric recurrence Factor = Multiplier * Factor + Factor; } } }
// INVERSE FOURIER TRANSFORM, INPLACE VERSION // Data - both input data and output // N - length of both input data and result // Scale - if to scale result public bool Inverse(complex* Data, uint N, bool Scale /* = true */) { // Check input parameters if (Data == null || N < 1 || (N & (N - 1)) != 0) return false; // Rearrange Rearrange(Data, N); // Call FFT implementation Perform(Data, N, true); // Scale if necessary if (Scale) this.Scale(Data, N); // Succeeded return true; }
// INVERSE FOURIER TRANSFORM // Input - input data // Output - transform result // N - length of both input data and result // Scale - if to scale result public bool Inverse(complex* Input, complex* Output, uint N, bool Scale /* = true */) { // Check input parameters if (Input == null || Output == null || N < 1 || (N & (N - 1)) != 0) return false; // Initialize data Rearrange(Input, Output, N); // Call FFT implementation Perform(Output, N, true); // Scale if necessary if (Scale) this.Scale(Output, N); // Succeeded return true; }
// FORWARD FOURIER TRANSFORM, INPLACE VERSION // Data - both input data and output // N - length of input data public bool Forward(complex* Data, uint N) { // Check input parameters if (Data == null || N < 1 || (N & (N - 1)) != 0) return false; // Rearrange Rearrange(Data, N); // Call FFT implementation Perform(Data, N, false); // Succeeded return true; }
public static void to_complex(complex[] c1, short* src, uint l) { //complex[] c1 = new complex[l]; fixed (complex* c = c1) { uint i; for (i = 0; i < l; i++) { c[i].a = (double)src[i]; c[i].b = 0D; } } return; }
public static void to_double(double[] d, complex[] c, uint l) { uint i; for (i = 0; i < l; i++) { d[i] = System.Math.Sqrt((c[i].a * c[i].a) + (c[i].b * c[i].b)); } }
// Inplace version of rearrange function public void Rearrange(complex* Data, uint N) { // Swap position uint Target = 0; // Process all positions of input signal for (uint Position = 0; Position < N; ++Position) { // Only for not yet swapped entries if (Target > Position) { // Swap entries complex Temp = Data[Target]; Data[Target] = Data[Position]; Data[Position] = Temp; } // Bit mask uint Mask = N; // While bit is set while ((Target & (Mask >>= 1)) != 0) // Drop bit Target &= ~Mask; // The current bit is 0 - set it Target |= Mask; } }
// FORWARD FOURIER TRANSFORM // Input - input data // Output - transform result // N - length of both input data and result public bool Forward(complex* Input, complex* Output, uint N) { // Check input parameters if (Input == null || Output == null || N < 1 || (N & (N - 1)) != 0) return false; // Initialize data Rearrange(Input, Output, N); // Call FFT implementation Perform(Output, N, false); // Succeeded return true; }
// Scaling of inverse FFT result public void Scale(complex* Data, uint N) { double Factor = 1.0 / (double)N; // Scale all data entries for (uint Position = 0; Position < N; ++Position) Data[Position] *= Factor; }