iPhone加速框架FFT VS Matlab的FFT(iPhone Accelerate Fram

2019-06-24 23:37发布

我没有太多的数学背景,但我的工作项目的一部分,需要一个载体的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

Answer 1:

一个大问题:C数组索引从0,不同于MATLAB阵列,其是基于1的。 所以,你需要你的循环从改变

for(int i = 1; i <= 16; i++)

for(int i = 0; i < 16; i++)

第二,大问题-你混合单精度( float )和双精度( double )例程。 您的数据是double所以你应该使用vDSP_ctozD ,不vDSP_ctozvDSP_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.被缩放



Answer 2:

我想这也可能是一个数组的包装问题。 我刚才一直在看他们的示例代码,我看他们一直叫转换例程像

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}



Answer 3:

在MATLAB中,它看起来像你做16个真值的FFT {1 + 0I,2 + 0I,3 + 0I,等等...}而在加速,你正在做的8个复数值{的FFT 1+ 2I,3 + 4I,5 + 6I等...}



文章来源: iPhone Accelerate Framework FFT vs Matlab FFT