1 /* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "dl/api/omxtypes.h" 12 #include "dl/sp/api/armSP.h" 13 #include "dl/sp/api/omxSP.h" 14 15 extern void armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( 16 const OMX_FC32* pSrc, 17 OMX_FC32* pDst, 18 OMX_FC32* pTwiddle, 19 long* subFFTNum, 20 long* subFFTSize); 21 22 extern void armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( 23 const OMX_FC32* pSrc, 24 OMX_FC32* pDst, 25 OMX_FC32* pTwiddle, 26 long* subFFTNum, 27 long* subFFTSize); 28 29 extern void armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace( 30 const OMX_FC32* pSrc, 31 OMX_FC32* pDst, 32 OMX_FC32* pTwiddle, 33 long* subFFTNum, 34 long* subFFTSize); 35 36 extern void armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace( 37 const OMX_FC32* pSrc, 38 OMX_FC32* pDst, 39 OMX_FC32* pTwiddle, 40 long* subFFTNum, 41 long* subFFTSize); 42 43 extern void armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace( 44 const OMX_FC32* pSrc, 45 OMX_FC32* pDst, 46 OMX_FC32* pTwiddle, 47 long* subFFTNum, 48 long* subFFTSize); 49 50 extern void armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace( 51 const OMX_FC32* pSrc, 52 OMX_FC32* pDst, 53 OMX_FC32* pTwiddle, 54 long* subFFTNum, 55 long* subFFTSize); 56 57 extern void armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace( 58 const OMX_FC32* pSrc, 59 OMX_FC32* pDst, 60 OMX_FC32* pTwiddle, 61 long* subFFTNum, 62 long* subFFTSize); 63 64 extern void ComplexToRealFixup(OMX_FC32* pSrc, 65 OMX_F32* pDst, 66 const OMX_FC32* pTwiddle, 67 OMX_F32* pBuf, 68 long N); 69 70 /** 71 * Function: omxSP_FFTFwd_CToC_FC32_Sfs (2.2.4.2.2) 72 * 73 * Description: 74 * Compute an FFT for a complex signal of length of 2^order, 75 * where 0 <= order <= 15. 76 * Transform length is determined by the specification structure, which 77 * must be initialized prior to calling the FFT function using the appropriate 78 * helper, i.e., <FFTInit_C_sc32> or <FFTInit_C_SC16>. The relationship 79 * between the input and output sequences can be expressed in terms of the 80 * DFT, i.e., 81 * 82 * X[k] = SUM[n=0...N-1]x[n].e^(-jnk.2.pi/N) 83 * k = 0,1,2,..., N-1 84 * N = 2^order 85 * 86 * Input Arguments: 87 * pSrc - pointer to the input signal, a complex-valued vector of length 88 * 2^order; must be aligned on a 32 byte boundary. 89 * pFFTSpec - pointer to the preallocated and initialized specification 90 * structure 91 * 92 * Output Arguments: 93 * pDst - pointer to the complex-valued output vector, of length 2^order; 94 * must be aligned on an 32-byte boundary. 95 * 96 * Return Value: 97 * 98 * OMX_Sts_NoErr - no error 99 * OMX_Sts_BadArgErr - returned if one or more of the following conditions 100 * is true: 101 * - one or more of the following pointers is NULL: pSrc, pDst, or 102 * pFFTSpec. 103 * - pSrc or pDst is not 32-byte aligned 104 * 105 */ 106 107 OMXResult omxSP_FFTFwd_RToCCS_F32_Sfs(const OMX_F32* pSrc, 108 OMX_F32* pDst, 109 const OMXFFTSpec_R_F32* pFFTSpec) { 110 ARMsFFTSpec_R_FC32* spec = (ARMsFFTSpec_R_FC32*)pFFTSpec; 111 int order; 112 long subFFTSize; 113 long subFFTNum; 114 OMX_FC32* pTwiddle; 115 OMX_FC32* pOut; 116 OMX_FC32* pComplexSrc = (OMX_FC32*) pSrc; 117 OMX_FC32* pComplexDst = (OMX_FC32*) pDst; 118 119 /* 120 * Check args are not NULL and the source and destination pointers 121 * are properly aligned. 122 */ 123 if (!validateParametersF32(pSrc, pDst, spec)) 124 return OMX_Sts_BadArgErr; 125 126 /* 127 * Compute the RFFT using a complex FFT of one less order, so set 128 * order to be the order of the complex FFT. 129 */ 130 order = fastlog2(spec->N) - 1; 131 132 subFFTSize = 1; 133 subFFTNum = spec->N >> 1; 134 pTwiddle = spec->pTwiddle; 135 pOut = (OMX_FC32*) spec->pBuf; 136 137 if (order > 3) { 138 OMX_FC32* argDst; 139 OMX_FC32* pComplexDst = (OMX_FC32*) pDst; 140 141 /* 142 * Set up argDst and pOut appropriately so that pOut = pDst for 143 * ComplexToRealFixup. 144 */ 145 if ((order & 2) != 0) { 146 argDst = pOut; 147 pOut = pComplexDst; 148 } else { 149 argDst = pComplexDst; 150 } 151 152 /* 153 * Odd order uses a radix 8 first stage; even order, a radix 4 154 * first stage. 155 */ 156 if (order & 1) { 157 armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace( 158 pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); 159 } else { 160 armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace( 161 pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); 162 } 163 164 /* 165 * Now use radix 4 stages to finish rest of the FFT 166 */ 167 if (subFFTNum >= 4) { 168 while (subFFTNum > 4) { 169 OMX_FC32* tmp; 170 171 armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace( 172 argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); 173 /* 174 * Swap argDst and pOut 175 */ 176 tmp = pOut; 177 pOut = argDst; 178 argDst = tmp; 179 } 180 181 armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace( 182 argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); 183 } 184 } else if (order == 3) { 185 armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( 186 pComplexSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); 187 armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace( 188 pOut, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); 189 armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( 190 pComplexDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); 191 } else if (order == 2) { 192 armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( 193 pComplexSrc, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); 194 armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( 195 pComplexDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); 196 } else if (order == 1) { 197 armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( 198 pComplexSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); 199 } else { 200 /* Handle complex order 0 specially */ 201 pOut->Re = pSrc[0]; 202 pOut->Im = pSrc[1]; 203 } 204 205 /* 206 * Complex FFT done. Fix up the complex result to give the correct 207 * RFFT. 208 */ 209 210 ComplexToRealFixup(pOut, pDst, pTwiddle, spec->pBuf, spec->N); 211 212 return OMX_Sts_NoErr; 213 } 214