/** * Function: omxSP_FFTInv_CCSToR_F32_Sfs * * Description: * These functions compute the inverse FFT for a conjugate-symmetric input * sequence. Transform length is determined by the specification structure, * which must be initialized prior to calling the FFT function using * <FFTInit_R_F32>. For a transform of length M, the input sequence is * represented using a packed CCS vector of length M+2, and is organized * as follows: * * Index: 0 1 2 3 4 5 . . . M-2 M-1 M M+1 * Comp: R[0] 0 R[1] I[1] R[2] I[2] . . . R[M/2-1] I[M/2-1] R[M/2] 0 * * where R[n] and I[n], respectively, denote the real and imaginary * components for FFT bin n. Bins are numbered from 0 to M/2, where M * is the FFT length. Bin index 0 corresponds to the DC component, * and bin index M/2 corresponds to the foldover frequency. * * Input Arguments: * pSrc - pointer to the complex-valued input sequence represented * using CCS format, of length (2^order) + 2; must be aligned on a * 32-byte boundary. * pFFTSpec - pointer to the preallocated and initialized * specification structure * * Output Arguments: * pDst - pointer to the real-valued output sequence, of length * 2^order ; must be aligned on a 32-byte boundary. * * Return Value: * * OMX_Sts_NoErr - no error * OMX_Sts_BadArgErr - bad arguments if one or more of the * following is true: * - pSrc, pDst, or pFFTSpec is NULL * - pSrc or pDst is not aligned on a 32-byte boundary * */ OMXResult omxSP_FFTInv_CCSToR_F32_Sfs( const OMX_F32* pSrc, OMX_F32* pDst, const OMXFFTSpec_R_F32* pFFTSpec) { ARMsFFTSpec_R_FC32* spec = (ARMsFFTSpec_R_FC32*)pFFTSpec; int order; long subFFTSize; long subFFTNum; OMX_FC32* pTwiddle; OMX_FC32* pOut; OMX_FC32* pComplexSrc; OMX_FC32* pComplexDst = (OMX_FC32*) pDst; /* * Check args are not NULL and the source and destination pointers * are properly aligned. */ if (!validateParametersF32(pSrc, pDst, spec)) return OMX_Sts_BadArgErr; /* * Preprocess the input before calling the complex inverse FFT. The * result is actually stored in the second half of the temp buffer * in pFFTSpec. */ if (spec->N > 1) armSP_FFTInv_CCSToR_F32_preTwiddleRadix2( pSrc, spec->pTwiddle, spec->pBuf, spec->N); /* * Do a complex inverse FFT of half size. */ order = fastlog2(spec->N) - 1; subFFTSize = 1; subFFTNum = spec->N >> 1; pTwiddle = spec->pTwiddle; /* * The pBuf is split in half. The first half is the temp buffer. The * second half holds the source data that was placed there by * armSP_FFTInv_CCSToR_F32_preTwiddleRadix2_unsafe. */ pOut = (OMX_FC32*) spec->pBuf; pComplexSrc = pOut + (1 << order); if (order > 3) { OMX_FC32* argDst; /* * Set up argDst and pOut appropriately so that pOut = pDst for * the very last FFT stage. */ if ((order & 2) == 0) { argDst = pOut; pOut = pComplexDst; } else { argDst = pComplexDst; } /* * Odd order uses a radix 8 first stage; even order, a radix 4 * first stage. */ if (order & 1) { armSP_FFTInv_CToC_FC32_Radix8_fs_OutOfPlace( pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); } else { armSP_FFTInv_CToC_FC32_Radix4_fs_OutOfPlace( pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); } /* * Now use radix 4 stages to finish rest of the FFT */ if (subFFTNum >= 4) { while (subFFTNum > 4) { OMX_FC32* tmp; armSP_FFTInv_CToC_FC32_Radix4_OutOfPlace( argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); /* * Swap argDst and pOut */ tmp = pOut; pOut = argDst; argDst = tmp; } armSP_FFTInv_CToC_FC32_Radix4_ls_OutOfPlace( argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); } } else if (order == 3) { armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( pComplexSrc, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); armSP_FFTInv_CToC_FC32_Radix2_OutOfPlace( pComplexDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace( pOut, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); } else if (order == 2) { armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( pComplexSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace( pOut, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); } else if (order == 1) { armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( pComplexSrc, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); } else { /* Order = 0 */ *pComplexDst = *pComplexSrc; } ScaleRFFTData(pDst, spec->N); return OMX_Sts_NoErr; }
OMXResult omxSP_FFTFwd_RToCCS_F32_Sfs(const OMX_F32* pSrc, OMX_F32* pDst, const OMXFFTSpec_R_F32* pFFTSpec) { ARMsFFTSpec_R_FC32* spec = (ARMsFFTSpec_R_FC32*)pFFTSpec; int order; long subFFTSize; long subFFTNum; OMX_FC32* pTwiddle; OMX_FC32* pOut; OMX_FC32* pComplexSrc = (OMX_FC32*) pSrc; OMX_FC32* pComplexDst = (OMX_FC32*) pDst; /* * Check args are not NULL and the source and destination pointers * are properly aligned. */ if (!validateParametersF32(pSrc, pDst, spec)) return OMX_Sts_BadArgErr; /* * Compute the RFFT using a complex FFT of one less order, so set * order to be the order of the complex FFT. */ order = fastlog2(spec->N) - 1; subFFTSize = 1; subFFTNum = spec->N >> 1; pTwiddle = spec->pTwiddle; pOut = (OMX_FC32*) spec->pBuf; if (order > 3) { OMX_FC32* argDst; OMX_FC32* pComplexDst = (OMX_FC32*) pDst; /* * Set up argDst and pOut appropriately so that pOut = pDst for * ComplexToRealFixup. */ if ((order & 2) != 0) { argDst = pOut; pOut = pComplexDst; } else { argDst = pComplexDst; } /* * Odd order uses a radix 8 first stage; even order, a radix 4 * first stage. */ if (order & 1) { armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace( pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); } else { armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace( pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); } /* * Now use radix 4 stages to finish rest of the FFT */ if (subFFTNum >= 4) { while (subFFTNum > 4) { OMX_FC32* tmp; armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace( argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); /* * Swap argDst and pOut */ tmp = pOut; pOut = argDst; argDst = tmp; } armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace( argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); } } else if (order == 3) { armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( pComplexSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace( pOut, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( pComplexDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); } else if (order == 2) { armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( pComplexSrc, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( pComplexDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); } else if (order == 1) { armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( pComplexSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); } else { /* Handle complex order 0 specially */ pOut->Re = pSrc[0]; pOut->Im = pSrc[1]; } /* * Complex FFT done. Fix up the complex result to give the correct * RFFT. */ ComplexToRealFixup(pOut, pDst, pTwiddle, spec->pBuf, spec->N); return OMX_Sts_NoErr; }