示例#1
0
#pragma warning restore 0414
        //======================================================================================
        //======================================================================================

        /// <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(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;
                    }
                }
            }
        }
示例#2
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 (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);
                }
            }
        }
示例#3
0
        static private void ReorderArray(double[] data)
        {
            Debug.Assert(data != null);

            int length = data.Length / 2;

            Debug.Assert(Fourier.IsPowerOf2(length) == true);
            Debug.Assert(length >= cMinLength);
            Debug.Assert(length <= cMaxLength);

            int[] reversedBits = Fourier.GetReversedBits(Fourier.Log2(length));
            for (int i = 0; i < length; i++)
            {
                int swap = reversedBits[i];
                if (swap > i)
                {
                    Fourier.Swap(ref data[i << 1], ref data[swap << 1]);
                    Fourier.Swap(ref data[i << 1 + 1], ref data[swap << 1 + 1]);
                }
            }
        }
示例#4
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);
            }
        }