void DspRifft::processDspWithIndex(int fromIndex, int toIndex) { #if __APPLE__ DSPSplitComplex inputVector; inputVector.realp = dspBufferAtInlet[0]; inputVector.imagp = dspBufferAtInlet[1]; DSPSplitComplex outputVector; outputVector.realp = dspBufferAtOutlet[0]; outputVector.imagp = (float *) alloca(blockSizeInt*sizeof(float)); // this buffer will not contain any useful data vDSP_fft_zop(fftSetup, &inputVector, 1, &outputVector, 1, log2n, kFFTDirection_Inverse); #endif // __APPLE__ }
void DspRfft::processDspWithIndex(int fromIndex, int toIndex) { #if __APPLE__ DSPSplitComplex inputVector; inputVector.realp = dspBufferAtInlet0; inputVector.imagp = DspObject::zeroBuffer; DSPSplitComplex outputVector; outputVector.realp = dspBufferAtOutlet0; outputVector.imagp = dspBufferAtOutlet[1]; vDSP_fft_zop(fftSetup, &inputVector, 1, &outputVector, 1, log2n, kFFTDirection_Forward); // NOTE(mhroth): vDSP_fft_zop outputs the entire series of symmetric coefficients. // Pd only returns the unique values. The below code makes this object output values in the same // way that Pd does. But since the Apple fft and ifft functions require the symmetric values, // we leave it like this for now. //int halfBlockSize = blockSizeInt >> 1; //memset(dspBufferAtOutlet0+halfBlockSize+1, 0, (halfBlockSize-1) * sizeof(float)); //memset(dspBufferAtOutlet[1]+halfBlockSize, 0, halfBlockSize * sizeof(float)); #endif // __APPLE__ }
/* Demonstrate the complex one-dimensional out-of-place FFT, vDSP_fft_zop. The out-of-place FFT writes results into a different array than the input. */ static void DemonstratevDSP_fft_zop(FFTSetup Setup) { /* Define strides for the arrays be passed to the FFT. In many applications, the strides are one and are passed to the vDSP routine as constants. */ const vDSP_Stride SignalStride = 1, ObservedStride = 1; // Define a variable for a loop iterator. vDSP_Length i; // Define some variables used to time the routine. ClockData t0, t1; double Time; printf("\n\tOne-dimensional complex FFT of %lu elements.\n", (unsigned long) N); // Allocate memory for the arrays. DSPSplitComplex Signal, Observed; Signal.realp = malloc(N * SignalStride * sizeof Signal.realp); Signal.imagp = malloc(N * SignalStride * sizeof Signal.imagp); Observed.realp = malloc(N * ObservedStride * sizeof Observed.realp); Observed.imagp = malloc(N * ObservedStride * sizeof Observed.imagp); if (Signal.realp == NULL || Signal.imagp == NULL || Observed.realp == NULL || Observed.imagp == NULL) { fprintf(stderr, "Error, failed to allocate memory.\n"); exit(EXIT_FAILURE); } /* Generate an input signal. In a real application, data would of course be provided from an image file, sensors, or other source. */ const float Frequency0 = 300, Frequency1 = 450, Frequency2 = 775; const float Phase0 = .3, Phase1 = .45f, Phase2 = .775f; for (i = 0; i < N; ++i) { Signal.realp[i*SignalStride] = cos((i * Frequency0 / N + Phase0) * TwoPi) + cos((i * Frequency1 / N + Phase1) * TwoPi) + cos((i * Frequency2 / N + Phase2) * TwoPi); Signal.imagp[i*SignalStride] = sin((i * Frequency0 / N + Phase0) * TwoPi) + sin((i * Frequency1 / N + Phase1) * TwoPi) + sin((i * Frequency2 / N + Phase2) * TwoPi); } // Perform an FFT. vDSP_fft_zop(Setup, &Signal, SignalStride, &Observed, ObservedStride, Log2N, FFT_FORWARD); /* Prepare expected results based on analytical transformation of the input signal. */ DSPSplitComplex Expected; Expected.realp = malloc(N * sizeof Expected.realp); Expected.imagp = malloc(N * sizeof Expected.imagp); if (Expected.realp == NULL || Expected.imagp == NULL) { fprintf(stderr, "Error, failed to allocate memory.\n"); exit(EXIT_FAILURE); } for (i = 0; i < N/2; ++i) Expected.realp[i] = Expected.imagp[i] = 0; // Add the frequencies in the signal to the expected results. Expected.realp[(int) Frequency0] = N * cos(Phase0 * TwoPi); Expected.imagp[(int) Frequency0] = N * sin(Phase0 * TwoPi); Expected.realp[(int) Frequency1] = N * cos(Phase1 * TwoPi); Expected.imagp[(int) Frequency1] = N * sin(Phase1 * TwoPi); Expected.realp[(int) Frequency2] = N * cos(Phase2 * TwoPi); Expected.imagp[(int) Frequency2] = N * sin(Phase2 * TwoPi); // Compare the observed results to the expected results. CompareComplexVectors(Expected, Observed, N); // Release memory. free(Expected.realp); free(Expected.imagp); /* The above shows how to use the vDSP_fft_zop routine. Now we will see how fast it is. */ // Time vDSP_fft_zop by itself. t0 = Clock(); for (i = 0; i < Iterations; ++i) vDSP_fft_zop(Setup, &Signal, SignalStride, &Observed, ObservedStride, Log2N, FFT_FORWARD); t1 = Clock(); // Average the time over all the loop iterations. Time = ClockToSeconds(t1, t0) / Iterations; printf("\tvDSP_fft_zop on %lu elements takes %g microseconds.\n", (unsigned long) N, Time * 1e6); // Release resources. free(Signal.realp); free(Signal.imagp); free(Observed.realp); free(Observed.imagp); }