iPhone FFT with Accelerate framework vDSP

前端 未结 3 1710
臣服心动
臣服心动 2020-12-23 15:49

I\'m having difficulty implementing an FFT using vDSP. I understand the theory but am looking for a specific code example please.

I have data from a wav file as bel

3条回答
  •  旧巷少年郎
    2020-12-23 16:04

    You can check Apple’s documentation and take good care of data packing.

    Here is my example:

    //  main.cpp
    //  FFTTest
    //
    //  Created by Harry-Chris Stamatopoulos on 11/23/12.
    //  
    
    /* 
     This is an example of a hilbert transformer using 
     Apple's VDSP fft/ifft & other VDSP calls.
     Output signal has a PI/2 phase shift.
     COMPLEX_SPLIT vector "B" was used to cross-check
     real and imaginary parts coherence with the original vector "A"
     that is obtained straight from the fft.
     Tested and working. 
     Cheers!
    */
    
    #include 
    #include 
    #define PI 3.14159265
    #define DEBUG_PRINT 1
    
    int main(int argc, const char * argv[])
    {
        float fs = 44100;           //sample rate
        float f0 = 440;             //sine frequency
        uint32_t i = 0;
    
        uint32_t L = 1024;
    
        /* vector allocations*/
        float *input = new float [L];
        float *output = new float[L];
        float *mag = new float[L/2];
        float *phase = new float[L/2];
    
        for (i = 0 ; i < L; i++)
        {
            input[i] = cos(2*PI*f0*i/fs);
        }
    
        uint32_t log2n = log2f((float)L);
        uint32_t n = 1 << log2n;
        //printf("FFT LENGTH = %lu\n", n);
    
        FFTSetup fftSetup;
        COMPLEX_SPLIT A;
        COMPLEX_SPLIT B;
        A.realp = (float*) malloc(sizeof(float) * L/2);
        A.imagp = (float*) malloc(sizeof(float) * L/2);
    
        B.realp = (float*) malloc(sizeof(float) * L/2);
        B.imagp = (float*) malloc(sizeof(float) * L/2);
    
        fftSetup = vDSP_create_fftsetup(log2n, FFT_RADIX2);
    
        /* Carry out a Forward and Inverse FFT transform. */
        vDSP_ctoz((COMPLEX *) input, 2, &A, 1, L/2);
        vDSP_fft_zrip(fftSetup, &A, 1, log2n, FFT_FORWARD);
    
        mag[0] = sqrtf(A.realp[0]*A.realp[0]);
    
        //get phase
        vDSP_zvphas (&A, 1, phase, 1, L/2);
        phase[0] = 0;
    
        //get magnitude;
        for(i = 1; i < L/2; i++){
            mag[i] = sqrtf(A.realp[i]*A.realp[i] + A.imagp[i] * A.imagp[i]);
        }
    
        //after done with possible phase and mag processing re-pack the vectors in VDSP format
        B.realp[0] = mag[0];
        B.imagp[0] = mag[L/2 - 1];;
    
        //unwrap, process & re-wrap phase
        for(i = 1; i < L/2; i++){
            phase[i] -= 2*PI*i * fs/L;
            phase[i] -= PI / 2 ;
            phase[i] += 2*PI*i * fs/L;
        }
    
        //construct real & imaginary part of the output packed vector (input to ifft)
        for(i = 1; i < L/2; i++){
            B.realp[i] = mag[i] * cosf(phase[i]);
            B.imagp[i] = mag[i] * sinf(phase[i]);
        }
    
    #if DEBUG_PRINT
        for (i = 0 ; i < L/2; i++)
        {
           printf("A REAL = %f \t A IMAG = %f \n", A.realp[i], A.imagp[i]);
           printf("B REAL = %f \t B IMAG = %f \n", B.realp[i], B.imagp[i]);
        }
    #endif
        //ifft
        vDSP_fft_zrip(fftSetup, &B, 1, log2n, FFT_INVERSE);
    
        //scale factor
        float scale = (float) 1.0 / (2*L);
    
        //scale values
        vDSP_vsmul(B.realp, 1, &scale, B.realp, 1, L/2);
        vDSP_vsmul(B.imagp, 1, &scale, B.imagp, 1, L/2);
    
        //unpack B to real interleaved output
        vDSP_ztoc(&B, 1, (COMPLEX *) output, 2, L/2);
    
        // print output signal values to console
        printf("Shifted signal x = \n");
        for (i = 0 ; i < L/2; i++)
            printf("%f\n", output[i]);
    
        //release resources
        free(input);
        free(output);
        free(A.realp);
        free(A.imagp);
        free(B.imagp);
        free(B.realp);
        free(mag);
        free(phase);
    }
    

提交回复
热议问题