Пример #1
0
        // Get rotation of complex number
        private static Complex[] GetComplexRotation(int numberOfBits, FourierDirection direction)
        {
            int directionIndex = (direction == FourierDirection.Forward) ? 0 : 1;

            // check if the array is already calculated
            if (complexRotation[numberOfBits - 1, directionIndex] == null)
            {
                int       n     = 1 << (numberOfBits - 1);
                float     uR    = 1.0f;
                float     uI    = 0.0f;
                double    angle = System.Math.PI / n * (int)direction;
                float     wR    = (float)System.Math.Cos(angle);
                float     wI    = (float)System.Math.Sin(angle);
                float     t;
                Complex[] rotation = new Complex[n];

                for (int i = 0; i < n; i++)
                {
                    rotation[i] = new Complex(uR, uI);
                    t           = uR * wI + uI * wR;
                    uR          = uR * wR - uI * wI;
                    uI          = t;
                }

                complexRotation[numberOfBits - 1, directionIndex] = rotation;
            }
            return(complexRotation[numberOfBits - 1, directionIndex]);
        }
Пример #2
0
		public static void DFT(Complex[] data, FourierDirection direction) {
			int length = data.Length;
			Complex[] complexArray = new Complex[length];
			for (int i = 0; i < length; i++) {
				complexArray[i] = Complex.Zero;
				double num2 = (((((double)-((int)direction)) * 2.0) * 3.1415926535897931) * i) / ((double)length);
				for (int j = 0; j < length; j++) {
					double num3 = Math.Cos(j * num2);
					double num4 = Math.Sin(j * num2);
					complexArray[i].Re += (float)((data[j].Re * num3) - (data[j].Im * num4));
					complexArray[i].Im += (float)((data[j].Re * num4) + (data[j].Im * num3));
				}
			}
			if (direction == FourierDirection.Forward) {
				for (int k = 0; k < length; k++) {
					data[k].Re = complexArray[k].Re / ((float)length);
					data[k].Im = complexArray[k].Im / ((float)length);
				}
			} else {
				for (int m = 0; m < length; m++) {
					data[m].Re = complexArray[m].Re;
					data[m].Im = complexArray[m].Im;
				}
			}
		}
Пример #3
0
    private static void     LinearFFT(float[] data, int start, int inc, int length, FourierDirection direction)
    {
        Debug.Assert(data != null);
        Debug.Assert(start >= 0);
        Debug.Assert(inc >= 1);
        Debug.Assert(length >= 1);
        Debug.Assert((start + inc * (length - 1)) * 2 < data.Length);

        // copy to buffer
        float[] buffer = null;
        LockBufferF(length * 2, ref buffer);
        int j = start;

        for (int i = 0; i < length * 2; i++)
        {
            buffer[i] = data[j];
            j        += inc;
        }

        FFT(buffer, length, direction);

        // copy from buffer
        j = start;
        for (int i = 0; i < length; i++)
        {
            data[j] = buffer[i];
            j      += inc;
        }
        UnlockBufferF(ref buffer);
    }
Пример #4
0
        FFT(double[] x, double[] y, uint n, FourierDirection direction, ref object temporaryStorage)
        {
            ChirpNativeFFTStorage s = temporaryStorage as ChirpNativeFFTStorage;

            chirpnativefft(x, y, x, y, (int)n, direction, ref s);
            temporaryStorage = s;
        }
Пример #5
0
    /// <summary>
    /// Compute a 2D fast fourier transform on a data set of complex numbers
    /// </summary>
    /// <param name="data"></param>
    /// <param name="xLength"></param>
    /// <param name="yLength"></param>
    /// <param name="direction"></param>
    public static void      FFT2(ComplexF[] data, int xLength, int yLength, FourierDirection direction)
    {
        int xInc = 1;
        int yInc = xLength;

        if (xLength > 1)
        {
            SyncLookupTableLength(xLength);
            for (int y = 0; y < yLength; y++)
            {
                int xStart = y * yInc;
                LinearFFT_Quick(data, xStart, xInc, xLength, direction);
            }
        }

        if (yLength > 1)
        {
            SyncLookupTableLength(yLength);
            for (int x = 0; x < xLength; x++)
            {
                int yStart = x * xInc;
                LinearFFT_Quick(data, yStart, yInc, yLength, direction);
            }
        }
    }
Пример #6
0
        public static void DFT(Complex[] data, FourierDirection direction)
        {
            int length = data.Length;

            Complex[] complexArray = new Complex[length];
            for (int i = 0; i < length; i++)
            {
                complexArray[i] = Complex.Zero;
                double num2 = (((((double)-((int)direction)) * 2.0) * 3.1415926535897931) * i) / ((double)length);
                for (int j = 0; j < length; j++)
                {
                    double num3 = Math.Cos(j * num2);
                    double num4 = Math.Sin(j * num2);
                    complexArray[i].Re += (float)((data[j].Re * num3) - (data[j].Im * num4));
                    complexArray[i].Im += (float)((data[j].Re * num4) + (data[j].Im * num3));
                }
            }
            if (direction == FourierDirection.Forward)
            {
                for (int k = 0; k < length; k++)
                {
                    data[k].Re = complexArray[k].Re / ((float)length);
                    data[k].Im = complexArray[k].Im / ((float)length);
                }
            }
            else
            {
                for (int m = 0; m < length; m++)
                {
                    data[m].Re = complexArray[m].Re;
                    data[m].Im = complexArray[m].Im;
                }
            }
        }
Пример #7
0
 /// <summary>
 /// Compute a 1D real-symmetric fast fourier transform.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="direction"></param>
 public static void      RFFT(float[] data, FourierDirection direction)
 {
     if (data == null)
     {
         throw new ArgumentNullException("data");
     }
     Fourier.RFFT(data, data.Length, direction);
 }
Пример #8
0
 public static void FFT(ComplexF[] data, FourierDirection direction)
 {
     if (data == null)
     {
         throw new ArgumentNullException("data");
     }
     FFT(data, data.Length, direction);
 }
Пример #9
0
    /// <summary>
    /// Compute a 1D fast Fourier transform of a dataset of complex numbers.
    /// </summary>
    /// <param name="data"></param>
    /// <param name="length"></param>
    /// <param name="direction"></param>
    public static void      FFT_Quick(ComplexF[] data, int length, FourierDirection direction)
    {
        /*if( data == null ) {
         *      throw new ArgumentNullException( "data" );
         * }
         * if( data.Length < length ) {
         *      throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
         * }
         * if( Fourier.IsPowerOf2( length ) == false ) {
         *      throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
         * }
         *
         * Fourier.SyncLookupTableLength( length );*/

        int ln = Fourier.Log2(length);

        // reorder array
        Fourier.ReorderArray(data);

        // successive doubling
        int N         = 1;
        int signIndex = (direction == FourierDirection.Forward) ? 0 : 1;

        for (int level = 1; level <= ln; level++)
        {
            int M = N;
            N <<= 1;

            float[] uRLookup = _uRLookupF[level, signIndex];
            float[] uILookup = _uILookupF[level, signIndex];

            for (int j = 0; j < M; j++)
            {
                float uR = uRLookup[j];
                float uI = uILookup[j];

                for (int even = j; even < length; even += N)
                {
                    int odd = even + M;

                    float r = data[odd].Re;
                    float i = data[odd].Im;

                    float odduR = r * uR - i * uI;
                    float odduI = r * uI + i * uR;

                    r = data[even].Re;
                    i = data[even].Im;

                    data[even].Re = r + odduR;
                    data[even].Im = i + odduI;

                    data[odd].Re = r - odduR;
                    data[odd].Im = i - odduI;
                }
            }
        }
    }
Пример #10
0
        /// <summary>
        /// Performs a inline native fouriertransformation of real and imaginary part arrays.
        /// </summary>
        /// <param name="real">The real part of the array to transform.</param>
        /// <param name="imag">The real part of the array to transform.</param>
        /// <param name="direction">Direction of the Fourier transform.</param>
        public static void FFT(double[] real, double[] imag, FourierDirection direction)
        {
            if (real.Length != imag.Length)
            {
                throw new ArgumentException("Length of real and imaginary array do not match!");
            }

            FFT(real, imag, real, imag, real.Length, direction);
        }
 /// <summary>
 /// Performs a out-of-place fourier transformation. The original values are kept.
 /// </summary>
 /// <param name="inputarr">The data to transform.</param>
 /// <param name="direction">Specify forward or reverse transformation here.</param>
 /// <param name="outputarr">. On output, contains the fourier transformed data.</param>
 public void Transform(double[] inputarr, FourierDirection direction, double[] outputarr)
 {
   if(inputarr.Length!=_numberOfData)
     throw new ArgumentException(string.Format("Length of array inputarr ({0}) is different from the length specified at construction ({1})",inputarr.Length,_numberOfData),"inputarr");
   if(outputarr.Length!=_numberOfData)
     throw new ArgumentException(string.Format("Length of array outputarr ({0}) is different from the length specified at construction ({1})",outputarr.Length,_numberOfData),"outputarr");
   
   Array.Copy(inputarr,0,outputarr,0,inputarr.Length);
   Transform(outputarr,direction);
 }
Пример #12
0
        //======================================================================================

        /// <summary>
        /// Compute a 1D fast Fourier transform of a dataset of complex numbers (as pairs of float's).
        /// </summary>
        /// <param name="data"></param>
        /// <param name="direction"></param>
        public static void FFT(float[] data, FourierDirection direction)
        {
            int length = data.Length;

            Debug.Assert(data != null);
            Debug.Assert(data.Length >= length * 2);
            Debug.Assert(Fourier.IsPowerOf2(length) == true);

            Fourier.SyncLookupTableLength(length);

            int ln = Fourier.Log2(length);

            // reorder array
            Fourier.ReorderArray(data);

            // successive doubling
            int N         = 1;
            int signIndex = (direction == FourierDirection.Forward) ? 0 : 1;

            for (int level = 1; level <= ln; level++)
            {
                int M = N;
                N <<= 1;

                float[] uRLookup = _uRLookupF[level, signIndex];
                float[] uILookup = _uILookupF[level, signIndex];

                for (int j = 0; j < M; j++)
                {
                    float uR = uRLookup[j];
                    float uI = uILookup[j];

                    for (int evenT = j; evenT < length; evenT += N)
                    {
                        int even = evenT << 1;
                        int odd  = (evenT + M) << 1;

                        float r = data[odd];
                        float i = data[odd + 1];

                        float odduR = r * uR - i * uI;
                        float odduI = r * uI + i * uR;

                        r = data[even];
                        i = data[even + 1];

                        data[even]     = r + odduR;
                        data[even + 1] = i + odduI;

                        data[odd]     = r - odduR;
                        data[odd + 1] = i - odduI;
                    }
                }
            }
        }
Пример #13
0
        private static void chirpnativefft(
            double[] resultreal,
            double[] resultimag,
            double[] inputreal,
            double[] inputimag,
            int arrsize,
            FourierDirection direction,
            ref ChirpNativeFFTStorage s)
        {
            if (arrsize <= 2)
            {
                throw new ArgumentException("This algorithm works for array sizes > 2 only.");
            }

            int msize = GetNecessaryTransformationSize(arrsize);

            if (s == null || arrsize != s._arrSize || direction != s._direction)
            {
                s = new ChirpNativeFFTStorage(msize, arrsize, direction);
            }
            else // if the temp storage is not fresh, we have to clear the arrays first
            {
                Array.Clear(s._xjfj_real, 0, msize);
                Array.Clear(s._xjfj_imag, 0, msize);
            }

            // make the arrays local variables
            double[] xjfj_real     = s._xjfj_real;
            double[] xjfj_imag     = s._xjfj_imag;
            double[] fserp_real    = s._fserp_real;
            double[] fserp_imag    = s._fserp_imag;
            double[] resarray_real = s._resarray_real;
            double[] resarray_imag = s._resarray_imag;

            var chirpfactor_real = s._chirpfactors_real;
            var chirpfactor_imag = s._chirpfactors_imag;

            // multiply the input array with the chirpfactors
            for (int i = 0; i < arrsize; ++i)
            {
                xjfj_real[i] = inputreal[i] * chirpfactor_real[i] - inputimag[i] * chirpfactor_imag[i];
                xjfj_imag[i] = inputreal[i] * chirpfactor_imag[i] + inputimag[i] * chirpfactor_real[i];
            }

            // convolute xjfj with precomputed fourier-transformation of fserp
            fhtconvolutionWithFouriertransformed2ndArgument(resarray_real, resarray_imag, xjfj_real, xjfj_imag, fserp_real, fserp_imag, msize);

            // multiply the result  with the chirpfactors
            for (int i = 0; i < arrsize; ++i)
            {
                resultreal[i] = resarray_real[i] * chirpfactor_real[i] - resarray_imag[i] * chirpfactor_imag[i];
                resultimag[i] = resarray_real[i] * chirpfactor_imag[i] + resarray_imag[i] * chirpfactor_real[i];
            }
        }
Пример #14
0
		public static void DFT2(Complex[,] data, FourierDirection direction) {
			double num3;
			double num4;
			double num5;
			int length = data.GetLength(0);
			int num2 = data.GetLength(1);
			Complex[] complexArray = new Complex[Math.Max(length, num2)];
			for (int i = 0; i < length; i++) {
				for (int k = 0; k < num2; k++) {
					complexArray[k] = Complex.Zero;
					num3 = (((((double)-((int)direction)) * 2.0) * 3.1415926535897931) * k) / ((double)num2);
					for (int m = 0; m < num2; m++) {
						num4 = Math.Cos(m * num3);
						num5 = Math.Sin(m * num3);
						complexArray[k].Re += (float)((data[i, m].Re * num4) - (data[i, m].Im * num5));
						complexArray[k].Im += (float)((data[i, m].Re * num5) + (data[i, m].Im * num4));
					}
				}
				if (direction == FourierDirection.Forward) {
					for (int n = 0; n < num2; n++) {
						data[i, n].Re = complexArray[n].Re / ((float)num2);
						data[i, n].Im = complexArray[n].Im / ((float)num2);
					}
				} else {
					for (int num10 = 0; num10 < num2; num10++) {
						data[i, num10].Re = complexArray[num10].Re;
						data[i, num10].Im = complexArray[num10].Im;
					}
				}
			}
			for (int j = 0; j < num2; j++) {
				for (int num12 = 0; num12 < length; num12++) {
					complexArray[num12] = Complex.Zero;
					num3 = (((((double)-((int)direction)) * 2.0) * 3.1415926535897931) * num12) / ((double)length);
					for (int num13 = 0; num13 < length; num13++) {
						num4 = Math.Cos(num13 * num3);
						num5 = Math.Sin(num13 * num3);
						complexArray[num12].Re += (float)((data[num13, j].Re * num4) - (data[num13, j].Im * num5));
						complexArray[num12].Im += (float)((data[num13, j].Re * num5) + (data[num13, j].Im * num4));
					}
				}
				if (direction == FourierDirection.Forward) {
					for (int num14 = 0; num14 < length; num14++) {
						data[num14, j].Re = complexArray[num14].Re / ((float)length);
						data[num14, j].Im = complexArray[num14].Im / ((float)length);
					}
				} else {
					for (int num15 = 0; num15 < length; num15++) {
						data[num15, j].Re = complexArray[num15].Re;
						data[num15, j].Im = complexArray[num15].Im;
					}
				}
			}
		}
Пример #15
0
        // Two dimensional Fast Fourier Transform
        public static void FFT2(Complex[,] data, FourierDirection 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( );
            }

            // 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];
                }
            }
        }
Пример #16
0
        FFT(double[] x, double[] y, FourierDirection direction, ref object temporaryStorage)
        {
            if (x.Length != y.Length)
            {
                throw new ArgumentException("Length of real and imaginary array do not match!");
            }

            var s = temporaryStorage as ChirpNativeFFTStorage;

            chirpnativefft(x, y, x, y, x.Length, direction, ref s);
            temporaryStorage = s;
        }
Пример #17
0
        //======================================================================================
        //======================================================================================
        /// <summary>
        ///   Compute a 1D fast Fourier transform of a dataset of complex numbers (as pairs of float's).
        /// </summary>
        /// <param name = "data"></param>
        /// <param name = "length"></param>
        /// <param name = "direction"></param>
        public static void FFT(float[] data, int length, FourierDirection direction)
        {
            Debug.Assert(data != null);
            Debug.Assert(data.Length >= length*2);
            Debug.Assert(IsPowerOf2(length));

            SyncLookupTableLength(length);

            int ln = Log2(length);

            // reorder array
            ReorderArray(data);

            // successive doubling
            int N = 1;
            int signIndex = (direction == FourierDirection.Forward) ? 0 : 1;
            for (int level = 1; level <= ln; level++)
            {
                int M = N;
                N <<= 1;

                float[] uRLookup = _uRLookupF[level, signIndex];
                float[] uILookup = _uILookupF[level, signIndex];

                for (int j = 0; j < M; j++)
                {
                    float uR = uRLookup[j];
                    float uI = uILookup[j];

                    for (int evenT = j; evenT < length; evenT += N)
                    {
                        int even = evenT << 1;
                        int odd = (evenT + M) << 1;

                        float r = data[odd];
                        float i = data[odd + 1];

                        float odduR = r*uR - i*uI;
                        float odduI = r*uI + i*uR;

                        r = data[even];
                        i = data[even + 1];

                        data[even] = r + odduR;
                        data[even + 1] = i + odduI;

                        data[odd] = r - odduR;
                        data[odd + 1] = i - odduI;
                    }
                }
            }
        }
Пример #18
0
 /// <summary>
 ///     Fourier transform
 /// </summary>
 /// <param name="array">Array</param>
 /// <param name="direction">Fourier direction</param>
 public static void Fourier(Array array, FourierDirection direction)
 {
     var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
     FftwLock.WaitOne();
     var plan = dft(array.Rank, Enumerable.Range(0, array.Rank).Select(array.GetLength).ToArray(),
         handle.AddrOfPinnedObject(), handle.AddrOfPinnedObject(),
         (fftw_direction) direction,
         fftw_flags.Estimate);
     execute(plan);
     destroy_plan(plan);
     FftwLock.ReleaseMutex();
     handle.Free();
 }
Пример #19
0
 /// <summary>
 ///     Fourier transform
 /// </summary>
 /// <param name="n0">Array size</param>
 /// <param name="n1">Array size</param>
 /// <param name="array">Array</param>
 /// <param name="direction">Fourier direction</param>
 public static void Fourier(int n0, int n1, Array array, FourierDirection direction)
 {
     var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
     FftwLock.WaitOne();
     var plan = dft_2d(n0, n1,
         handle.AddrOfPinnedObject(), handle.AddrOfPinnedObject(),
         (fftw_direction) direction,
         fftw_flags.Estimate);
     execute(plan);
     destroy_plan(plan);
     FftwLock.ReleaseMutex();
     handle.Free();
 }
Пример #20
0
        /// <summary>
        /// Voert een 2 dimensionale Fourier analyse uit op een afbeelding
        /// </summary>
        /// <param name="invoer">De complexe waarden van de afbeelding</param>
        /// <param name="dir">FourierDirection.Forward or FourierDirection.Backward</param>
        /// <returns>Fourier resultset</returns>
        private static ComplexGetal[,] FFT2D(ComplexGetal[,] invoer, FourierDirection dir)
        {
            float[] reëel     = new float[invoer.GetLength(1)];
            float[] imaginair = new float[invoer.GetLength(1)];
            ComplexGetal[,] resultaat = invoer;

            //rijen
            for (int i = 0; i < invoer.GetLength(0); i++)
            {
                // Plaats de waarden in een 1 dimensionale array
                for (int j = 0; j < invoer.GetLength(1); j++)
                {
                    reëel[j]     = invoer[i, j].Reëel;
                    imaginair[j] = invoer[i, j].Imaginair;
                }

                // Voer een 1 dimensionale fourier analyse uit op de huidige rij
                FFT1D(dir, reëel, imaginair);

                // Plaats de waarden in het resultaat object
                for (int j = 0; j < resultaat.GetLength(1); j++)
                {
                    resultaat[i, j].Reëel     = reëel[j];
                    resultaat[i, j].Imaginair = imaginair[j];
                }
            }

            //kolommen - gebruik nu het resultaat object, anders gaan de berekeningen van de rijen verloren
            for (int i = 0; i < resultaat.GetLength(1); i++)
            {
                // Plaats de waarden in een 1 dimensionale array
                for (int j = 0; j < resultaat.GetLength(0); j++)
                {
                    reëel[j]     = resultaat[j, i].Reëel;
                    imaginair[j] = resultaat[j, i].Imaginair;
                }

                // Voer een 1 dimensionale fourier analyse uit op de huidige kolom
                FFT1D(dir, reëel, imaginair);

                // Plaats de waarden in het resultaat object
                for (int j = 0; j < resultaat.GetLength(0); j++)
                {
                    resultaat[j, i].Reëel     = reëel[j];
                    resultaat[j, i].Imaginair = imaginair[j];
                }
            }

            return(resultaat);
        }
Пример #21
0
        /// <summary>
        /// Performs a out-of-place fourier transformation. The original values are kept.
        /// </summary>
        /// <param name="inputarr">The data to transform.</param>
        /// <param name="direction">Specify forward or reverse transformation here.</param>
        /// <param name="outputarr">. On output, contains the fourier transformed data.</param>
        public void Transform(double[] inputarr, FourierDirection direction, double[] outputarr)
        {
            if (inputarr.Length != _numberOfData)
            {
                throw new ArgumentException(string.Format("Length of array inputarr ({0}) is different from the length specified at construction ({1})", inputarr.Length, _numberOfData), "inputarr");
            }
            if (outputarr.Length != _numberOfData)
            {
                throw new ArgumentException(string.Format("Length of array outputarr ({0}) is different from the length specified at construction ({1})", outputarr.Length, _numberOfData), "outputarr");
            }

            Array.Copy(inputarr, 0, outputarr, 0, inputarr.Length);
            Transform(outputarr, direction);
        }
Пример #22
0
        /// <summary>
        /// Performs a native fouriertransformation of a real value array.
        /// </summary>
        /// <param name="arr">The double valued array to transform.</param>
        /// <param name="resultarr">Used to store the result of the transformation.</param>
        /// <param name="count">Number of points to transform.</param>
        /// <param name="direction">Direction of the Fourier transform.</param>
        public static void FFT(double[] arr, Complex[] resultarr, int count, FourierDirection direction)
        {
            int iss = direction == FourierDirection.Forward ? 1 : -1;

            for (int k = 0; k < count; k++)
            {
                resultarr[k] = new Complex(0, 0);
                for (int i = 0; i < count; i++)
                {
                    double phi = iss * 2 * Math.PI * ((i * k) % count) / count;
                    resultarr[k] += new Complex(arr[i] * Math.Cos(phi), arr[i] * Math.Sin(phi));
                }
            }
        }
Пример #23
0
        // One dimensional Fast Fourier Transform
        public static void FFT(Complex[] data, FourierDirection 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];

                        float tr = co.Re * t.Re - co.Im * t.Im;
                        float 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 == FourierDirection.Forward)
            {
                for (int i = 0; i < n; i++)
                {
                    data[i].Re /= (float)n;
                    data[i].Im /= (float)n;
                }
            }
        }
Пример #24
0
        private void MyRoutine2(double[] real1, FourierDirection dir)
        {
            int n   = real1.Length;
            var rnd = new System.Random();

            double[] real2 = new double[n];
            for (int i = 0; i < n; i++)
            {
                real2[i] = rnd.NextDouble() / n;
            }

            var fft = new Pfa235FFT(n);

            fft.RealFFT(real2, real1, dir);
        }
Пример #25
0
        /// <summary>
        ///     Fourier transform
        /// </summary>
        /// <param name="array">Array</param>
        /// <param name="direction">Fourier direction</param>
        public static void Fourier(Array array, FourierDirection direction)
        {
            var handle = GCHandle.Alloc(array, GCHandleType.Pinned);

            FftwLock.WaitOne();
            var plan = dft(array.Rank, Enumerable.Range(0, array.Rank).Select(array.GetLength).ToArray(),
                           handle.AddrOfPinnedObject(), handle.AddrOfPinnedObject(),
                           (fftw_direction)direction,
                           fftw_flags.Estimate);

            execute(plan);
            destroy_plan(plan);
            FftwLock.ReleaseMutex();
            handle.Free();
        }
Пример #26
0
        /// <summary>
        ///     Fourier transform
        /// </summary>
        /// <param name="n0">Array size</param>
        /// <param name="n1">Array size</param>
        /// <param name="n2">Array size</param>
        /// <param name="array">Array</param>
        /// <param name="direction">Fourier direction</param>
        public static void Fourier(int n0, int n1, int n2, Complex[] array, FourierDirection direction)
        {
            GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);

            FftwLock.WaitOne();
            IntPtr plan = dft_3d(n0, n1, n2,
                                 handle.AddrOfPinnedObject(), handle.AddrOfPinnedObject(),
                                 (fftw_direction)direction,
                                 fftw_flags.Estimate);

            execute(plan);
            destroy_plan(plan);
            FftwLock.ReleaseMutex();
            handle.Free();
        }
Пример #27
0
        /*-------------------------------------------------------------------------
         *  Perform a 2D FFT inplace given a complex 2D array.
         *  The dimensions of c must be powers of 2
         */
        public static Complex[,] FFT2D(Complex[,] c, FourierDirection dir)
        {
            int rows = c.GetLength(0), cols = c.GetLength(1);

            Complex[,] result = new Complex[rows, cols];

            double[] real = new double[cols];
            double[] imag = new double[cols];
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    real[j] = c[i, j].real;
                    imag[j] = c[i, j].imag;
                }

                // Calling 1D FFT Function for Rows
                FFT1D(ref real, ref imag, dir);

                for (int j = 0; j < cols; j++)
                {
                    result[i, j].real = real[j];
                    result[i, j].imag = imag[j];
                }
            }

            real = new double[rows];
            imag = new double[rows];
            for (int i = 0; i < cols; i++)
            {
                for (int j = 0; j < rows; j++)
                {
                    real[j] = result[j, i].real;
                    imag[j] = result[j, i].imag;
                }

                // Calling 1D FFT Function for Columns
                FFT1D(ref real, ref imag, dir);

                for (int j = 0; j < rows; j++)
                {
                    result[j, i].real = real[j];
                    result[j, i].imag = imag[j];
                }
            }

            return(result);
        }
Пример #28
0
    //======================================================================================


    /// <summary>
    /// Compute a 1D fast Fourier transform of a dataset of complex numbers.
    /// </summary>
    /// <param name="data"></param>
    /// <param name="length"></param>
    /// <param name="direction"></param>
    public static void      FFT(ComplexF[] data, int length, FourierDirection direction)
    {
        SyncLookupTableLength(length);

        int ln = Log2(length);

        // reorder array
        ReorderArray(data);

        // successive doubling
        int N         = 1;
        int signIndex = (direction == FourierDirection.Forward) ? 0 : 1;

        for (int level = 1; level <= ln; level++)
        {
            int M = N;
            N <<= 1;

            float[] uRLookup = _uRLookupF[level, signIndex];
            float[] uILookup = _uILookupF[level, signIndex];

            for (int j = 0; j < M; j++)
            {
                float uR = uRLookup[j];
                float uI = uILookup[j];

                for (int even = j; even < length; even += N)
                {
                    int odd = even + M;

                    float r = data[odd].Re;
                    float i = data[odd].Im;

                    float odduR = r * uR - i * uI;
                    float odduI = r * uI + i * uR;

                    r = data[even].Re;
                    i = data[even].Im;

                    data[even].Re = r + odduR;
                    data[even].Im = i + odduI;

                    data[odd].Re = r - odduR;
                    data[odd].Im = i - odduI;
                }
            }
        }
    }
Пример #29
0
        /// <summary>
        ///     Fourier transform
        /// </summary>
        /// <param name="array">Array</param>
        /// <param name="direction">Fourier direction</param>
        public static void Fourier(Complex[,] array, FourierDirection direction)
        {
            int      n0     = array.GetLength(0);
            int      n1     = array.GetLength(1);
            GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);

            FftwLock.WaitOne();
            IntPtr plan = dft_2d(n0, n1,
                                 handle.AddrOfPinnedObject(), handle.AddrOfPinnedObject(),
                                 (fftw_direction)direction,
                                 fftw_flags.Estimate);

            execute(plan);
            destroy_plan(plan);
            FftwLock.ReleaseMutex();
            handle.Free();
        }
Пример #30
0
            public ChirpNativeFFTStorage(int msize, int arrsize, FourierDirection direction)
            {
                _msize     = msize;
                _arrSize   = arrsize;
                _direction = direction;

                _xjfj_real         = new double[msize];
                _xjfj_imag         = new double[msize];
                _fserp_real        = new double[msize];
                _fserp_imag        = new double[msize];
                _resarray_real     = new double[msize];
                _resarray_imag     = new double[msize];
                _chirpfactors_real = new double[arrsize];
                _chirpfactors_imag = new double[arrsize];

                PreCompute_ChirpFactors();                             // Precompute the factors for An: Exp(sign * I * Pi * i^2/N)
                Precompute_Fouriertransformed_ChirpFactorsConjugate(); // Pre-compute fserp using Pre-computed chirp-factors
            }
Пример #31
0
			public ChirpNativeFFTStorage(int msize, int arrsize, FourierDirection direction)
			{
				_msize = msize;
				_arrSize = arrsize;
				_direction = direction;

				_xjfj_real = new double[msize];
				_xjfj_imag = new double[msize];
				_fserp_real = new double[msize];
				_fserp_imag = new double[msize];
				_resarray_real = new double[msize];
				_resarray_imag = new double[msize];
				_chirpfactors_real = new double[arrsize];
				_chirpfactors_imag = new double[arrsize];

				PreCompute_ChirpFactors(); // Precompute the factors for An: Exp(sign * I * Pi * i^2/N)
				Precompute_Fouriertransformed_ChirpFactorsConjugate(); // Pre-compute fserp using Pre-computed chirp-factors
			}
Пример #32
0
        // One dimensional Discrete Fourier Transform
        public static void DFT(Complex[] data, FourierDirection direction)
        {
            int    n = data.Length;
            double arg, cos, sin;

            Complex[] dst = new Complex[n];

            // for each destination element
            for (int i = 0; i < n; i++)
            {
                dst[i] = Complex.Zero;

                arg = -(int)direction * 2.0 * System.Math.PI * (double)i / (double)n;

                // sum source elements
                for (int j = 0; j < n; j++)
                {
                    cos = System.Math.Cos(j * arg);
                    sin = System.Math.Sin(j * arg);

                    dst[i].Re += (float)(data[j].Re * cos - data[j].Im * sin);
                    dst[i].Im += (float)(data[j].Re * sin + data[j].Im * cos);
                }
            }

            // copy elements
            if (direction == FourierDirection.Forward)
            {
                // devide also for forward transform
                for (int i = 0; i < n; i++)
                {
                    data[i].Re = dst[i].Re / n;
                    data[i].Im = dst[i].Im / n;
                }
            }
            else
            {
                for (int i = 0; i < n; i++)
                {
                    data[i].Re = dst[i].Re;
                    data[i].Im = dst[i].Im;
                }
            }
        }
Пример #33
0
        // One dimensional Discrete Fourier Transform
        public static void DFT( Complex[] data, FourierDirection direction )
        {
            int			n = data.Length;
            double		arg, cos, sin;
            Complex[]	dst = new Complex[n];

            // for each destination element
            for ( int i = 0; i < n; i++ )
            {
                dst[i] = Complex.Zero;

                arg = - (int) direction * 2.0 * System.Math.PI * (double) i / (double) n;

                // sum source elements
                for ( int j = 0; j < n; j++ )
                {
                    cos = System.Math.Cos( j * arg );
                    sin = System.Math.Sin( j * arg );

                    dst[i].Re += (float) ( data[j].Re * cos - data[j].Im * sin );
                    dst[i].Im += (float) ( data[j].Re * sin + data[j].Im * cos );
                }
            }

            // copy elements
            if ( direction == FourierDirection.Forward )
            {
                // devide also for forward transform
                for ( int i = 0; i < n; i++ )
                {
                    data[i].Re = dst[i].Re / n;
                    data[i].Im = dst[i].Im / n;
                }
            }
            else
            {
                for ( int i = 0; i < n; i++ )
                {
                    data[i].Re = dst[i].Re;
                    data[i].Im = dst[i].Im;
                }
            }
        }
Пример #34
0
    /// <summary>
    /// Compute a 2D fast fourier transform on a data set of complex numbers
    /// </summary>
    /// <param name="data"></param>
    /// <param name="xLength"></param>
    /// <param name="yLength"></param>
    /// <param name="direction"></param>
    public static void      FFT2(Complex[] data, int xLength, int yLength, FourierDirection direction)
    {
        if (data == null)
        {
            throw new ArgumentNullException("data");
        }
        if (data.Length < xLength * yLength)
        {
            throw new ArgumentOutOfRangeException("data.Length", data.Length, "must be at least as large as 'xLength * yLength' parameter");
        }
        if (Fourier.IsPowerOf2(xLength) == false)
        {
            throw new ArgumentOutOfRangeException("xLength", xLength, "must be a power of 2");
        }
        if (Fourier.IsPowerOf2(yLength) == false)
        {
            throw new ArgumentOutOfRangeException("yLength", yLength, "must be a power of 2");
        }

        int xInc = 1;
        int yInc = xLength;

        if (xLength > 1)
        {
            Fourier.SyncLookupTableLength(xLength);
            for (int y = 0; y < yLength; y++)
            {
                int xStart = y * yInc;
                Fourier.LinearFFT_Quick(data, xStart, xInc, xLength, direction);
            }
        }

        if (yLength > 1)
        {
            Fourier.SyncLookupTableLength(yLength);
            for (int x = 0; x < xLength; x++)
            {
                int yStart = x * xInc;
                Fourier.LinearFFT_Quick(data, yStart, yInc, yLength, direction);
            }
        }
    }
Пример #35
0
    private static void LinearFFT(float[] data, int start, int inc, int length, FourierDirection direction)
    {
        float[] buffer = null;
        LockBufferF(length * 2, ref buffer);
        int num = start;

        for (int i = 0; i < length * 2; i++)
        {
            buffer[i] = data[num];
            num      += inc;
        }
        FFT(buffer, length, direction);
        num = start;
        for (int j = 0; j < length; j++)
        {
            data[num] = buffer[j];
            num      += inc;
        }
        UnlockBufferF(ref buffer);
    }
Пример #36
0
    public static void FFT2(float[] data, int xLength, int yLength, FourierDirection direction)
    {
        if (data == null)
        {
            throw new ArgumentNullException("data");
        }
        if (data.Length < xLength * yLength * 2)
        {
            throw new ArgumentOutOfRangeException("data.Length", data.Length, "must be at least as large as 'xLength * yLength * 2' parameter");
        }
        if (!IsPowerOf2(xLength))
        {
            throw new ArgumentOutOfRangeException("xLength", xLength, "must be a power of 2");
        }
        if (!IsPowerOf2(yLength))
        {
            throw new ArgumentOutOfRangeException("yLength", yLength, "must be a power of 2");
        }
        int num = 1;

        if (xLength > 1)
        {
            SyncLookupTableLength(xLength);
            for (int i = 0; i < yLength; i++)
            {
                int start = i * xLength;
                LinearFFT_Quick(data, start, num, xLength, direction);
            }
        }
        if (yLength > 1)
        {
            SyncLookupTableLength(yLength);
            for (int j = 0; j < xLength; j++)
            {
                int start2 = j * num;
                LinearFFT_Quick(data, start2, xLength, yLength, direction);
            }
        }
    }
Пример #37
0
        public static void FFT(Complex[] data, FourierDirection direction)
        {
            int length = data.Length;
            int num2   = Tools.Log2(length);

            ReorderData(data);
            int num3 = 1;

            for (int i = 1; i <= num2; i++)
            {
                Complex[] complexRotation = GetComplexRotation(i, direction);
                int       num4            = num3;
                num3 = num3 << 1;
                for (int j = 0; j < num4; j++)
                {
                    Complex complex = complexRotation[j];
                    for (int k = j; k < length; k += num3)
                    {
                        int     index    = k + num4;
                        Complex complex2 = data[k];
                        Complex complex3 = data[index];
                        float   num9     = (complex3.Re * complex.Re) - (complex3.Im * complex.Im);
                        float   num10    = (complex3.Re * complex.Im) + (complex3.Im * complex.Re);
                        data[k].Re    += num9;
                        data[k].Im    += num10;
                        data[index].Re = complex2.Re - num9;
                        data[index].Im = complex2.Im - num10;
                    }
                }
            }
            if (direction == FourierDirection.Forward)
            {
                for (int m = 0; m < length; m++)
                {
                    data[m].Re /= (float)length;
                    data[m].Im /= (float)length;
                }
            }
        }
Пример #38
0
    /// <summary>
    /// 傅里叶转换
    /// </summary>
    /// <param name="data"></param>
    /// <param name="length"></param>
    /// <param name="direction"></param>
    public static void FFT(float[] data, int length, FourierDirection direction)
    {
        SyncLookupTableLength(length);
        int num = Log2(length);

        ReorderArray(data);
        int num2 = 1;
        int num3 = ((direction != FourierDirection.Forward) ? 1 : 0);

        for (int i = 1; i <= num; i++)
        {
            int num4 = num2;
            num2 <<= 1;
            float[] array  = _uRLookupF[i, num3];
            float[] array2 = _uILookupF[i, num3];
            for (int j = 0; j < num4; j++)
            {
                float num5 = array[j];
                float num6 = array2[j];
                for (int k = j; k < length; k += num2)
                {
                    int   num7  = k << 1;
                    int   num8  = k + num4 << 1;
                    float num9  = data[num8];
                    float num10 = data[num8 + 1];
                    float num11 = num9 * num5 - num10 * num6;
                    float num12 = num9 * num6 + num10 * num5;
                    num9           = data[num7];
                    num10          = data[num7 + 1];
                    data[num7]     = num9 + num11;
                    data[num7 + 1] = num10 + num12;
                    data[num8]     = num9 - num11;
                    data[num8 + 1] = num10 - num12;
                }
            }
        }
    }
Пример #39
0
        /// <summary>
        /// Compute a 1D fast Fourier transform of a dataset of complex numbers.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="length"></param>
        /// <param name="direction"></param>
        public static void FFT_Quick( Complex[] data, int length, FourierDirection direction )
        {
            /*if( data == null ) {
                throw new ArgumentNullException( "data" );
            }
            if( data.Length < length ) {
                throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
            }
            if( Fourier.IsPowerOf2( length ) == false ) {
                throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
            }

            Fourier.SyncLookupTableLength( length );   */

            int ln = Fourier.Log2( length );

            // reorder array
            Fourier.ReorderArray( data );

            // successive doubling
            int N = 1;
            int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;

            for( int level = 1; level <= ln; level ++ ) {
                int M = N;
                N <<= 1;

                double[] uRLookup = _uRLookup[ level, signIndex ];
                double[] uILookup = _uILookup[ level, signIndex ];

                for( int j = 0; j < M; j ++ ) {
                    double uR = uRLookup[j];
                    double uI = uILookup[j];

                    for( int even = j; even < length; even += N ) {
                        int odd	 = even + M;

                        double	r = data[ odd ].Re;
                        double	i = data[ odd ].Im;

                        double	odduR = r * uR - i * uI;
                        double	odduI = r * uI + i * uR;

                        r = data[ even ].Re;
                        i = data[ even ].Im;

                        data[ even ].Re	= r + odduR;
                        data[ even ].Im	= i + odduI;

                        data[ odd ].Re	= r - odduR;
                        data[ odd ].Im	= i - odduI;
                    }
                }
            }
        }
Пример #40
0
        // Two dimensional Fast Fourier Transform
        public static void FFT2( Complex[,] data, FourierDirection 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( );
            }

            // 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];
            }
        }
Пример #41
0
        // Two dimensional Discrete Fourier Transform
        public static void DFT2( Complex[,] data, FourierDirection direction )
        {
            int			n = data.GetLength( 0 );	// rows
            int			m = data.GetLength( 1 );	// columns
            double		arg, cos, sin;
            Complex[]	dst = new Complex[System.Math.Max( n, m )];

            // process rows
            for ( int i = 0; i < n; i++ )
            {
                for ( int j = 0; j < m; j++ )
                {
                    dst[j] = Complex.Zero;

                    arg = - (int) direction * 2.0 * System.Math.PI * (double) j / (double) m;

                    // sum source elements
                    for ( int k = 0; k < m; k++ )
                    {
                        cos = System.Math.Cos( k * arg );
                        sin = System.Math.Sin( k * arg );

                        dst[j].Re += (float) ( data[i, k].Re * cos - data[i, k].Im * sin );
                        dst[j].Im += (float) ( data[i, k].Re * sin + data[i, k].Im * cos );
                    }
                }

                // copy elements
                if ( direction == FourierDirection.Forward )
                {
                    // devide also for forward transform
                    for ( int j = 0; j < m; j++ )
                    {
                        data[i, j].Re = dst[j].Re / m;
                        data[i, j].Im = dst[j].Im / m;
                    }
                }
                else
                {
                    for ( int j = 0; j < m; j++ )
                    {
                        data[i, j].Re = dst[j].Re;
                        data[i, j].Im = dst[j].Im;
                    }
                }
            }

            // process columns
            for ( int j = 0; j < m; j++ )
            {
                for ( int i = 0; i < n; i++ )
                {
                    dst[i] = Complex.Zero;

                    arg = - (int) direction * 2.0 * System.Math.PI * (double) i / (double) n;

                    // sum source elements
                    for ( int k = 0; k < n; k++ )
                    {
                        cos = System.Math.Cos( k * arg );
                        sin = System.Math.Sin( k * arg );

                        dst[i].Re += (float) ( data[k, j].Re * cos - data[k, j].Im * sin );
                        dst[i].Im += (float) ( data[k, j].Re * sin + data[k, j].Im * cos );
                    }
                }

                // copy elements
                if ( direction == FourierDirection.Forward )
                {
                    // devide also for forward transform
                    for ( int i = 0; i < n; i++ )
                    {
                        data[i, j].Re = dst[i].Re / n;
                        data[i, j].Im = dst[i].Im / n;
                    }
                }
                else
                {
                    for ( int i = 0; i < n; i++ )
                    {
                        data[i, j].Re = dst[i].Re;
                        data[i, j].Im = dst[i].Im;
                    }
                }
            }
        }
        /// <summary>
        /// Voert een 2 dimensionale Fourier analyse uit op een afbeelding
        /// </summary>
        /// <param name="invoer">De complexe waarden van de afbeelding</param>
        /// <param name="dir">FourierDirection.Forward or FourierDirection.Backward</param>
        /// <returns>Fourier resultset</returns>
        private static ComplexGetal[,] FFT2D(ComplexGetal[,] invoer, FourierDirection dir)
        {
            float[] reëel = new float[invoer.GetLength(1)];
            float[] imaginair = new float[invoer.GetLength(1)];
            ComplexGetal[,] resultaat = invoer;

            //rijen
            for (int i = 0; i < invoer.GetLength(0); i++) {
                // Plaats de waarden in een 1 dimensionale array
                for (int j = 0; j < invoer.GetLength(1); j++) {
                    reëel[j] = invoer[i, j].Reëel;
                    imaginair[j] = invoer[i, j].Imaginair;
                }

                // Voer een 1 dimensionale fourier analyse uit op de huidige rij
                FFT1D(dir, reëel, imaginair);

                // Plaats de waarden in het resultaat object
                for (int j = 0; j < resultaat.GetLength(1); j++) {
                    resultaat[i, j].Reëel = reëel[j];
                    resultaat[i, j].Imaginair = imaginair[j];
                }
            }

            //kolommen - gebruik nu het resultaat object, anders gaan de berekeningen van de rijen verloren
            for (int i = 0; i < resultaat.GetLength(1); i++) {
                // Plaats de waarden in een 1 dimensionale array
                for (int j = 0; j < resultaat.GetLength(0); j++) {
                    reëel[j] = resultaat[j, i].Reëel;
                    imaginair[j] = resultaat[j, i].Imaginair;
                }

                // Voer een 1 dimensionale fourier analyse uit op de huidige kolom
                FFT1D(dir, reëel, imaginair);

                // Plaats de waarden in het resultaat object
                for (int j = 0; j < resultaat.GetLength(0); j++) {
                    resultaat[j, i].Reëel = reëel[j];
                    resultaat[j, i].Imaginair = imaginair[j];
                }
            }

            return resultaat;
        }
Пример #43
0
		public static void FFT2(Complex[,] data, FourierDirection direction) {
			int length = data.GetLength(0);
			int x = data.GetLength(1);
			if (((!Tools.IsPowerOf2(length) || !Tools.IsPowerOf2(x)) || ((length < 2) || (length > 0x4000))) || ((x < 2) || (x > 0x4000))) {
				throw new ArgumentException();
			}
			Complex[] complexArray = new Complex[x];
			for (int i = 0; i < length; i++) {
				for (int k = 0; k < x; k++) {
					complexArray[k] = data[i, k];
				}
				FFT(complexArray, direction);
				for (int m = 0; m < x; m++) {
					data[i, m] = complexArray[m];
				}
			}
			Complex[] complexArray2 = new Complex[length];
			for (int j = 0; j < x; j++) {
				for (int n = 0; n < length; n++) {
					complexArray2[n] = data[n, j];
				}
				FFT(complexArray2, direction);
				for (int num8 = 0; num8 < length; num8++) {
					data[num8, j] = complexArray2[num8];
				}
			}
		}
Пример #44
0
		private static Complex[] GetComplexRotation(int numberOfBits, FourierDirection direction) {
			int num = (direction == FourierDirection.Forward) ? 0 : 1;
			if (complexRotation[numberOfBits - 1, num] == null) {
				int num2 = ((int)1) << (numberOfBits - 1);
				float re = 1f;
				float im = 0f;
				double d = (3.1415926535897931 / ((double)num2)) * ((double)direction);
				float num6 = (float)Math.Cos(d);
				float num7 = (float)Math.Sin(d);
				Complex[] complexArray = new Complex[num2];
				for (int i = 0; i < num2; i++) {
					complexArray[i] = new Complex(re, im);
					float num8 = (re * num7) + (im * num6);
					re = (re * num6) - (im * num7);
					im = num8;
				}
				complexRotation[numberOfBits - 1, num] = complexArray;
			}
			return complexRotation[numberOfBits - 1, num];
		}
        /// <summary>
        /// This function computes an in-place complex-to-complex FFT
        ///    x and y are the real and imaginary arrays of 2^m points.
        ///    Both arrays must have equal size and must be a power of 2. 
        ///    dir = 1 gives forward transform
        ///    dir = -1 gives reverse transform
        ///    Formula: forward
        ///             N-1
        ///              ---
        ///            1 \         - j k 2 pi n / N
        ///    X(K) = --- > x(n) e                  = Forward transform
        ///            N /                            n=0..N-1
        ///              ---
        ///             n=0
        ///    Formula: reverse
        ///             N-1
        ///             ---
        ///             \          j k 2 pi n / N
        ///    X(n) =    > x(k) e                  = Inverse transform
        ///             /                             k=0..N-1
        ///             ---
        ///             k=0
        /// The result is found in the arrays x and y. 
        /// </summary>
        /// <param name="dir">FourierDirection.Forward or FourierDirection.Backward</param>
        /// <param name="x">real values</param>
        /// <param name="y">imaginary values</param>
        private static void FFT1D(FourierDirection dir, float[] x, float[] y)
        {
            long nn, i, i1, j, k, i2, l, l1, l2;
            float c1, c2, tx, ty, t1, t2, u1, u2, z;

            if (x.Length != y.Length)
                throw new FormatException("Real values and imaginary values arrays lengths do not match");

            int m = (int)Math.Log(x.Length, 2);
            if (m != Math.Log(x.Length, 2))
                throw new FormatException("Data arrays lenght is no power of two");

            /* Calculate the number of points */
            nn = 1;
            for (i = 0; i < m; i++)
                nn *= 2;
            /* Do the bit reversal */
            i2 = nn >> 1;
            j = 0;
            for (i = 0; i < nn - 1; i++)
            {
                if (i < j)
                {
                    tx = x[i];
                    ty = y[i];
                    x[i] = x[j];
                    y[i] = y[j];
                    x[j] = tx;
                    y[j] = ty;
                }
                k = i2;
                while (k <= j)
                {
                    j -= k;
                    k >>= 1;
                }
                j += k;
            }
            /* Compute the FFT */
            c1 = -1f;
            c2 = 0f;
            l2 = 1;
            for (l = 0; l < m; l++)
            {
                l1 = l2;
                l2 <<= 1;
                u1 = 1;
                u2 = 0;
                for (j = 0; j < l1; j++)
                {
                    for (i = j; i < nn; i += l2)
                    {
                        i1 = i + l1;
                        t1 = u1 * x[i1] - u2 * y[i1];
                        t2 = u1 * y[i1] + u2 * x[i1];
                        x[i1] = x[i] - t1;
                        y[i1] = y[i] - t2;
                        x[i] += t1;
                        y[i] += t2;
                    }
                    z = u1 * c1 - u2 * c2;
                    u2 = u1 * c2 + u2 * c1;
                    u1 = z;
                }
                c2 = (float)Math.Sqrt((1f - c1) / 2f);
                if (dir == FourierDirection.Forward)
                    c2 = -c2;
                c1 = (float)Math.Sqrt((1f + c1) / 2f);
            }
            /* Scaling for forward transform */
            if (dir == FourierDirection.Forward)
            {
                for (i = 0; i < nn; i++)
                {
                    x[i] /= nn;
                    y[i] /= nn;

                }
            }
        }
		/// <summary>
		/// Compute a 2D fast fourier transform on a data set of complex numbers
		/// </summary>
		/// <param name="data"></param>
		/// <param name="xLength"></param>
		/// <param name="yLength"></param>
		/// <param name="direction"></param>
		public static void	FFT2( ComplexF[] data, int xLength, int yLength, FourierDirection direction ) {

		int xInc = 1;
			int yInc = xLength;

			if( xLength > 1 ) {
				SyncLookupTableLength( xLength );
				for( int y = 0; y < yLength; y ++ ) {
					int xStart = y * yInc;
					LinearFFT_Quick( data, xStart, xInc, xLength, direction );
				}
			}
		
			if( yLength > 1 ) {
				SyncLookupTableLength( yLength );
				for( int x = 0; x < xLength; x ++ ) {
					int yStart = x * xInc;
					LinearFFT_Quick( data, yStart, yInc, yLength, direction );
				}
			}
		}
Пример #47
0
        /// <summary>
        /// Compute a 1D real-symmetric fast fourier transform.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="length"></param>
        /// <param name="direction"></param>
        public static void RFFT( float[] data, int length, FourierDirection direction )
        {
            if( data == null ) {
                throw new ArgumentNullException( "data" );
            }
            if( data.Length < length ) {
                throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
            }
            if( Fourier.IsPowerOf2( length ) == false ) {
                throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
            }

            float	c1 = 0.5f, c2;
            float	theta	= (float) Math.PI / (length/2);

            if( direction == FourierDirection.Forward ) {
                c2 = -0.5f;
                FFT( data, length/2, direction );
            }
            else {
                c2 = 0.5f;
                theta = - theta;
            }

            float	wtemp = (float) Math.Sin( 0.5*theta );
            float	wpr = -2 * wtemp*wtemp;
            float	wpi	=(float)  Math.Sin( theta );
            float	wr	= 1 + wpr;
            float	wi	= wpi;

            // do / undo packing
            for( int i = 1; i < length/4; i ++ ) {
                int a = 2*i;
                int b = length - 2*i;
                float	h1r	= c1 * ( data[ a ] + data[ b ] );
                float	h1i	= c1 * ( data[ a+1 ] - data[ b+1 ] );
                float	h2r	= -c2 * ( data[ a+1 ] + data[ b+1 ] );
                float	h2i	= c2 * ( data[ a ] - data[ b ] );
                data[ a ]	= h1r + wr*h2r - wi*h2i;
                data[ a+1 ]	= h1i + wr*h2i + wi*h2r;
                data[ b ]	= h1r - wr*h2r + wi*h2i;
                data[ b+1 ]	= -h1i + wr*h2i + wi*h2r;
                wr = (wtemp = wr) * wpr - wi * wpi + wr;
                wi = wi * wpr + wtemp * wpi + wi;
            }

            if( direction == FourierDirection.Forward ) {
                float  hir = data[0];
                data[0] = hir + data[1];
                data[1] = hir - data[1];
            }
            else {
                float  hir = data[0];
                data[0] = c1 * ( hir + data[1] );
                data[1] = c1 * ( hir - data[1] );
                Fourier.FFT( data, length/2, direction );
            }
        }
Пример #48
0
        // Get rotation of complex number
        private static Complex[] GetComplexRotation( int numberOfBits, FourierDirection direction )
        {
            int		directionIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;

            // check if the array is already calculated
            if ( complexRotation[numberOfBits - 1, directionIndex] == null )
            {
                int			n = 1 << (numberOfBits - 1);
                float		uR = 1.0f;
                float		uI = 0.0f;
                double		angle = System.Math.PI / n * (int) direction;
                float		wR = (float) System.Math.Cos( angle );
                float		wI = (float) System.Math.Sin( angle );
                float		t;
                Complex[]	rotation = new Complex[n];

                for ( int i = 0; i < n; i++ )
                {
                    rotation[i] = new Complex(uR, uI);
                    t = uR * wI + uI * wR;
                    uR = uR * wR - uI * wI;
                    uI = t;
                }

                complexRotation[numberOfBits - 1, directionIndex] = rotation;
            }
            return complexRotation[numberOfBits - 1, directionIndex];
        }
Пример #49
0
        private static void LinearFFT_Quick( float[] data, int start, int inc, int length, FourierDirection direction )
        {
            /*Debug.Assert( data != null );
            Debug.Assert( start >= 0 );
            Debug.Assert( inc >= 1 );
            Debug.Assert( length >= 1 );
            Debug.Assert( ( start + inc * ( length - 1 ) ) * 2 < data.Length );*/

            // copy to buffer
            float[]	buffer = null;
            LockBufferF( length * 2, ref buffer );
            int j = start;
            for( int i = 0; i < length * 2; i ++ ) {
                buffer[ i ] = data[ j ];
                j += inc;
            }

            FFT_Quick( buffer, length, direction );

            // copy from buffer
            j = start;
            for( int i = 0; i < length; i ++ ) {
                data[ j ] = buffer[ i ];
                j += inc;
            }
            UnlockBufferF( ref buffer );
        }
Пример #50
0
    /// <summary>
    /// Convolves or deconvolves a real-valued data set data[] (including any
    /// user supplied zero padding) with a response function response[].
    /// The result is returned in the array result[]. All arrays including
    /// the scratch[] array must have the same dimensions (or larger).
    /// The data set (and of course the other arrays) can be either one-dimensional,
    /// two-dimensional, or three-dimensional, d = 1,2,3.  Each dimension must be 
    /// of the form n = (2**p) * (3**q) * (5**r), because of the underlying FFT.
    /// The d-dimensional data can be either single precision (FLOAT := float) 
    /// or double precision (FLOAT := double).    /// </summary>
    /// <param name="data">
    ///The real-valued data set. Note, that you have to
    ///                           care for end effects by zero padding. This means, 
    ///                           that you have to pad the data with a number of zeros
    ///                           on one end equal to the maximal positive duration
    ///                           or maximal negative duration of the response function,
    ///                           whichever is larger!!   /// </param>
    /// <param name="response">
    ///  The response function must be stored in wrap-around
    ///  order. This means that the first half of the array
    ///  response[] (in each dimension) contains the impulse
    ///  response function at positive times, while the second
    ///  half of the array contains the impulse response
    ///  function at negative times, counting down from the
    ///  element with the highest index. The array must have 
    ///  at least the size of the data array.
    /// </param>
    /// <param name="result">
    /// The result array. It must have 
    /// at least the size of the data array.
    /// </param>
    /// <param name="scratch">
    ///  A work array. If a NULL pointer is passed the
    /// work array is allocated and freed auotomatically.
    /// If the array is given by the user it must have 
    /// at least the size of the data array.
    /// </param>
    /// <param name="isign">
    /// If isign == forward a convolution is performed. 
    /// If isign == inverse then a deconvolution is performed.
    /// </param>
    /// <returns>
    /// In the case of a convolution (isign == forward) the value "true" is returned
    /// always. In the case of deconvolution (isign == inverse) the value "false" is
    /// returned if the FFT transform of the response function is exactly zero for 
    /// some value. This indicates that the original convolution has lost all 
    /// information at this particular frequency, so that a reconstruction is not
    /// possible. If the transform of the response function is non-zero everywhere
    /// the deconvolution can be performed and the value "true" is returned.
    ///</returns>
    ///<remarks>
    /// Implementation notes
    /// --------------------
    /// The FFT of the real-valued data array and the real-valued response array is
    /// calculated in one step. This is done by regarding the two arrays
    /// as the real part and the imaginary part of one complex-valued array.
    /// 
    /// Possible improvements
    /// ---------------------
    /// * When doing the backtransform only a real transform is necessary.
    ///   The upper half of the result/scratch arrays is redundant.
    ///   (comment: "symmetry"). This should be used to speed-up the backtransform.
    ///
    /// * 2D and 3D versions are not yet available !!!
    ///</remarks>
    public bool Convolute (double[] data, double[] response, double[] result, double[] scratch, FourierDirection isign)
    {
      // return status
      bool status = true;

      // get total size of data array
      int size = 0;
      if (ndim == 0) 
      {
        throw new ArithmeticException("MpConvolution::Convolute no dimensions have been specified");
      } 
      else if (ndim == 1) 
      {
        size = dim[0];
      } 
      else if (ndim == 2) 
      {
        size = row_order ? (dim[0] * id) : (id * dim[1]);
      } 
      else if (ndim == 3) 
      {
        size = row_order ? (dim[0] * dim[1] * id) : (id * dim[1] * dim[2]);
      }

      // allocate the scratch array
      //bool auto_scratch = false;
      if ( null==scratch ) 
      {
        scratch = new  double[size];
        //auto_scratch = true;
      }

      //---------------------------------------------------------------------------//
      //  1-dimensional convolution (original data not are overwritten)
      //---------------------------------------------------------------------------//

      if (ndim == 1) 
      {

        // First copy the arrays data and response to result and scratch,
        // respectively, to prevent overwriting of the original data.
        Array.Copy(data,result,size);
        Array.Copy(response,scratch, size);

        // transform both arrays simultaneously - this is a forward FFT
        base.FFT(result,scratch, FourierDirection.Forward);
    
        // multiply FFTs to convolve
        int n = dim[0], n2 = n/2;

        if (isign == FourierDirection.Forward) 
        {
      
          double scale = 0.25/n;
          result[0] *= scratch[0] / n;
          scratch[0] = 0;
          for (int i = 1; i <= n2; i++) 
          {
            double rr = result[i]  + result[n-i], 
              ri = result[i]  - result[n-i], 
              sr = scratch[i] + scratch[n-i],
              si = scratch[i] - scratch[n-i];
            result[i]  = scale * (rr*sr + ri*si);   // real part
            scratch[i] = scale * (si*sr - ri*rr);   // imaginary part 
            result[n-i]  = result[i];     // symmetry
            scratch[n-i] = -scratch[i];       // symmetry
          }
      
        } 
        else /* isign == inverse */ 
        {

          double mag;
          if ((mag = Square(scratch[0])) == 0.0) 
          {   // check for zero divide
            status = false;
            goto ErrorExit;
          }
          result[0] *= scratch[0] / mag / n;
          scratch[0] = 0;
          for (int i = 1; i <= n2; i++) 
          {
            double rr = result[i] + result[n-i], 
              ri = result[i] - result[n-i], 
              sr = scratch[i] + scratch[n-i],
              si = scratch[i] - scratch[n-i];
            if ((mag = sr*sr + ri*ri) == 0.0)  
            {   // check for zero divide
              status = false;
              goto ErrorExit;
            }
            result[i]  =  (rr*sr - ri*si) / (n*mag);  // real part
            scratch[i] =  (si*sr + ri*rr) / (n*mag);  // imaginary part 
            result[n-i]  = result[i];     // symmetry
            scratch[n-i] = -scratch[i];       // symmetry
          }
        }

        // transform back - this is an inverse FFT
        base.FFT(result,scratch, FourierDirection.Inverse);

        //---------------------------------------------------------------------------//
        //  2-dimensional convolution
        //---------------------------------------------------------------------------//

      } 
      else if (ndim == 2) 
      {
    
        int n = dim[0],
          m = dim[1];

        // set imaginary parts to zero
        FillZero(result);  // imaginary part of data
        FillZero(scratch); // imaginary part of response

        // transform both arrays - this is a forward FFT
        base.FFT(data,result, FourierDirection.Forward);
        base.FFT(response,scratch,FourierDirection.Forward);

        if (isign == FourierDirection.Forward) 
        { 
          double scale = 1.0/n/m;
          for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) 
            {
              int l = row_order ? i*id+j : j*id+i;
              // do complex multiplication with three real multiplications
              // (a+ib)(c+id) = ( ac-bd ) + i( (a+b)(c+d)-ac-bd )
              double ac = data[l]*response[l],
                bd = result[l]*scratch[l];
              scratch[l] = scale*((data[l]+result[l])*(response[l]+scratch[l])-ac-bd);
              result[l]  = scale*(ac-bd);
            }
        } 
        else /* isign == inverse */ 
        {
          double mag, scale = 1.0/n/m;
          for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) 
            {
              int l = row_order ? i*id+j : j*id+i;
              // do complex division (a+ib)/(c+id) = 
              // (a+ib)(c-id)/(cc+dd) = [(ac+bd) + i((a+b)(c-d)-ac+bd)]/(cc+dd)
              if ((mag = Square(response[l])+Square(scratch[l])) == 0.0) 
              {
                status = false;
                goto ErrorExit;
              }
              mag = scale/mag;
              double ac = data[l]*response[l],
                bd = result[l]*scratch[l];
              scratch[l] = mag*((data[l]+result[l])*(response[l]-scratch[l])-ac+bd);
              result[l]  = mag*(ac+bd);
            }
        } 

        // transform back - this is an inverse FFT
        base.FFT(result,scratch,FourierDirection.Inverse);

        //---------------------------------------------------------------------------//
        //  3-dimensional convolution
        //---------------------------------------------------------------------------//

      } 
      else if (ndim == 3) 
      {

        int n = dim[0],
          m = dim[1],
          p = dim[2];

        // set imaginary parts to zero
        FillZero(result);  // imaginary part of data
        FillZero(scratch); // imaginary part of response

        // transform both arrays - this is a forward FFT
        base.FFT(data,result,FourierDirection.Forward);
        base.FFT(response,scratch,FourierDirection.Forward);

        if (isign == FourierDirection.Forward) 
        {
          double scale = 1.0/n/m/p;
          for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) 
              for (int k = 0;  k < p; k++) 
              {
                int l = row_order ? (i*m+j)*id+k : (k*m+j)*id+i;
                // do complex multiplication with three real multiplications
                // (a+ib)(c+id) = ( ac-bd ) + i( (a+b)(c+d)-ac-bd )
                double ac = data[l]*response[l],
                  bd = result[l]*scratch[l];
                scratch[l] = scale*((data[l]+result[l])*(response[l]+scratch[l])-ac-bd);
                result[l]  = scale*(ac-bd);
              }
        } 
        else /* isign == inverse */ 
        {
          double mag, scale = 1.0/n/m/p;
          for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) 
              for (int k = 0;  k < p; k++) 
              {
                int l = row_order ? (i*m+j)*id+k : (k*m+j)*id+i;
                // do complex division (a+ib)/(c+id) = 
                // (a+ib)(c-id)/(cc+dd) = [(ac+bd) + i((a+b)(c-d)-ac+bd)]/(cc+dd)
                if ((mag = Square(response[l])+Square(scratch[l])) == 0.0) 
                {
                  status = false;
                  goto ErrorExit;
                }
                mag = scale/mag;
                double ac = data[l]*response[l],
                  bd = result[l]*scratch[l];
                scratch[l] = mag*((data[l]+result[l])*(response[l]-scratch[l])-ac+bd);
                result[l]  = mag*(ac+bd);
              } 
        }

        // transform back - this is an inverse FFT
        base.FFT(result,scratch,FourierDirection.Inverse);
      }

      ErrorExit:
  
          
        return status;
    }
Пример #51
0
    /// <summary>
    /// Convolves or deconvolves a splitted complex-valued data set data[] (including any
    /// user supplied zero padding) with a response function response[].
    /// The result is returned in the splitted complex arrays resultre[] and resultim[]. All arrays including
    /// the scratch[] arrays must have the same dimensions (or larger).
    /// The data set (and of course the other arrays) can be either one-dimensional,
    /// two-dimensional, or three-dimensional, d = 1,2,3.  Each dimension must be 
    /// of the form n = (2**p) * (3**q) * (5**r), because of the underlying FFT.
    /// </summary>
    /// <param name="datare">
    /// The splitted complex-valued data set. Note, that you have to
    /// care for end effects by zero padding. This means, 
    /// that you have to pad the data with a number of zeros
    /// on one end equal to the maximal positive duration
    /// or maximal negative duration of the response function,
    /// whichever is larger!!</param>
    /// <param name="dataim">The imaginary part of the data array.</param>
    /// <param name="responsere">
    ///  The response function must be stored in wrap-around
    ///  order. This means that the first half of the array
    ///  response[] (in each dimension) contains the impulse
    ///  response function at positive times, while the second
    ///  half of the array contains the impulse response
    ///  function at negative times, counting down from the
    ///  element with the highest index. The array must have 
    ///  at least the size of the data array.
    /// </param>
    /// <param name="responseim">The imaginary part of the response array.</param>
    /// <param name="resultre">
    /// The real part of the result array. It must have 
    /// at least the size of the data array.
    /// </param>
    /// <param name="resultim">The imaginary part of the result array.</param>
    /// <param name="scratchre">
    ///  A work array. If a NULL pointer is passed the
    /// work array is allocated and freed auotomatically.
    /// If the array is given by the user it must have 
    /// at least the size of the data array.
    /// </param>
    /// <param name="scratchim">
    ///  A work array. If a NULL pointer is passed the
    /// work array is allocated and freed auotomatically.
    /// If the array is given by the user it must have 
    /// at least the size of the data array.
    /// </param>
    /// <param name="isign">
    /// If isign == forward a convolution is performed. 
    /// If isign == inverse then a deconvolution is performed.
    /// </param>
    /// <returns>
    /// In the case of a convolution (isign == forward) the value "true" is returned
    /// always. In the case of deconvolution (isign == inverse) the value "false" is
    /// returned if the FFT transform of the response function is exactly zero for 
    /// some value. This indicates that the original convolution has lost all 
    /// information at this particular frequency, so that a reconstruction is not
    /// possible. If the transform of the response function is non-zero everywhere
    /// the deconvolution can be performed and the value "true" is returned.
    /// </returns>
 
    public bool Convolute (
      double[] datare, double[] dataim, 
      double[] responsere, double[] responseim,
      double[] resultre, double[] resultim,
      double[] scratchre, double[] scratchim,
      FourierDirection isign)
    {
      // return status
      bool status = true;

      // get total size of data array
      int size = 0;
      if (ndim == 0) 
      {
        throw new ArithmeticException("Convolute: no dimensions have been specified");
      } 
      else if (ndim == 1) 
      {
        size = dim[0];
      } 
      else if (ndim == 2) 
      {
        size = row_order ? (dim[0] * id) : (id * dim[1]);
      } 
      else if (ndim == 3) 
      {
        size = row_order ? (dim[0] * dim[1] * id) : (id * dim[1] * dim[2]);
      }

      // allocate the scratch array
      //bool auto_scratch = false;
      if ( null==scratchre )
        scratchre = new  double[size];
      if ( null==scratchim )
        scratchim = new  double[size];

      //---------------------------------------------------------------------------//
      //  1-dimensional convolution (original data not are overwritten)
      //---------------------------------------------------------------------------//

      if (ndim == 1) 
      {

        // First copy the arrays data and response to result and scratch,
        // respectively, to prevent overwriting of the original data.
        Array.Copy(datare,resultre,size);
        Array.Copy(dataim,resultim,size);
        Array.Copy(responsere,scratchre, size);
        Array.Copy(responseim,scratchim, size);

        // transform both arrays simultaneously - this is a forward FFT
        base.FFT(resultre,resultim, FourierDirection.Forward);
        base.FFT(scratchre,scratchim, FourierDirection.Forward);
    
        // multiply FFTs to convolve
        int n = dim[0];

        if (isign == FourierDirection.Forward) 
        {
      
          double scale = 1.0/n;
          for (int i = 0; i < n; i++) 
          {
            double re = resultre[i]*scratchre[i] - resultim[i]*scratchim[i];
            double im = resultre[i]*scratchim[i] + resultim[i]*scratchre[i];
            resultre[i] = re*scale; 
            resultim[i] = im*scale;
          }
        } 
        else /* isign == inverse */ 
        {

          double mag;
          if ((mag = Square(scratchre[0])+Square(scratchim[0])) == 0.0) 
          {   // check for zero divide
            status = false;
            goto ErrorExit;
          }
          for (int i = 0; i < n; i++) 
          {
            double rr = resultre[i]; 
            double ri = resultim[i]; 
            double sr = scratchre[i];
            double si = scratchim[i];
            if ((mag = sr*sr + ri*ri) == 0.0)  
            {   // check for zero divide
              status = false;
              goto ErrorExit;
            }
            resultre[i] =  (rr*sr - ri*si) / (n*mag);  // real part
            resultim[i] =  (si*sr + ri*rr) / (n*mag);  // imaginary part 
          }
        }
        // transform back - this is an inverse FFT
        base.FFT(resultre,resultim, FourierDirection.Inverse);
      }
      else
      {
        throw new NotImplementedException("Sorry, convolution of dimension 2 or 3 is not implemented yet. Will you do it?");
      }

      ErrorExit:
        return status;
    }
Пример #52
0
		public static void FFT(Complex[] data, FourierDirection direction) {
			int length = data.Length;
			int num2 = Tools.Log2(length);
			ReorderData(data);
			int num3 = 1;
			for (int i = 1; i <= num2; i++) {
				Complex[] complexRotation = GetComplexRotation(i, direction);
				int num4 = num3;
				num3 = num3 << 1;
				for (int j = 0; j < num4; j++) {
					Complex complex = complexRotation[j];
					for (int k = j; k < length; k += num3) {
						int index = k + num4;
						Complex complex2 = data[k];
						Complex complex3 = data[index];
						float num9 = (complex3.Re * complex.Re) - (complex3.Im * complex.Im);
						float num10 = (complex3.Re * complex.Im) + (complex3.Im * complex.Re);
						data[k].Re += num9;
						data[k].Im += num10;
						data[index].Re = complex2.Re - num9;
						data[index].Im = complex2.Im - num10;
					}
				}
			}
			if (direction == FourierDirection.Forward) {
				for (int m = 0; m < length; m++) {
					data[m].Re /= (float)length;
					data[m].Im /= (float)length;
				}
			}
		}
Пример #53
0
        /// <summary>
        /// Compute a 3D fast fourier transform on a data set of complex numbers
        /// </summary>
        /// <param name="data"></param>
        /// <param name="xLength"></param>
        /// <param name="yLength"></param>
        /// <param name="zLength"></param>
        /// <param name="direction"></param>
        public static void FFT3( Complex[] data, int xLength, int yLength, int zLength, FourierDirection direction )
        {
            if( data == null ) {
                throw new ArgumentNullException( "data" );
            }
            if( data.Length < xLength*yLength*zLength ) {
                throw new ArgumentOutOfRangeException( "data.Length", data.Length, "must be at least as large as 'xLength * yLength * zLength' parameter" );
            }
            if( Fourier.IsPowerOf2( xLength ) == false ) {
                throw new ArgumentOutOfRangeException( "xLength", xLength, "must be a power of 2" );
            }
            if( Fourier.IsPowerOf2( yLength ) == false ) {
                throw new ArgumentOutOfRangeException( "yLength", yLength, "must be a power of 2" );
            }
            if( Fourier.IsPowerOf2( zLength ) == false ) {
                throw new ArgumentOutOfRangeException( "zLength", zLength, "must be a power of 2" );
            }

            int xInc = 1;
            int yInc = xLength;
            int zInc = xLength * yLength;

            if( xLength > 1 ) {
                Fourier.SyncLookupTableLength( xLength );
                for( int z = 0; z < zLength; z ++ ) {
                    for( int y = 0; y < yLength; y ++ ) {
                        int xStart = y * yInc + z * zInc;
                        Fourier.LinearFFT_Quick( data, xStart, xInc, xLength, direction );
                    }
                }
            }

            if( yLength > 1 ) {
                Fourier.SyncLookupTableLength( yLength );
                for( int z = 0; z < zLength; z ++ ) {
                    for( int x = 0; x < xLength; x ++ ) {
                        int yStart = z * zInc + x * xInc;
                        Fourier.LinearFFT_Quick( data, yStart, yInc, yLength, direction );
                    }
                }
            }

            if( zLength > 1 ) {
                Fourier.SyncLookupTableLength( zLength );
                for( int y = 0; y < yLength; y ++ ) {
                    for( int x = 0; x < xLength; x ++ ) {
                        int zStart = y * yInc + x * xInc;
                        Fourier.LinearFFT_Quick( data, zStart, zInc, zLength, direction );
                    }
                }
            }
        }
		private static void	LinearFFT_Quick( ComplexF[] data, int start, int inc, int length, FourierDirection direction ) {
			
			// copy to buffer
			ComplexF[]	buffer = null;
			LockBufferCF( length, ref buffer );
			int j = start;
			for( int i = 0; i < length; i ++ ) {
				buffer[ i ] = data[ j ];
				j += inc;
			}

			FFT( buffer, length, direction );

			// copy from buffer
			j = start;
			for( int i = 0; i < length; i ++ ) {
				data[ j ] = buffer[ i ];
				j += inc;
			}
			UnlockBufferCF( ref buffer );
		}
Пример #55
0
 /// <summary>
 /// Compute a 1D real-symmetric fast fourier transform.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="direction"></param>
 public static void RFFT( float[] data, FourierDirection direction )
 {
     if( data == null ) {
         throw new ArgumentNullException( "data" );
     }
     Fourier.RFFT( data, data.Length, direction );
 }
		//======================================================================================
		 

		/// <summary>
		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
		/// </summary>
		/// <param name="data"></param>
		/// <param name="length"></param>
		/// <param name="direction"></param>
		public static void	FFT( ComplexF[] data, int length, FourierDirection direction ) {

			SyncLookupTableLength( length );

			int ln = Log2( length );
			
			// reorder array
			ReorderArray( data );
			
			// successive doubling
			int N = 1;
			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
			
			for( int level = 1; level <= ln; level ++ ) {
				int M = N;
				N <<= 1;

				float[] uRLookup = _uRLookupF[ level, signIndex ];
				float[] uILookup = _uILookupF[ level, signIndex ];

				for( int j = 0; j < M; j ++ ) {
					float uR = uRLookup[j];
					float uI = uILookup[j];

					for( int even = j; even < length; even += N ) {
						int odd	 = even + M;
						
						float	r = data[ odd ].Re;
						float	i = data[ odd ].Im;

						float	odduR = r * uR - i * uI;
						float	odduI = r * uI + i * uR;

						r = data[ even ].Re;
						i = data[ even ].Im;
						
						data[ even ].Re	= r + odduR;
						data[ even ].Im	= i + odduI;
						
						data[ odd ].Re	= r - odduR;
						data[ odd ].Im	= i - odduI;
					}
				}
			}

		}
Пример #57
0
        private static void LinearFFT( Complex[] data, int start, int inc, int length, FourierDirection direction )
        {
            Debug.Assert( data != null );
            Debug.Assert( start >= 0 );
            Debug.Assert( inc >= 1 );
            Debug.Assert( length >= 1 );
            Debug.Assert( ( start + inc * ( length - 1 ) ) < data.Length );

            // copy to buffer
            Complex[]	buffer = null;
            LockBufferC( length, ref buffer );
            int j = start;
            for( int i = 0; i < length; i ++ ) {
                buffer[ i ] = data[ j ];
                j += inc;
            }

            FFT( buffer, length, direction );

            // copy from buffer
            j = start;
            for( int i = 0; i < length; i ++ ) {
                data[ j ] = buffer[ i ];
                j += inc;
            }
            UnlockBufferC( ref buffer );
        }
Пример #58
0
 /// <summary>
 /// Compute a 1D fast Fourier transform of a dataset of complex numbers.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="direction"></param>
 public static void FFT( ComplexF[] data, FourierDirection direction )
 {
     if( data == null ) {
         throw new ArgumentNullException( "data" );
     }
     FourierBase.FFT(data, data.Length, direction);
 }
    /// <summary>
    /// Performs a inplace fourier transformation. The original values are overwritten by the fourier transformed values.
    /// </summary>
    /// <param name="arr">The data to transform. On output, the fourier transformed data.</param>
    /// <param name="direction">Specify forward or reverse transformation here.</param>
    public void Transform(double[] arr, FourierDirection direction)
    {
      if(arr.Length!=_numberOfData)
        throw new ArgumentException(string.Format("Length of array arr ({0}) is different from the length specified at construction ({1})",arr.Length,_numberOfData),"arr");

      switch(_method)
      {
        case Method.Trivial:
        {
          if(_numberOfData==2)
          {
            double a0=arr[0],a1=arr[1];
            arr[0]=a0+a1;
            arr[1]=a0-a1;
            
          }
        }
          break;
        case Method.Hartley:
        {
          FastHartleyTransform.RealFFT(arr,direction);
        }
          break;
        case Method.Pfa235:
        {
          NullifyTempArrN1();

          _pfa235.RealFFT(arr,_tempArr1N,direction);
        }
          break;
        case Method.Chirp:
        {
          if(direction==FourierDirection.Forward)
          {
            NullifyTempArrN1();
          }
          else
          {
            if(null==this._tempArr1N)
              _tempArr1N = new double[_numberOfData];

            _tempArr1N[0]=0;
            for(int k=1;k<=_numberOfData/2;k++)
            {
              double sumreal = arr[k];
              double sumimag = arr[_numberOfData-k];

              _tempArr1N[k] = sumimag;
              _tempArr1N[_numberOfData-k] = -sumimag;
              arr[_numberOfData-k] = sumreal;
            }
          }

          ChirpFFT.FFT(arr, _tempArr1N, direction, ref _fftTempStorage);

          if(direction==FourierDirection.Forward)
          {
            for(int k=0;k<=_numberOfData/2;k++)
            {
              double sumreal = arr[k];
              double sumimag = _tempArr1N[k];
              
              if(k!=0 && (k+k)!=_numberOfData)
                arr[_numberOfData-k] = sumimag; 
              arr[k] = sumreal;
            }
          }
        }
          break;
      }
    }
Пример #60
0
        /// <summary>
        /// Compute a 2D fast fourier transform on a data set of complex numbers (represented as pairs of floats)
        /// </summary>
        /// <param name="data"></param>
        /// <param name="xLength"></param>
        /// <param name="yLength"></param>
        /// <param name="direction"></param>
        public static void FFT2( float[] data, int xLength, int yLength, FourierDirection direction )
        {
            if( data == null ) {
                throw new ArgumentNullException( "data" );
            }
            if( data.Length < xLength*yLength*2 ) {
                throw new ArgumentOutOfRangeException( "data.Length", data.Length, "must be at least as large as 'xLength * yLength * 2' parameter" );
            }
            if (Misc.IsPowerOf2(xLength) == false)
            {
                throw new ArgumentOutOfRangeException( "xLength", xLength, "must be a power of 2" );
            }
            if (Misc.IsPowerOf2(yLength) == false)
            {
                throw new ArgumentOutOfRangeException( "yLength", yLength, "must be a power of 2" );
            }

            int xInc = 1;
            int yInc = xLength;

            if( xLength > 1 ) {
                FourierBase.SyncLookupTableLength(xLength);
                for( int y = 0; y < yLength; y ++ ) {
                    int xStart = y * yInc;
                    FourierBase.LinearFFT_Quick(data, xStart, xInc, xLength, direction);
                }
            }

            if( yLength > 1 ) {
                FourierBase.SyncLookupTableLength(yLength);
                for( int x = 0; x < xLength; x ++ ) {
                    int yStart = x * xInc;
                    FourierBase.LinearFFT_Quick(data, yStart, yInc, yLength, direction);
                }
            }
        }