예제 #1
0
        /**
         * Initialize class to perform FFT of specified size.
         *
         * @param   logN    Log2 of FFT length. e.g. for 512 pt FFT, logN = 9.
         */
        public void init(
            uint logN)
        {
            m_logN = logN;
            m_N    = (uint)(1 << (int)m_logN);

            // Allocate elements for linked list of complex numbers.
            m_X = new FFTElement[m_N];
            for (uint k = 0; k < m_N; k++)
            {
                m_X[k] = new FFTElement();
            }

            // Set up "next" pointers.
            for (uint k = 0; k < m_N - 1; k++)
            {
                m_X[k].next = m_X[k + 1];
            }

            // Specify target for bit reversal re-ordering.
            for (uint k = 0; k < m_N; k++)
            {
                m_X[k].revTgt = BitReverse(k, logN);
            }
        }
예제 #2
0
    private void InitThread()
    {
        lock (this) {
            uint logN = log;
            m_logN = logN;
            m_N    = (uint)(1 << (int)m_logN);

            // Allocate elements for linked list of complex numbers.
            m_X = new FFTElement[m_N];
            for (uint k = 0; k < m_N; k++)
            {
                m_X[k] = new FFTElement();
            }

            // Set up "next" pointers.
            for (uint k = 0; k < m_N - 1; k++)
            {
                m_X[k].next = m_X[k + 1];
            }

            // Specify target for bit reversal re-ordering.
            for (uint k = 0; k < m_N; k++)
            {
                m_X[k].revTgt = BitReverse(k, logN);
            }
            myInstance = instances;
            instances++;

            //Debug.Log ("done init " + myInstance);
        }
    }
예제 #3
0
        /// <summary>
        /// Initialize the FFT. Must call first and this anytime the FFT setup changes.
        /// </summary>
        /// <param name="inputDataLength"></param>
        /// <param name="zeroPaddingLength"></param>
        public FFT Initialize(UInt32 inputDataLength, UInt32 zeroPaddingLength = 0)
        {
            mN = inputDataLength;

            // Find the power of two for the total FFT size up to 2^32
            bool foundIt = false;

            for (mLogN = 1; mLogN <= 32; mLogN++)
            {
                double n = Math.Pow(2.0, mLogN);
                if ((inputDataLength + zeroPaddingLength) == n)
                {
                    foundIt = true;
                    break;
                }
            }

            if (foundIt == false)
            {
                throw new ArgumentOutOfRangeException("inputDataLength + zeroPaddingLength was not an even power of 2! FFT cannot continue.");
            }

            // Set global parameters.
            mLengthTotal = inputDataLength + zeroPaddingLength;
            mLengthHalf  = (mLengthTotal / 2) + 1;

            // Set the overall scale factor for all the terms
            mFFTScale  = Math.Sqrt(2) / (double)(mLengthTotal);               // Natural FFT Scale Factor  // Window Scale Factor
            mFFTScale *= ((double)mLengthTotal) / (double)inputDataLength;    // Zero Padding Scale Factor

            // Allocate elements for linked list of complex numbers.
            mX = new FFTElement[mLengthTotal];
            for (UInt32 k = 0; k < (mLengthTotal); k++)
            {
                mX[k] = new FFTElement();
            }

            // Set up "next" pointers.
            for (UInt32 k = 0; k < (mLengthTotal) - 1; k++)
            {
                mX[k].next = mX[k + 1];
            }

            // Specify target for bit reversal re-ordering.
            for (UInt32 k = 0; k < (mLengthTotal); k++)
            {
                mX[k].revTgt = DSP.Util.BitReverse(k, mLogN);
            }

            return(this);
        }
예제 #4
0
        public void Initialize(uint inputDataLength, uint zeroPaddingLength = 0)
        {
            mN = inputDataLength;

            bool foundIt = false;

            for (mLogN = 1; mLogN <= 32; mLogN++)
            {
                double n = Math.Pow(2.0, mLogN);
                if ((inputDataLength + zeroPaddingLength) == n)
                {
                    foundIt = true;
                    break;
                }
            }

            if (foundIt == false)
            {
                throw new ArgumentOutOfRangeException("inputDataLength + zeroPaddingLength não foi uma potência igual a 2! A FFT não pode continuar.");
            }

            mLengthTotal = inputDataLength + zeroPaddingLength;
            mLengthHalf  = (mLengthTotal / 2) + 1;

            mFFTScale  = Math.Sqrt(2) / mLengthTotal;
            mFFTScale *= mLengthTotal / (double)inputDataLength;

            mX = new FFTElement[mLengthTotal];
            for (uint k = 0; k < (mLengthTotal); k++)
            {
                mX[k] = new FFTElement();
            }

            for (uint k = 0; k < (mLengthTotal) - 1; k++)
            {
                mX[k].next = mX[k + 1];
            }

            for (uint k = 0; k < (mLengthTotal); k++)
            {
                mX[k].revTgt = BitReverse(k, mLogN);
            }
        }
예제 #5
0
파일: test.cs 프로젝트: puthutp/Waver
        /**
         * Initialize class to perform FFT of specified size.
         *
         * @param	logN	Log2 of FFT length. e.g. for 512 pt FFT, logN = 9.
         */
        public void init(
			uint logN )
        {
            m_logN = logN;
            m_N = (uint)(1 << (int)m_logN);

            // Allocate elements for linked list of complex numbers.
            m_X = new FFTElement[m_N];
            for (uint k = 0; k < m_N; k++)
                m_X[k] = new FFTElement();

            // Set up "next" pointers.
            for (uint k = 0; k < m_N-1; k++)
                m_X[k].next = m_X[k+1];

            // Specify target for bit reversal re-ordering.
            for (uint k = 0; k < m_N; k++ )
                m_X[k].revTgt = BitReverse(k,logN);
        }
예제 #6
0
        public Complex[] Execute(double[] timeSeries)
        {
            uint numFlies   = mLengthTotal >> 1;
            uint span       = mLengthTotal >> 1;
            uint spacing    = mLengthTotal;
            uint wIndexStep = 1;

            FFTElement x = mX[0];
            uint       k = 0;

            for (uint i = 0; i < mN; i++)
            {
                x.re = timeSeries[k];
                x.im = 0.0;
                x    = x.next;
                k++;
            }

            if (mN != mLengthTotal)
            {
                for (uint i = mN; i < mLengthTotal; i++)
                {
                    x.re = 0.0;
                    x.im = 0.0;
                    x    = x.next;
                }
            }

            for (uint stage = 0; stage < mLogN; stage++)
            {
                double wAngleInc = wIndexStep * -2.0 * Math.PI / (mLengthTotal);
                double wMulRe    = Math.Cos(wAngleInc);
                double wMulIm    = Math.Sin(wAngleInc);

                for (uint start = 0; start < (mLengthTotal); start += spacing)
                {
                    FFTElement xTop = mX[start];
                    FFTElement xBot = mX[start + span];

                    double wRe = 1.0;
                    double wIm = 0.0;

                    for (uint flyCount = 0; flyCount < numFlies; ++flyCount)
                    {
                        double xTopRe = xTop.re;
                        double xTopIm = xTop.im;
                        double xBotRe = xBot.re;
                        double xBotIm = xBot.im;

                        xTop.re = xTopRe + xBotRe;
                        xTop.im = xTopIm + xBotIm;

                        xBotRe  = xTopRe - xBotRe;
                        xBotIm  = xTopIm - xBotIm;
                        xBot.re = xBotRe * wRe - xBotIm * wIm;
                        xBot.im = xBotRe * wIm + xBotIm * wRe;

                        xTop = xTop.next;
                        xBot = xBot.next;

                        double tRe = wRe;
                        wRe = wRe * wMulRe - wIm * wMulIm;
                        wIm = tRe * wMulIm + wIm * wMulRe;
                    }
                }

                numFlies   >>= 1;
                span       >>= 1;
                spacing    >>= 1;
                wIndexStep <<= 1;
            }

            x = mX[0];
            Complex[] unswizzle = new Complex[mLengthTotal];
            while (x != null)
            {
                uint target = x.revTgt;
                unswizzle[target] = new Complex(x.re * mFFTScale, x.im * mFFTScale);
                x = x.next;
            }

            Complex[] result = new Complex[mLengthHalf];
            Array.Copy(unswizzle, result, mLengthHalf);

            result[0] = new Complex(result[0].Real / Math.Sqrt(2), 0.0);
            result[mLengthHalf - 1] = new Complex(result[mLengthHalf - 1].Real / Math.Sqrt(2), 0.0);

            return(result);
        }
예제 #7
0
        /**
         * Performs in-place complex FFT.
         *
         * @param   xRe     Real part of input/output - horizontal
         * @param   xIm     Imaginary part of input/output -vertical
         * @param   inverse If true, do an inverse FFT
         */
        public void run(
            double[] xRe,
            double[] xIm,
            bool inverse = false)
        {
            uint numFlies   = m_N >> 1; // Number of butterflies per sub-FFT
            uint span       = m_N >> 1; // Width of the butterfly
            uint spacing    = m_N;      // Distance between start of sub-FFTs
            uint wIndexStep = 1;        // Increment for twiddle table index

            // Copy data into linked complex number objects
            // If it's an IFFT, we divide by N while we're at it
            FFTElement x     = m_X[0];
            uint       k     = 0;
            double     scale = inverse ? 1.0 / m_N : 1.0;

            while (x != null)
            {
                x.re = scale * xRe[k];
                x.im = scale * xIm[k];
                x    = x.next;
                k++;
            }

            // For each stage of the FFT
            for (uint stage = 0; stage < m_logN; stage++)
            {
                // Compute a multiplier factor for the "twiddle factors".
                // The twiddle factors are complex unit vectors spaced at
                // regular angular intervals. The angle by which the twiddle
                // factor advances depends on the FFT stage. In many FFT
                // implementations the twiddle factors are cached, but because
                // array lookup is relatively slow in C#, it's just
                // as fast to compute them on the fly.
                double wAngleInc = wIndexStep * 2.0 * Math.PI / m_N;
                if (inverse == false)
                {
                    wAngleInc *= -1;
                }
                double wMulRe = Math.Cos(wAngleInc);
                double wMulIm = Math.Sin(wAngleInc);

                for (uint start = 0; start < m_N; start += spacing)
                {
                    FFTElement xTop = m_X[start];
                    FFTElement xBot = m_X[start + span];

                    double wRe = 1.0;
                    double wIm = 0.0;

                    // For each butterfly in this stage
                    for (uint flyCount = 0; flyCount < numFlies; ++flyCount)
                    {
                        // Get the top & bottom values
                        double xTopRe = xTop.re;
                        double xTopIm = xTop.im;
                        double xBotRe = xBot.re;
                        double xBotIm = xBot.im;

                        // Top branch of butterfly has addition
                        xTop.re = xTopRe + xBotRe;
                        xTop.im = xTopIm + xBotIm;

                        // Bottom branch of butterly has subtraction,
                        // followed by multiplication by twiddle factor
                        xBotRe  = xTopRe - xBotRe;
                        xBotIm  = xTopIm - xBotIm;
                        xBot.re = xBotRe * wRe - xBotIm * wIm;
                        xBot.im = xBotRe * wIm + xBotIm * wRe;

                        // Advance butterfly to next top & bottom positions
                        xTop = xTop.next;
                        xBot = xBot.next;

                        // Update the twiddle factor, via complex multiply
                        // by unit vector with the appropriate angle
                        // (wRe + j wIm) = (wRe + j wIm) x (wMulRe + j wMulIm)
                        double tRe = wRe;
                        wRe = wRe * wMulRe - wIm * wMulIm;
                        wIm = tRe * wMulIm + wIm * wMulRe;
                    }
                }

                numFlies   >>= 1; // Divide by 2 by right shift
                span       >>= 1;
                spacing    >>= 1;
                wIndexStep <<= 1;     // Multiply by 2 by left shift
            }

            // The algorithm leaves the result in a scrambled order.
            // Unscramble while copying values from the complex
            // linked list elements back to the input/output vectors.
            x = m_X[0];
            while (x != null)
            {
                uint target = x.revTgt;
                xRe[target] = x.re;
                xIm[target] = x.im;
                x           = x.next;
            }
        }
예제 #8
0
        /// <summary>
        /// Executes a FFT
        /// </summary>
        /// <param name="series"></param>
        /// <returns>Complex[] Spectrum</returns>
        private Complex[] Execute(Complex[] series, bool direct = true)
        {
            UInt32 numFlies   = mLengthTotal >> 1; // Number of butterflies per sub-FFT
            UInt32 span       = mLengthTotal >> 1; // Width of the butterfly
            UInt32 spacing    = mLengthTotal;      // Distance between start of sub-FFTs
            UInt32 wIndexStep = 1;                 // Increment for twiddle table index

            Debug.Assert(series.Length <= mLengthTotal,
                         "The input timeSeries length was greater than the total number of points that was initialized. FFT.Execute()");

            // Copy data into linked complex number objects
            FFTElement x = mX[0];
            UInt32     k = 0;

            for (UInt32 i = 0; i < mN; i++)
            {
                x.re = series[k].Real;
                x.im = series[k].Imaginary;
                x    = x.next;
                k++;
            }

            // If zero padded, clean the 2nd half of the linked list from previous results
            if (mN != mLengthTotal)
            {
                for (UInt32 i = mN; i < mLengthTotal; i++)
                {
                    x.re = 0.0;
                    x.im = 0.0;
                    x    = x.next;
                }
            }

            // For each stage of the FFT
            for (UInt32 stage = 0; stage < mLogN; stage++)
            {
                // Compute a multiplier factor for the "twiddle factors".
                // The twiddle factors are complex unit vectors spaced at
                // regular angular intervals. The angle by which the twiddle
                // factor advances depends on the FFT stage. In many FFT
                // implementations the twiddle factors are cached, but because
                // array lookup is relatively slow in C#, it's just
                // as fast to compute them on the fly.
                double wAngleInc = wIndexStep * -2.0 * Math.PI / (mLengthTotal);
                double wMulRe    = Math.Cos(wAngleInc);
                double wMulIm    = Math.Sin(wAngleInc);

                for (UInt32 start = 0; start < (mLengthTotal); start += spacing)
                {
                    FFTElement xTop = mX[start];
                    FFTElement xBot = mX[start + span];

                    double wRe = 1.0;
                    double wIm = 0.0;

                    // For each butterfly in this stage
                    for (UInt32 flyCount = 0; flyCount < numFlies; ++flyCount)
                    {
                        // Get the top & bottom values
                        double xTopRe = xTop.re;
                        double xTopIm = xTop.im;
                        double xBotRe = xBot.re;
                        double xBotIm = xBot.im;

                        // Top branch of butterfly has addition
                        xTop.re = xTopRe + xBotRe;
                        xTop.im = xTopIm + xBotIm;

                        // Bottom branch of butterfly has subtraction,
                        // followed by multiplication by twiddle factor
                        xBotRe  = xTopRe - xBotRe;
                        xBotIm  = xTopIm - xBotIm;
                        xBot.re = xBotRe * wRe - xBotIm * wIm;
                        xBot.im = xBotRe * wIm + xBotIm * wRe;

                        // Advance butterfly to next top & bottom positions
                        xTop = xTop.next;
                        xBot = xBot.next;

                        // Update the twiddle factor, via complex multiply
                        // by unit vector with the appropriate angle
                        // (wRe + j wIm) = (wRe + j wIm) x (wMulRe + j wMulIm)
                        double tRe = wRe;
                        wRe = wRe * wMulRe - wIm * wMulIm;
                        wIm = tRe * wMulIm + wIm * wMulRe;
                    }
                }

                numFlies   >>= 1; // Divide by 2 by right shift
                span       >>= 1;
                spacing    >>= 1;
                wIndexStep <<= 1;     // Multiply by 2 by left shift
            }

            // The algorithm leaves the result in a scrambled order.
            // Unscramble while copying values from the complex
            // linked list elements to a complex output vector & properly apply scale factors.

            x = mX[0];
            Complex[] unswizzle = new Complex[mLengthTotal];
            while (x != null)
            {
                UInt32 target = x.revTgt;
                unswizzle[target] = direct ?
                                    new Complex(x.re * mFFTScale, x.im * mFFTScale) :
                                    new Complex(x.im, x.re);
                x = x.next;
            }

            Complex[] result = new Complex[mLengthTotal];
            Array.Copy(unswizzle, result, mLengthTotal);

            if (direct)
            {
                // DC and Fs/2 Points are scaled differently, since they have only a real part
                result[0] = new Complex(result[0].Real / Math.Sqrt(2), 0.0);
                result[mLengthHalf - 1] = new Complex(result[mLengthHalf - 1].Real / Math.Sqrt(2), 0.0);
            }
            else
            {
                result = result.Multiply(1 / System.Math.Sqrt(2));
            }

            return(result);
        }