我没有太多的数学背景,但我的工作项目的一部分,需要一个载体的FFT。 MATLAB函数FFT(x)的作品准确地为我所需要的,但试图建立的加速框架FFT功能后,我得到完全准确的结果。 如果任何人有加速框架FFT更多的专业知识/经验,我真的可以使用一些帮助,试图找出什么我做错了。 我根据我的FFT建立过一个例子,我在谷歌发现,但有迹象表明产生不同的结果没有教程或任何东西。
EDIT1:围绕基于答案为止一些东西改变。 这似乎是做计算,但它不以任何方式接近MATLAB的输出
这是FFT的MATLAB的文档: http://www.mathworks.com/help/techdoc/ref/fft.html
**注:为了举例的目的,在x数组将{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}在这两个例子
MATLAB代码:
x = fft(x)
Matlab的输出:
x =
1.0e+02 *
Columns 1 through 4
1.3600 -0.0800 + 0.4022i -0.0800 + 0.1931i -0.0800 + 0.1197i
Columns 5 through 8
-0.0800 + 0.0800i -0.0800 + 0.0535i -0.0800 + 0.0331i -0.0800 + 0.0159i
Columns 9 through 12
-0.0800 -0.0800 - 0.0159i -0.0800 - 0.0331i -0.0800 - 0.0535i
Columns 13 through 16
-0.0800 - 0.0800i -0.0800 - 0.1197i -0.0800 - 0.1931i -0.0800 - 0.4022i
苹果加速架构: http://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html#//apple_ref/doc/uid/TP40009464
目标C代码:
int log2n = log2f(16);
FFTSetupD fftSetup = vDSP_create_fftsetupD (log2n, kFFTRadix2);
DSPDoubleSplitComplex fft_data;
fft_data.realp = (double *)malloc(8 * sizeof(double));
fft_data.imagp = (double *)malloc(8 * sizeof(double));
vDSP_ctoz((COMPLEX *) ffx, 2, &fft_data, 1, nOver2); //split data (1- 16) into odds and evens
vDSP_fft_zrip (fftSetup, &fft_data, 1, log2n, kFFTDirection_Forward); //fft forward
vDSP_fft_zrip (fftSetup, &fft_data, 1, log2n, kFFTDirection_Inverse); //fft inverse
vDSP_ztoc(&fft_data, 2, (COMPLEX *) ffx, 1, nOver2); //combine complex back into real numbers
Objective C的输出:
FFX现在包含:
272.000000
-16.000000
-16.000000
-16.000000
0.000000
0.000000
0.000000
0.000000
0.000000
10.000000
11.000000
12.000000
13.000000
14.000000
15.000000
16.000000
一个大问题:C数组索引从0,不同于MATLAB阵列,其是基于1的。 所以,你需要你的循环从改变
for(int i = 1; i <= 16; i++)
至
for(int i = 0; i < 16; i++)
第二,大问题-你混合单精度( float
)和双精度( double
)例程。 您的数据是double
所以你应该使用vDSP_ctozD
,不vDSP_ctoz
和vDSP_fft_zripD
而不是vDSP_fft_zrip
等。
另一件要注意:不同的FFT实现使用DFT公式的不同定义,特别是关于缩放因子。 它看起来像MATLAB FFT包括一个1 / N缩放校正,其中大部分其它的FFT没有。
这是一个完整的工作示例,其输出匹配倍频(MATLAB克隆):
#include <stdio.h>
#include <stdlib.h>
#include <Accelerate/Accelerate.h>
int main(void)
{
const int log2n = 4;
const int n = 1 << log2n;
const int nOver2 = n / 2;
FFTSetupD fftSetup = vDSP_create_fftsetupD (log2n, kFFTRadix2);
double *input;
DSPDoubleSplitComplex fft_data;
int i;
input = malloc(n * sizeof(double));
fft_data.realp = malloc(nOver2 * sizeof(double));
fft_data.imagp = malloc(nOver2 * sizeof(double));
for (i = 0; i < n; ++i)
{
input[i] = (double)(i + 1);
}
printf("Input\n");
for (i = 0; i < n; ++i)
{
printf("%d: %8g\n", i, input[i]);
}
vDSP_ctozD((DSPDoubleComplex *)input, 2, &fft_data, 1, nOver2);
printf("FFT Input\n");
for (i = 0; i < nOver2; ++i)
{
printf("%d: %8g%8g\n", i, fft_data.realp[i], fft_data.imagp[i]);
}
vDSP_fft_zripD (fftSetup, &fft_data, 1, log2n, kFFTDirection_Forward);
printf("FFT output\n");
for (i = 0; i < nOver2; ++i)
{
printf("%d: %8g%8g\n", i, fft_data.realp[i], fft_data.imagp[i]);
}
for (i = 0; i < nOver2; ++i)
{
fft_data.realp[i] *= 0.5;
fft_data.imagp[i] *= 0.5;
}
printf("Scaled FFT output\n");
for (i = 0; i < nOver2; ++i)
{
printf("%d: %8g%8g\n", i, fft_data.realp[i], fft_data.imagp[i]);
}
printf("Unpacked output\n");
printf("%d: %8g%8g\n", 0, fft_data.realp[0], 0.0); // DC
for (i = 1; i < nOver2; ++i)
{
printf("%d: %8g%8g\n", i, fft_data.realp[i], fft_data.imagp[i]);
}
printf("%d: %8g%8g\n", nOver2, fft_data.imagp[0], 0.0); // Nyquist
return 0;
}
输出是:
Input
0: 1
1: 2
2: 3
3: 4
4: 5
5: 6
6: 7
7: 8
8: 9
9: 10
10: 11
11: 12
12: 13
13: 14
14: 15
15: 16
FFT Input
0: 1 2
1: 3 4
2: 5 6
3: 7 8
4: 9 10
5: 11 12
6: 13 14
7: 15 16
FFT output
0: 272 -16
1: -16 80.4374
2: -16 38.6274
3: -16 23.9457
4: -16 16
5: -16 10.6909
6: -16 6.62742
7: -16 3.1826
Scaled FFT output
0: 136 -8
1: -8 40.2187
2: -8 19.3137
3: -8 11.9728
4: -8 8
5: -8 5.34543
6: -8 3.31371
7: -8 1.5913
Unpacked output
0: 136 0
1: -8 40.2187
2: -8 19.3137
3: -8 11.9728
4: -8 8
5: -8 5.34543
6: -8 3.31371
7: -8 1.5913
8: -8 0
与八度比较,我们得到:
octave-3.4.0:15> x = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 ]
x =
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
octave-3.4.0:16> fft(x)
ans =
Columns 1 through 7:
136.0000 + 0.0000i -8.0000 + 40.2187i -8.0000 + 19.3137i -8.0000 + 11.9728i -8.0000 + 8.0000i -8.0000 + 5.3454i -8.0000 + 3.3137i
Columns 8 through 14:
-8.0000 + 1.5913i -8.0000 + 0.0000i -8.0000 - 1.5913i -8.0000 - 3.3137i -8.0000 - 5.3454i -8.0000 - 8.0000i -8.0000 - 11.9728i
Columns 15 and 16:
-8.0000 - 19.3137i -8.0000 - 40.2187i
octave-3.4.0:17>
注意,输出从9到16仅仅是复共轭反射镜的图像或底部8点而言,由于是预期的情况下与真正的输入FFT。
还要注意的是,我们需要通过2倍缩放VDSP FFT - 这是由于这样的事实,这是一个真正的到复杂的FFT,这是基于N / 2点复杂到复杂的FFT,因此输出由N / 2缩放,而正常的FFT将由N.被缩放
我想这也可能是一个数组的包装问题。 我刚才一直在看他们的示例代码,我看他们一直叫转换例程像
vDSP_ctoz
下面是苹果的代码示例链接: http://developer.apple.com/library/ios/#documentation/Performance/Conceptual/vDSP_Programming_Guide/SampleCode/SampleCode.html#//apple_ref/doc/uid/TP40005147-CH205- CIAEJIGF
我不认为它是完整的答案,但我也同意保罗R.
顺便说一句,只是好奇,如果你去Wolfram Alpha的,他们给了FFT {1,2,3,4,5,6,7,8,9,10,11,12,13,14一个完全不同的答案, 15,16}
在MATLAB中,它看起来像你做16个真值的FFT {1 + 0I,2 + 0I,3 + 0I,等等...}而在加速,你正在做的8个复数值{的FFT 1+ 2I,3 + 4I,5 + 6I等...}