/// <summary> /// Performs the transformation over a double[] array. /// </summary> public static void FHT(double[] data, FourierTransform.Direction direction) { int N = data.Length; // Forward operation if (direction == FourierTransform.Direction.Forward) { // Copy the input to a complex array which can be processed // in the complex domain by the FFT Complex[] cdata = new Complex[N]; for (int i = 0; i < N; i++) { cdata[i].Re = data[i]; } // Perform FFT FourierTransform.FFT(cdata, FourierTransform.Direction.Forward); //double positive frequencies for (int i = 1; i < (N / 2); i++) { cdata[i].Re *= 2.0; cdata[i].Im *= 2.0; } // zero out negative frequencies // (leaving out the dc component) for (int i = (N / 2) + 1; i < N; i++) { cdata[i].Re = 0.0; cdata[i].Im = 0.0; } // Reverse the FFT FourierTransform.FFT(cdata, FourierTransform.Direction.Backward); // Convert back to our initial double array for (int i = 0; i < N; i++) { data[i] = cdata[i].Im; } } else // Backward operation { // The inverse Hilbert can be calculated by // negating the transform and reapplying the // transformation. // // H^–1{h(t)} = –H{h(t)} FHT(data, FourierTransform.Direction.Forward); for (int i = 0; i < data.Length; i++) { data[i] = -data[i]; } } }
/// <summary> /// Two dimensional Fast Fourier Transform. /// </summary> /// /// <param name="data">Data to transform.</param> /// <param name="direction">Transformation direction.</param> /// /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size /// only in each dimension, where <b>n</b> may vary in the [1, 14] range. For example, 16x16 array /// is valid, but 15x15 is not.</note></para></remarks> /// /// <exception cref="ArgumentException">Incorrect data length.</exception> /// public static void FFT2(Complex[,] data, Direction direction) { int k = data.GetLength(0); int n = data.GetLength(1); // check data size if ( (!Tools.IsPowerOf2(k)) || (!Tools.IsPowerOf2(n)) || (k < minLength) || (k > maxLength) || (n < minLength) || (n > maxLength) ) { throw new ArgumentException("Incorrect data length."); } // process rows Complex[] row = new Complex[n]; for (int i = 0; i < k; i++) { // copy row for (int j = 0; j < n; j++) { row[j] = data[i, j]; } // transform it FourierTransform.FFT(row, direction); // copy back for (int j = 0; j < n; j++) { data[i, j] = row[j]; } } // process columns Complex[] col = new Complex[k]; for (int j = 0; j < n; j++) { // copy column for (int i = 0; i < k; i++) { col[i] = data[i, j]; } // transform it FourierTransform.FFT(col, direction); // copy back for (int i = 0; i < k; i++) { data[i, j] = col[i]; } } }
/// <summary> /// One dimensional Fast Fourier Transform. /// </summary> /// /// <param name="data">Data to transform.</param> /// <param name="direction">Transformation direction.</param> /// /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size /// only, where <b>n</b> may vary in the [1, 14] range.</note></para></remarks> /// /// <exception cref="ArgumentException">Incorrect data length.</exception> /// public static void FFT(Complex[] data, Direction direction) { int n = data.Length; int m = Tools.Log2(n); // reorder data first ReorderData(data); // compute FFT int tn = 1, tm; for (int k = 1; k <= m; k++) { Complex[] rotation = FourierTransform.GetComplexRotation(k, direction); tm = tn; tn <<= 1; for (int i = 0; i < tm; i++) { Complex t = rotation[i]; for (int even = i; even < n; even += tn) { int odd = even + tm; Complex ce = data[even]; Complex co = data[odd]; double tr = co.Re * t.Re - co.Im * t.Im; double ti = co.Re * t.Im + co.Im * t.Re; data[even].Re += tr; data[even].Im += ti; data[odd].Re = ce.Re - tr; data[odd].Im = ce.Im - ti; } } } if (direction == Direction.Forward) { for (int i = 0; i < n; i++) { data[i].Re /= (double)n; data[i].Im /= (double)n; } } }
/// <summary> /// Performs the transformation over a complex[] array. /// </summary> public static void FHT(Complex[] data, FourierTransform.Direction direction) { int N = data.Length; // Forward operation if (direction == FourierTransform.Direction.Forward) { // Makes a copy of the data so we don't lose the // original information to build our final signal Complex[] shift = (Complex[])data.Clone(); // Perform FFT FourierTransform.FFT(shift, FourierTransform.Direction.Backward); //double positive frequencies for (int i = 1; i < (N / 2); i++) { shift[i].Re *= 2.0; shift[i].Im *= 2.0; } // zero out negative frequencies // (leaving out the dc component) for (int i = (N / 2) + 1; i < N; i++) { shift[i].Re = 0.0; shift[i].Im = 0.0; } // Reverse the FFT FourierTransform.FFT(shift, FourierTransform.Direction.Forward); // Put the Hilbert transform in the Imaginary part // of the input signal, creating a Analytic Signal for (int i = 0; i < N; i++) { data[i].Im = shift[i].Im; } } else // Backward operation { // Just discard the imaginary part for (int i = 0; i < data.Length; i++) { data[i].Im = 0.0; } } }