/// <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> /// 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.Real * t.Real - co.Imaginary * t.Imaginary; double ti = co.Real * t.Imaginary + co.Imaginary * t.Real; data[even] += new Complex(tr, ti); data[odd] = new Complex(ce.Real - tr, ce.Imaginary - ti); } } } if (direction == Direction.Forward) { for (int i = 0; i < data.Length; i++) { data[i] /= (double)n; } } }
/// <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++) { var t = rotation[i]; for (int even = i; even < n; even += tn) { int odd = even + tm; var ce = data[even]; var cot = data[odd] * t; data[even] += cot; data[odd] = ce - cot; } } } if (direction == Direction.Forward) { for (int i = 0; i < n; i++) { data[i] /= (double)n; } } }
private static void ReorderData(Complex[] data) { int num = data.Length; if (num < 2 || num > 16384 || !Tools.IsPowerOf2(num)) { throw new ArgumentException("Incorrect data length."); } int[] array = GetReversedBits(Tools.Log2(num)); for (int i = 0; i < num; i++) { int num2 = array[i]; if (num2 > i) { Complex complex = data[i]; data[i] = data[num2]; data[num2] = complex; } } }
public static void FFT(Complex[] data, Direction direction) { int num = data.Length; int num2 = Tools.Log2(num); ReorderData(data); int num3 = 1; for (int i = 1; i <= num2; i++) { Complex[] array = GetComplexRotation(i, direction); int num4 = num3; num3 <<= 1; for (int j = 0; j < num4; j++) { Complex complex = array[j]; for (int k = j; k < num; k += num3) { int num5 = k + num4; Complex complex2 = data[k]; Complex complex3 = data[num5]; double num6 = complex3.Re * complex.Re - complex3.Im * complex.Im; double num7 = complex3.Re * complex.Im + complex3.Im * complex.Re; data[k].Re += num6; data[k].Im += num7; data[num5].Re = complex2.Re - num6; data[num5].Im = complex2.Im - num7; } } } if (direction == Direction.Forward) { for (int l = 0; l < num; l++) { data[l].Re /= num; data[l].Im /= num; } } }
// Reorder data for FFT using private static void ReorderData(Complex[] data) { int len = data.Length; // check data length if ((len < minLength) || (len > maxLength) || (!Tools.IsPowerOf2(len))) { throw new ArgumentException("Incorrect data length."); } int[] rBits = GetReversedBits(Tools.Log2(len)); for (int i = 0; i < len; i++) { int s = rBits[i]; if (s > i) { Complex t = data[i]; data[i] = data[s]; data[s] = t; } } }