2015-11-12 122 views
3

我正在为程序化音频文件编写一个应用程序,我必须分析我的新文件,得到它的频谱并在计算中改变它。C#逆向FFT#

我想用快速傅立叶变换(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倍。

此外,维基表示FFT的逆可以与

this

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

有没有人知道什么是错的?

+1

查找处理FFT的现有库。不太确定您希望从其他人为您调试代码中获得什么。 –

+0

我想要一个有fft经验的人,怎么能解释我如何得到fft的反例,例如使用其他算法,或者这是不可能的。我的代码工作。我尝试使用正弦和余弦输入并获得正确的输出。 –

回答

2

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

更具体地说,你的实现是基于DFT的定义如下:

OP's DFT definition

在另一方面,Wolfram Alpha的默认使用a definition,其调整后从0开始的索引样子:

Wolfram alpha default DFT definition

与此相对应,就可以改变你的执行的结果与匹配Wolfram Alpha的公司:

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]); 
    } 
} 

现在只要使用正变换,直接执行公式

OP's inverse formula

你提供的是计算逆DFT:

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所示。