5

I'm using the Accelerate framework to perform a Fast Fourier Transform (FFT), and am trying to find a way to create a buffer for use with it that has a length of 1024. I have access to the average peak and peak of a signal on which I want to do the FFT.

Can somebody help me or give me some hints to do this?

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
  • 2
    In one of WWDC2010 sessions about Accelerate.Framework they spoke about that. I might be wrong but *probably* there is a sample about that. Either way, you should look at Accelerate.Framework reference, there are very useful functions for doing what you want ;) – nacho4d Jan 26 '11 at 11:45
  • You might want to look at the answers to [this StackOverflow question](http://stackoverflow.com/questions/3398753/using-the-apple-fft-and-accelerate-framework "this stack overflow question"). A number of good examples are provided of using Apple's Accelerate framework to generate an FFT of audio. – rcw3 Jan 26 '11 at 15:02

1 Answers1

11

Apple has some examples of how to set up FFTs in their vDSP Programming Guide. You should also check out the vDSP Examples sample application. While for the Mac, this code should translate directly across to iOS as well.

I recently needed to do a simple FFT of an 64 integer input waveform, for which I used the following code:

static FFTSetupD fft_weights;
static DSPDoubleSplitComplex input;
static double *magnitudes;

+ (void)initialize
{
    /* Setup weights (twiddle factors) */
    fft_weights = vDSP_create_fftsetupD(6, kFFTRadix2);

    /* Allocate memory to store split-complex input and output data */
    input.realp = (double *)malloc(64 * sizeof(double));
    input.imagp = (double *)malloc(64 * sizeof(double));
    magnitudes = (double *)malloc(64 * sizeof(double));
}

- (CGFloat)performAcceleratedFastFourierTransformAndReturnMaximumAmplitudeForArray:(NSUInteger *)waveformArray;
{   
    for (NSUInteger currentInputSampleIndex = 0; currentInputSampleIndex < 64; currentInputSampleIndex++)
    {
        input.realp[currentInputSampleIndex] = (double)waveformArray[currentInputSampleIndex];
        input.imagp[currentInputSampleIndex] = 0.0f;
    }

    /* 1D in-place complex FFT */
    vDSP_fft_zipD(fft_weights, &input, 1, 6, FFT_FORWARD);  

    input.realp[0] = 0.0;
    input.imagp[0] = 0.0;

    // Get magnitudes
    vDSP_zvmagsD(&input, 1, magnitudes, 1, 64);

    // Extract the maximum value and its index
    double fftMax = 0.0;
    vDSP_maxmgvD(magnitudes, 1, &fftMax, 64);

    return sqrt(fftMax);
}

As you can see, I only used the real values in this FFT to set up the input buffers, performed the FFT, and then read out the magnitudes.

Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
  • 1
    Thanks - this is a much simpler example than others I have seen (where they mostly perform an inverse FFT straight after). Very helpful as I could see which are the minimum bits I needed for my problem! – Oliver Mason May 01 '12 at 08:24
  • 1
    You put just wave amplitude indexes to real values. Should imagp be zero? It is not clear for me. Why are you not using CTOZ function? thx – Sergey Kopanev Dec 25 '12 at 13:25
  • @SergeyKopanev He uses a complex to complex fft (and not a real to complex fft). In this case you don't need to arrange the real data since all of them will be stored in the realp array of the `DSPDoubleSplitComplex`. The imaginary array will be empty since the there is no imaginary values. – DEADBEEF Mar 30 '17 at 11:00