FFT 工作正常,但当我想采用 IFFT 时,我总是从其结果中看到相同的图形。结果很复杂,无论原始信号如何,图形始终相同。
在实部图中是一个 -sin,周期 = 帧大小
虚部是同周期的-cos
哪里会出问题?
原始信号:
IFFT 真实值(图片上只有一半帧):
我使用的算法 FFT。
double** FFT(double** f, int s, bool inverse) {
if (s == 1) return f;
int sH = s / 2;
double** fOdd = new double*[sH];
double** fEven = new double*[sH];
for (int i = 0; i < sH; i++) {
int j = 2 * i;
fOdd[i] = f[j];
fEven[i] = f[j + 1];
}
double** sOdd = FFT(fOdd, sH, inverse);
double** sEven = FFT(fEven, sH, inverse);
double**spectr = new double*[s];
double arg = inverse ? DoublePI / s : -DoublePI / s;
double*oBase = new double[2]{ cos(arg),sin(arg) };
double*o = new double[2]{ 1,0 };
for (int i = 0; i < sH; i++) {
double* sO1 = Mul(o, sOdd[i]);
spectr[i] = Sum(sEven[i], sO1);
spectr[i + sH] = Dif(sEven[i], sO1);
o = Mul(o, oBase);
}
return spectr;
}
最佳答案
“蝴蝶”部分错误地应用了系数:
for (int i = 0; i < sH; i++) {
double* sO1 = sOdd[i];
double* sE1 = Mul(o, sEven[i]);
spectr[i] = Sum(sO1, sE1);
spectr[i + sH] = Dif(sO1, sE1);
o = Mul(o, oBase);
}
旁注:
我保留了你的符号,但这让事情变得困惑:
fOdd
有索引 0, 2, 4, 6, ... 所以它应该是 fEven
fEven
有索引 1, 3, 5, 7, ... 所以它应该是 fOdd
真的 sOdd
应该是 sLower
而 sEven
应该是 sUpper
因为它们对应于 0 :s/2
和 s/2:s-1
元素分别为:
sLower = FFT(fEven, sH, inverse); // fEven is 0, 2, 4, ...
sUpper = FFT(fOdd, sH, inverse); // fOdd is 1, 3, 5, ...
然后蝴蝶变成:
for (int i = 0; i < sH; i++) {
double* sL1 = sLower[i];
double* sU1 = Mul(o, sUpper[i]);
spectr[i] = Sum(sL1, sU1);
spectr[i + sH] = Dif(sL1, sU1);
o = Mul(o, oBase);
}
当这样写时,比较容易与 pseudocode example on wikipedia 进行比较.
@Dai 是正确的,你会泄漏大量内存
关于c++ - ifft 结果与原始信号不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44095442/