C#中的逆FFT

时间:2015-11-12 16:52:49

标签: c# fft ifft

我正在编写程序性音频文件的应用程序,我必须分析我的新文件,获取其频谱并在其计算中更改它。

我想用快速傅立叶变换(FFT)来做到这一点。这是我的递归C#FFT:

void ft(float n, ref Complex[] f)
{
    if (n > 1)
    {
        Complex[] g = new Complex[(int) n / 2];
        Complex[] u = new Complex[(int) n / 2];

        for (int i = 0; i < n / 2; i++)
        {
            g[i] = f[i * 2];
            u[i] = f[i * 2 + 1];
        }

        ft(n / 2, ref g);
        ft(n / 2, ref u);

        for (int i = 0; i < n / 2; i++)
        {
            float a = i;
            a = -2.0f * Mathf.PI * a / n;
            float cos = Mathf.Cos(a);
            float sin = Mathf.Sin(a);
            Complex c1 = new Complex(cos, sin);
            c1 = Complex.Multiply(u[i], c1);
            f[i] = Complex.Add(g[i], c1);

            f[i + (int) n / 2] = Complex.Subtract(g[i], c1);
        }
    }
}

鼓舞人心的例子是from wiki

然后我将结果与来自wolframalpha的结果进行了比较,输入相同0.6,0.7,0.8,0.9,但结果不一样。我的结果是Wolfram的两倍,虚部是Wolfram的-2倍。

此外,wiki表示可以使用

计算FFT的倒数

this

但我比较输入和输出,它们是不同的。

有谁知道什么是错的?

1 个答案:

答案 0 :(得分:2)

不同的实现通常使用离散傅立叶变换(DFT)的不同定义,并且具有相应的不同结果。实现之间的对应关系通常相当简单(例如缩放因子)。

更具体地说,您的实现基于以下DFT定义:

OP's DFT definition

另一方面,默认情况下,Wolfram alpha使用a definition,在调整为基于0的索引后,它看起来像:

Wolfram alpha default DFT definition

相应地,可以将您的实现结果转换为匹配Wolfram alpha&:#/ p>

void toWolframAlphaDefinition(ref Complex[] f)
{
  float scaling = (float)(1.0/Math.Sqrt(f.Length));
  for (int i = 0; i < f.Length; i++)
  {
    f[i] = scaling * Complex.Conjugate(f[i]);
  }
}

现在,使用正向变换计算逆DFT,直接实现公式

OP's inverse formula

你提供的将是:

void inverseFt(ref Complex[] f)
{
  for (int i = 0; i < f.Length; i++)
  {
    f[i] = Complex.Conjugate(f[i]);
  }
  ft(f.Length, ref f);
  float scaling = (float)(1.0 / f.Length);
  for (int i = 0; i < f.Length; i++)
  {
    f[i] = scaling * Complex.Conjugate(f[i]);
  }
}

在原始序列ft上调用0.6, 0.7, 0.8, 0.9可以获得转换后的序列3, -0.2+0.2j, -0.2, -0.2-0.2j

此变换序列的进一步调用inverseFt应该会返回到原始序列0.6, 0.7, 0.8, 0.9(在一些合理的浮点错误内),如this live demo所示。