FFT(Bluestein和Cooley-Tukey)......开始时的意外高峰

时间:2018-02-06 08:03:31

标签: c# math graph fft dft

前几天我发布了我的FFT测试工具有一些问题,所以这是我的“翻拍”后面几乎相同的问题,但代码不同。

问题: 我正在尝试制作一个工具来读取一些传感器值并执行这些操作。我实现了普通的DFT,FFT(Bluestein)和FFT(Cooley-Tukey)。一切正常,逆变换显示输入应该如此。 唯一的事情就是当我绘制Frequenz / Amplitude图时,我在开始时有一个巨大的峰值(不仅仅是像DC(0Hz)那样的0应该是!)。

对于Bluestein和DFT,我使用complet输入和Cooley-Tukey我用ZeroPadding计算或者只是将输入切换为2 ^ n长度。

例如,这是我的输入,只是一个简单的正弦波。 这里输出的是DFT和Bluetstein(看起来相同)和FFT(ZeroPadding)以及一个DFT zoomed in at 0Hz。 这里是带有八度的相同输入的ouput,这是我期望获得的。

这里我的代码前CT-FFT

            public static void TransformRadix2(Complex[] vector, bool inverse)
        {
            // Length variables
            int n = vector.Length;
            int levels = 0;  // compute levels = floor(log2(n))
            for (int temp = n; temp > 1; temp >>= 1)
                levels++;
            if (1 << levels != n)
                throw new ArgumentException("Length is not a power of 2");

            // Trigonometric table
            Complex[] expTable = new Complex[n / 2];
            double coef = 2 * Math.PI / n * (inverse ? 1 : -1);
            for (int i = 0; i < n / 2; i++)
                expTable[i] = Complex.Exp(new Complex(0, i * coef));

            // Bit-reversed addressing permutation
            for (int i = 0; i < n; i++)
            {
                int j = (int)((uint)ReverseBits(i) >> (32 - levels));
                if (j > i)
                {
                    Complex temp = vector[i];
                    vector[i] = vector[j];
                    vector[j] = temp;
                }
            }

            // Cooley-Tukey decimation-in-time radix-2 FFT
            for (int size = 2; size <= n; size *= 2)
            {
                int halfsize = size / 2;
                int tablestep = n / size;
                for (int i = 0; i < n; i += size)
                {
                    for (int j = i, k = 0; j < i + halfsize; j++, k += tablestep)
                    {
                        Complex temp = vector[j + halfsize] * expTable[k];
                        vector[j + halfsize] = vector[j] - temp;
                        vector[j] += temp;
                    }
                }
                if (size == n)  // Prevent overflow in 'size *= 2'
                    break;
            }
        }

在这里布鲁斯坦。

            public static void TransformBluestein(Complex[] vector, bool inverse)
        {
            // Find a power-of-2 convolution length m such that m >= n * 2 + 1
            int n = vector.Length;
            if (n >= 0x20000000)
                throw new ArgumentException("Array too large");
            int m = 1;
            while (m < n * 2 + 1)
                m *= 2;

            // Trignometric table
            Complex[] expTable = new Complex[n];
            double coef = Math.PI / n * (inverse ? 1 : -1);
            for (int i = 0; i < n; i++)
            {
                int j = (int)((long)i * i % (n * 2));  // This is more accurate than j = i * i
                expTable[i] = Complex.Exp(new Complex(0, j * coef));
            }

            // Temporary vectors and preprocessing
            Complex[] avector = new Complex[m];
            for (int i = 0; i < n; i++)
                avector[i] = vector[i] * expTable[i];
            Complex[] bvector = new Complex[m];
            bvector[0] = expTable[0];
            for (int i = 1; i < n; i++)
                bvector[i] = bvector[m - i] = Complex.Conjugate(expTable[i]);

            // Convolution
            Complex[] cvector = new Complex[m];
            Convolve(avector, bvector, cvector);

            // Postprocessing
            for (int i = 0; i < n; i++)
                vector[i] = cvector[i] * expTable[i];
        }


        /* 
         * Computes the circular convolution of the given complex vectors. Each vector's length must be the same.
         */
        public static void Convolve(Complex[] xvector, Complex[] yvector, Complex[] outvector)
        {
            int n = xvector.Length;
            if (n != yvector.Length || n != outvector.Length)
                throw new ArgumentException("Mismatched lengths");
            xvector = (Complex[])xvector.Clone();
            yvector = (Complex[])yvector.Clone();
            Transform(xvector, false);
            Transform(yvector, false);
            for (int i = 0; i < n; i++)
                xvector[i] *= yvector[i];
            Transform(xvector, true);
            for (int i = 0; i < n; i++)  // Scaling (because this FFT implementation omits it)
                outvector[i] = xvector[i] / n;
        }

        private static int ReverseBits(int val)
        {
            int result = 0;
            for (int i = 0; i < 32; i++, val >>= 1)
                result = (result << 1) | (val & 1);
            return result;
        }

这是每个周期的输入,间隔为0,00001953125。

0
 0.03141
 0.06279
 0.09411
 0.12533
 0.15643
0.18738
 0.21814
 0.24869
 0.27899
 0.30902
 0.33874
 0.36812
 0.39715
 0.42578
 0.45399
 0.48175
 0.50904
 0.53583
0.56208
 0.58779
 0.61291
 0.63742
 0.66131
 0.68455
0.70711
 0.72897
 0.75011
 0.77051
 0.79016
 0.80902
 0.82708
 0.84433
 0.86074
 0.87631
 0.89101
 0.90483
 0.91775
 0.92978
 0.94088
 0.95106
 0.96029
 0.96858
 0.97592
0.98229
 0.98769
 0.99211
 0.99556
 0.99803
 0.99951
1
 0.99951
   0.99803
   0.99556
   0.99211
   0.98769
   0.98229
   0.97592
   0.96858
   0.96029
   0.95106
   0.94088
   0.92978
  0.91775
   0.90483
   0.89101
   0.87631
   0.86074
   0.84433
  0.82708
  0.80902
  0.79016
   0.77051
   0.75011
   0.72897
   0.70711
   0.68455
   0.66131
   0.63742
   0.61291
   0.58779
   0.56208
   0.53583
   0.50904
   0.48175
   0.45399
   0.42578
   0.39715
  0.36812
   0.33874
   0.30902
   0.27899
   0.24869
   0.21814
  0.18738
   0.15643
   0.12533
   0.09411
   0.06279
   0.03141
   0
   -0.03141
   -0.06279
   -0.09411
   -0.12533
   -0.15643
   -0.18738
  -0.21814
   -0.24869
   -0.27899
   -0.30902
   -0.33874
   -0.36812
-0.39715
   -0.42578
   -0.45399
   -0.48175
   -0.50904
   -0.53583
  -0.56208
   -0.58779
   -0.61291
   -0.63742
   -0.66131
   -0.68455
   -0.70711
   -0.72897
   -0.75011
   -0.77051
   -0.79016
   -0.80902
   -0.82708
  -0.84433
   -0.86074
   -0.87631
   -0.89101
   -0.90483
   -0.91775
  -0.92978
   -0.94088
   -0.95106
   -0.96029
   -0.96858
   -0.97592
   -0.98229
   -0.98769
   -0.99211
   -0.99556
   -0.99803
   -0.99951
   -1
  -0.99951
   -0.99803
   -0.99556
   -0.99211
   -0.98769
   -0.98229
  -0.97592
   -0.96858
   -0.96029
   -0.95106
   -0.94088
   -0.92978
  -0.91775
   -0.90483
   -0.89101
   -0.87631
   -0.86074
   -0.84433
   -0.82708
   -0.80902
   -0.79016
   -0.77051
   -0.75011
   -0.72897
   -0.70711
  -0.68455
   -0.66131
   -0.63742
   -0.61291
   -0.58779
   -0.56208
  -0.53583
   -0.50904
   -0.48175
   -0.45399
   -0.42578
   -0.39715
   -0.36812
   -0.33874
   -0.30902
   -0.27899
   -0.24869
   -0.21814
   -0.18738
   -0.15643
   -0.12533
   -0.09411
   -0.06279
   -0.03141
   0

我不知道这个高峰是什么。我唯一可以说的是,当我的间隔越大时,开头的峰值也越大: 区间0,00001953125; 0,0001953125; 0,001953125

以下是我如何创建fft的输入。只是我显示的输入和intervall ....

                    float UsedInterval = float.Parse(Interval.Replace(",", "."), CultureInfo.InvariantCulture);
                float x = 0; //Intervall starting at 0
                foreach (var line in input)
                {
                    if (string.IsNullOrWhiteSpace(line)) continue; //delete empty lines

                    x += UsedInterval;  //add intervall
                    double y = double.Parse(line.Replace(",", "."), CultureInfo.InvariantCulture);

                    arr.Add(new Vector2XY(x, y));
                }

我希望你能帮助我解决我的问题并感谢你的关注。

当我进行256位ZeroPadding FFT时,上面的数据超过一个周期,间隔为0,00001953125 this is my ouput

1 个答案:

答案 0 :(得分:1)

你应该用Sin(coeff*i)填充复数输入的实部,用零纯实数输入虚部,你得到正确的输出而没有大的峰值接近零 - 这是由于当前的线性分量真实的部分。