void AccelerateFFT<double>::performFFT (double* buffer, double* real, double* imag) { vDSP_ctozD ((DOUBLE_COMPLEX*)buffer, 2, &doubleComplexSplit, 1, fftSizeOver2); vDSP_fft_zripD (fftSetupDouble, &doubleComplexSplit, 1, log2n, FFT_FORWARD); doubleComplexSplit.realp[fftSizeOver2] = doubleComplexSplit.imagp[0]; doubleComplexSplit.imagp[fftSizeOver2] = 0.0; doubleComplexSplit.imagp[0] = 0.0; for (size_t i = 0; i <= fftSizeOver2; i++) { doubleComplexSplit.realp[i] *= 0.5; doubleComplexSplit.imagp[i] *= 0.5; } for (size_t i = fftSizeOver2 - 1; i > 0; --i) { doubleComplexSplit.realp[2 * fftSizeOver2 - i] = doubleComplexSplit.realp[i]; doubleComplexSplit.imagp[2 * fftSizeOver2 - i] = -1 * doubleComplexSplit.imagp[i]; } for (size_t i = 0; i < fftSize; i++) { real[i] = doubleComplexSplit.realp[i]; imag[i] = doubleComplexSplit.imagp[i]; } }
void FFTLib_op::ComputeFrame(int N, double *in, double *out) { vDSP_ctozD ((DSPDoubleComplex*) in, 2, &A, 1, N/2 ); vDSP_fft_zripD(SetupReal, &A, 1, Exp, FFT_FORWARD); int i,j; for (i=0; i<N/2; i++) out[i] = A.realp[i]*0.5; out[N/2] = A.imagp[0]*0.5; for (i=1, j=N-1; i<N/2; i++, j--) out[j] = A.imagp[i]*0.5; }
int xtract_spectrum(const double *data, const int N, const void *argv, double *result) { int vector = 0; int withDC = 0; int normalise = 0; double q = 0.0; double temp = 0.0; double max = 0.0; double NxN = XTRACT_SQ(N); double *marker = NULL; double real = 0.0; double imag = 0.0; unsigned int n = 0; unsigned int m = 0; unsigned int M = N >> 1; #ifndef USE_OOURA DSPDoubleSplitComplex *fft = NULL; #endif q = *(double *)argv; vector = (int)*((double *)argv+1); withDC = (int)*((double *)argv+2); normalise = (int)*((double *)argv+3); XTRACT_CHECK_q; #ifdef USE_OOURA if(!ooura_data_spectrum.initialised) #else if(!vdsp_data_spectrum.initialised) #endif { fprintf(stderr, "libxtract: error: xtract_spectrum() failed, " "fft data unitialised.\n"); return XTRACT_NO_RESULT; } #ifdef USE_OOURA /* ooura is in-place * the output format is * a[0] - DC, a[1] - nyquist, a[2...N-1] - remaining bins */ rdft(N, 1, data, ooura_data_spectrum.ooura_ip, ooura_data_spectrum.ooura_w); #else fft = &vdsp_data_spectrum.fft; vDSP_ctozD((DSPDoubleComplex *)data, 2, fft, 1, N >> 1); vDSP_fft_zripD(vdsp_data_spectrum.setup, fft, 1, vdsp_data_spectrum.log2N, FFT_FORWARD); #endif switch(vector) { case XTRACT_LOG_MAGNITUDE_SPECTRUM: for(n = 0, m = 0; m < M; ++n, ++m) { marker = &result[m]; if(n==0 && !withDC) /* discard DC and keep Nyquist */ { ++n; #ifdef USE_OOURA marker = &result[M-1]; #endif } #ifdef USE_OOURA if(n==1 && withDC) /* discard Nyquist */ { ++n; } real = data[n*2]; imag = data[n*2+1]; #else real = fft->realp[n]; imag = fft->realp[n]; #endif temp = XTRACT_SQ(real) + XTRACT_SQ(imag); if (temp > XTRACT_LOG_LIMIT) { temp = log(sqrt(temp) / (double)N); } else { temp = XTRACT_LOG_LIMIT_DB; } result[m] = /* Scaling */ (temp + XTRACT_DB_SCALE_OFFSET) / XTRACT_DB_SCALE_OFFSET; XTRACT_SET_FREQUENCY; XTRACT_GET_MAX; } break; case XTRACT_POWER_SPECTRUM: for(n = 0, m = 0; m < M; ++n, ++m) { marker = &result[m]; if(n==0 && !withDC) /* discard DC and keep Nyquist */ { ++n; #ifdef USE_OOURA marker = &result[M-1]; #endif } #ifdef USE_OOURA if(n==1 && withDC) /* discard Nyquist */ { ++n; } real = data[n*2]; imag = data[n*2+1]; #else real = fft->realp[n]; imag = fft->realp[n]; #endif result[m] = (XTRACT_SQ(real) + XTRACT_SQ(imag)) / NxN; XTRACT_SET_FREQUENCY; XTRACT_GET_MAX; } break; case XTRACT_LOG_POWER_SPECTRUM: for(n = 0, m = 0; m < M; ++n, ++m) { marker = &result[m]; if(n==0 && !withDC) /* discard DC and keep Nyquist */ { ++n; #ifdef USE_OOURA marker = &result[M-1]; #endif } #ifdef USE_OOURA if(n==1 && withDC) /* discard Nyquist */ { ++n; } real = data[n*2]; imag = data[n*2+1]; #else real = fft->realp[n]; imag = fft->realp[n]; #endif if ((temp = XTRACT_SQ(real) + XTRACT_SQ(imag)) > XTRACT_LOG_LIMIT) temp = log(temp / NxN); else temp = XTRACT_LOG_LIMIT_DB; result[m] = (temp + XTRACT_DB_SCALE_OFFSET) / XTRACT_DB_SCALE_OFFSET; XTRACT_SET_FREQUENCY; XTRACT_GET_MAX; } break; default: /* MAGNITUDE_SPECTRUM */ for(n = 0, m = 0; m < M; ++n, ++m) { marker = &result[m]; if(n==0 && !withDC) /* discard DC and keep Nyquist */ { ++n; #ifdef USE_OOURA marker = &result[M-1]; #endif } #ifdef USE_OOURA if(n==1 && withDC) /* discard Nyquist */ { ++n; } real = data[n*2]; imag = data[n*2+1]; #else real = fft->realp[n]; imag = fft->realp[n]; #endif *marker = sqrt(XTRACT_SQ(real) + XTRACT_SQ(imag)) / (double)N; XTRACT_SET_FREQUENCY; XTRACT_GET_MAX; } break; } if(normalise) { for(n = 0; n < M; n++) result[n] /= max; } return XTRACT_SUCCESS; }
int xtract_autocorrelation_fft(const double *data, const int N, const void *argv, double *result) { double *rfft = NULL; int n = 0; int M = 0; #ifndef USE_OOURA DSPDoubleSplitComplex *fft = NULL; double M_double = 0.0; #endif M = N << 1; /* Zero pad the input vector */ rfft = (double *)calloc(M, sizeof(double)); memcpy(rfft, data, N * sizeof(double)); #ifdef USE_OOURA rdft(M, 1, rfft, ooura_data_autocorrelation_fft.ooura_ip, ooura_data_autocorrelation_fft.ooura_w); for(n = 2; n < M; ++n) { rfft[n*2] = XTRACT_SQ(rfft[n*2]) + XTRACT_SQ(rfft[n*2+1]); rfft[n*2+1] = 0.0; } rfft[0] = XTRACT_SQ(rfft[0]); rfft[1] = XTRACT_SQ(rfft[1]); rdft(M, -1, rfft, ooura_data_autocorrelation_fft.ooura_ip, ooura_data_autocorrelation_fft.ooura_w); #else /* vDSP has its own autocorrelation function, but it doesn't fit the * LibXtract model, e.g. we can't guarantee it's going to use * an FFT for all values of N */ fft = &vdsp_data_autocorrelation_fft.fft; vDSP_ctozD((DSPDoubleComplex *)data, 2, fft, 1, N); vDSP_fft_zripD(vdsp_data_autocorrelation_fft.setup, fft, 1, vdsp_data_autocorrelation_fft.log2N, FFT_FORWARD); for(n = 0; n < N; ++n) { fft->realp[n] = XTRACT_SQ(fft->realp[n]) + XTRACT_SQ(fft->imagp[n]); fft->imagp[n] = 0.0; } vDSP_fft_zripD(vdsp_data_autocorrelation_fft.setup, fft, 1, vdsp_data_autocorrelation_fft.log2N, FFT_INVERSE); #endif /* Normalisation factor */ M = M * N; #ifdef USE_OOURA for(n = 0; n < N; n++) result[n] = rfft[n] / (double)M; free(rfft); #else M_double = (double)M; vDSP_ztocD(fft, 1, (DOUBLE_COMPLEX *)result, 2, N); vDSP_vsdivD(result, 1, &M_double, result, 1, N); #endif return XTRACT_SUCCESS; }