Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dsp by
arm_cfft_f32.c
00001 /* ---------------------------------------------------------------------- 00002 * Copyright (C) 2010-2013 ARM Limited. All rights reserved. 00003 * 00004 * $Date: 17. January 2013 00005 * $Revision: V1.4.1 00006 * 00007 * Project: CMSIS DSP Library 00008 * Title: arm_cfft_f32.c 00009 * 00010 * Description: Combined Radix Decimation in Frequency CFFT Floating point processing function 00011 * 00012 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 00013 * 00014 * Redistribution and use in source and binary forms, with or without 00015 * modification, are permitted provided that the following conditions 00016 * are met: 00017 * - Redistributions of source code must retain the above copyright 00018 * notice, this list of conditions and the following disclaimer. 00019 * - Redistributions in binary form must reproduce the above copyright 00020 * notice, this list of conditions and the following disclaimer in 00021 * the documentation and/or other materials provided with the 00022 * distribution. 00023 * - Neither the name of ARM LIMITED nor the names of its contributors 00024 * may be used to endorse or promote products derived from this 00025 * software without specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00028 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00029 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00030 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00031 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00032 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00033 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00034 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00035 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00036 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00037 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00038 * POSSIBILITY OF SUCH DAMAGE. 00039 * -------------------------------------------------------------------- */ 00040 00041 00042 #include "arm_math.h" 00043 #include "arm_common_tables.h" 00044 00045 extern void arm_radix8_butterfly_f32( 00046 float32_t * pSrc, 00047 uint16_t fftLen, 00048 const float32_t * pCoef, 00049 uint16_t twidCoefModifier); 00050 00051 extern void arm_bitreversal_32( 00052 uint32_t * pSrc, 00053 const uint16_t bitRevLen, 00054 const uint16_t * pBitRevTable); 00055 00056 /** 00057 * @ingroup groupTransforms 00058 */ 00059 00060 /** 00061 * @defgroup ComplexFFT Complex FFT Functions 00062 * 00063 * \par 00064 * The Fast Fourier Transform (FFT) is an efficient algorithm for computing the 00065 * Discrete Fourier Transform (DFT). The FFT can be orders of magnitude faster 00066 * than the DFT, especially for long lengths. 00067 * The algorithms described in this section 00068 * operate on complex data. A separate set of functions is devoted to handling 00069 * of real sequences. 00070 * \par 00071 * There are separate algorithms for handling floating-point, Q15, and Q31 data 00072 * types. The algorithms available for each data type are described next. 00073 * \par 00074 * The FFT functions operate in-place. That is, the array holding the input data 00075 * will also be used to hold the corresponding result. The input data is complex 00076 * and contains <code>2*fftLen</code> interleaved values as shown below. 00077 * <pre> {real[0], imag[0], real[1], imag[1],..} </pre> 00078 * The FFT result will be contained in the same array and the frequency domain 00079 * values will have the same interleaving. 00080 * 00081 * \par Floating-point 00082 * The floating-point complex FFT uses a mixed-radix algorithm. Multiple radix-8 00083 * stages are performed along with a single radix-2 or radix-4 stage, as needed. 00084 * The algorithm supports lengths of [16, 32, 64, ..., 4096] and each length uses 00085 * a different twiddle factor table. 00086 * \par 00087 * The function uses the standard FFT definition and output values may grow by a 00088 * factor of <code>fftLen</code> when computing the forward transform. The 00089 * inverse transform includes a scale of <code>1/fftLen</code> as part of the 00090 * calculation and this matches the textbook definition of the inverse FFT. 00091 * \par 00092 * Preinitialized data structures containing twiddle factors and bit reversal 00093 * tables are provided and defined in <code>arm_const_structs.h</code>. Include 00094 * this header in your function and then pass one of the constant structures as 00095 * an argument to arm_cfft_f32. For example: 00096 * \par 00097 * <code>arm_cfft_f32(arm_cfft_sR_f32_len64, pSrc, 1, 1)</code> 00098 * \par 00099 * computes a 64-point inverse complex FFT including bit reversal. 00100 * The data structures are treated as constant data and not modified during the 00101 * calculation. The same data structure can be reused for multiple transforms 00102 * including mixing forward and inverse transforms. 00103 * \par 00104 * Earlier releases of the library provided separate radix-2 and radix-4 00105 * algorithms that operated on floating-point data. These functions are still 00106 * provided but are deprecated. The older functions are slower and less general 00107 * than the new functions. 00108 * \par 00109 * An example of initialization of the constants for the arm_cfft_f32 function follows: 00110 * \par 00111 * const static arm_cfft_instance_f32 *S; 00112 * ... 00113 * switch (length) { 00114 * case 16: 00115 * S = & arm_cfft_sR_f32_len16; 00116 * break; 00117 * case 32: 00118 * S = & arm_cfft_sR_f32_len32; 00119 * break; 00120 * case 64: 00121 * S = & arm_cfft_sR_f32_len64; 00122 * break; 00123 * case 128: 00124 * S = & arm_cfft_sR_f32_len128; 00125 * break; 00126 * case 256: 00127 * S = & arm_cfft_sR_f32_len256; 00128 * break; 00129 * case 512: 00130 * S = & arm_cfft_sR_f32_len512; 00131 * break; 00132 * case 1024: 00133 * S = & arm_cfft_sR_f32_len1024; 00134 * break; 00135 * case 2048: 00136 * S = & arm_cfft_sR_f32_len2048; 00137 * break; 00138 * case 4096: 00139 * S = & arm_cfft_sR_f32_len4096; 00140 * break; 00141 * } 00142 * \par Q15 and Q31 00143 * The library provides radix-2 and radix-4 FFT algorithms for fixed-point data. The 00144 * radix-2 algorithm supports lengths of [16, 32, 64, ..., 4096]. The radix-4 00145 * algorithm supports lengths of [16, 64, 256, ..., 4096]. When possible, you 00146 * should use the radix-4 algorithm since it is faster than the radix-2 of the 00147 * same length. 00148 * \par 00149 * The forward FFTs include scaling in order to prevent results from overflowing. 00150 * Intermediate results are scaled down during each butterfly stage. In the 00151 * radix-2 algorithm, a scale of 0.5 is applied during each butterfly. In the 00152 * radix-4 algorithm, a scale of 0.25 is applied. The scaling applies to both 00153 * the forward and the inverse FFTs. Thus the forward FFT contains an additional 00154 * scale factor of <code>1/fftLen</code> as compared to the standard textbook 00155 * definition of the FFT. The inverse FFT also scales down during each butterfly 00156 * stage and this corresponds to the standard textbook definition. 00157 * \par 00158 * A separate instance structure must be defined for each transform used but 00159 * twiddle factor and bit reversal tables can be reused. 00160 * \par 00161 * There is also an associated initialization function for each data type. 00162 * The initialization function performs the following operations: 00163 * - Sets the values of the internal structure fields. 00164 * - Initializes twiddle factor table and bit reversal table pointers. 00165 * \par 00166 * Use of the initialization function is optional. 00167 * However, if the initialization function is used, then the instance structure 00168 * cannot be placed into a const data section. To place an instance structure 00169 * into a const data section, the instance structure should be manually 00170 * initialized as follows: 00171 * <pre> 00172 *arm_cfft_radix2_instance_q31 S = {fftLen, ifftFlag, bitReverseFlag, pTwiddle, pBitRevTable, twidCoefModifier, bitRevFactor}; 00173 *arm_cfft_radix2_instance_q15 S = {fftLen, ifftFlag, bitReverseFlag, pTwiddle, pBitRevTable, twidCoefModifier, bitRevFactor}; 00174 *arm_cfft_radix4_instance_q31 S = {fftLen, ifftFlag, bitReverseFlag, pTwiddle, pBitRevTable, twidCoefModifier, bitRevFactor}; 00175 *arm_cfft_radix4_instance_q15 S = {fftLen, ifftFlag, bitReverseFlag, pTwiddle, pBitRevTable, twidCoefModifier, bitRevFactor}; 00176 *arm_cfft_instance_f32 S = {fftLen, pTwiddle, pBitRevTable, bitRevLength}; 00177 * </pre> 00178 * \par 00179 * where <code>fftLen</code> length of CFFT/CIFFT; <code>ifftFlag</code> Flag for 00180 * selection of forward or inverse transform. When ifftFlag is set the inverse 00181 * transform is calculated. 00182 * <code>bitReverseFlag</code> Flag for selection of output order (Set bitReverseFlag to output in normal order otherwise output in bit reversed order); 00183 * <code>pTwiddle</code>points to array of twiddle coefficients; <code>pBitRevTable</code> points to the bit reversal table. 00184 * <code>twidCoefModifier</code> modifier for twiddle factor table which supports all FFT lengths with same table; 00185 * <code>pBitRevTable</code> modifier for bit reversal table which supports all FFT lengths with same table. 00186 * <code>onebyfftLen</code> value of 1/fftLen to calculate CIFFT; 00187 * \par 00188 * The Q15 and Q31 FFT functions use a large bit reversal and twiddle factor 00189 * table. The tables are defined for the maximum length transform and a subset 00190 * of the coefficients are used in shorter transforms. 00191 * 00192 */ 00193 00194 void arm_cfft_radix8by2_f32( arm_cfft_instance_f32 * S, float32_t * p1) 00195 { 00196 uint32_t L = S->fftLen; 00197 float32_t * pCol1, * pCol2, * pMid1, * pMid2; 00198 float32_t * p2 = p1 + L; 00199 const float32_t * tw = (float32_t *) S->pTwiddle; 00200 float32_t t1[4], t2[4], t3[4], t4[4], twR, twI; 00201 float32_t m0, m1, m2, m3; 00202 uint32_t l; 00203 00204 pCol1 = p1; 00205 pCol2 = p2; 00206 00207 // Define new length 00208 L >>= 1; 00209 // Initialize mid pointers 00210 pMid1 = p1 + L; 00211 pMid2 = p2 + L; 00212 00213 // do two dot Fourier transform 00214 for ( l = L >> 2; l > 0; l-- ) 00215 { 00216 t1[0] = p1[0]; 00217 t1[1] = p1[1]; 00218 t1[2] = p1[2]; 00219 t1[3] = p1[3]; 00220 00221 t2[0] = p2[0]; 00222 t2[1] = p2[1]; 00223 t2[2] = p2[2]; 00224 t2[3] = p2[3]; 00225 00226 t3[0] = pMid1[0]; 00227 t3[1] = pMid1[1]; 00228 t3[2] = pMid1[2]; 00229 t3[3] = pMid1[3]; 00230 00231 t4[0] = pMid2[0]; 00232 t4[1] = pMid2[1]; 00233 t4[2] = pMid2[2]; 00234 t4[3] = pMid2[3]; 00235 00236 *p1++ = t1[0] + t2[0]; 00237 *p1++ = t1[1] + t2[1]; 00238 *p1++ = t1[2] + t2[2]; 00239 *p1++ = t1[3] + t2[3]; // col 1 00240 00241 t2[0] = t1[0] - t2[0]; 00242 t2[1] = t1[1] - t2[1]; 00243 t2[2] = t1[2] - t2[2]; 00244 t2[3] = t1[3] - t2[3]; // for col 2 00245 00246 *pMid1++ = t3[0] + t4[0]; 00247 *pMid1++ = t3[1] + t4[1]; 00248 *pMid1++ = t3[2] + t4[2]; 00249 *pMid1++ = t3[3] + t4[3]; // col 1 00250 00251 t4[0] = t4[0] - t3[0]; 00252 t4[1] = t4[1] - t3[1]; 00253 t4[2] = t4[2] - t3[2]; 00254 t4[3] = t4[3] - t3[3]; // for col 2 00255 00256 twR = *tw++; 00257 twI = *tw++; 00258 00259 // multiply by twiddle factors 00260 m0 = t2[0] * twR; 00261 m1 = t2[1] * twI; 00262 m2 = t2[1] * twR; 00263 m3 = t2[0] * twI; 00264 00265 // R = R * Tr - I * Ti 00266 *p2++ = m0 + m1; 00267 // I = I * Tr + R * Ti 00268 *p2++ = m2 - m3; 00269 00270 // use vertical symmetry 00271 // 0.9988 - 0.0491i <==> -0.0491 - 0.9988i 00272 m0 = t4[0] * twI; 00273 m1 = t4[1] * twR; 00274 m2 = t4[1] * twI; 00275 m3 = t4[0] * twR; 00276 00277 *pMid2++ = m0 - m1; 00278 *pMid2++ = m2 + m3; 00279 00280 twR = *tw++; 00281 twI = *tw++; 00282 00283 m0 = t2[2] * twR; 00284 m1 = t2[3] * twI; 00285 m2 = t2[3] * twR; 00286 m3 = t2[2] * twI; 00287 00288 *p2++ = m0 + m1; 00289 *p2++ = m2 - m3; 00290 00291 m0 = t4[2] * twI; 00292 m1 = t4[3] * twR; 00293 m2 = t4[3] * twI; 00294 m3 = t4[2] * twR; 00295 00296 *pMid2++ = m0 - m1; 00297 *pMid2++ = m2 + m3; 00298 } 00299 00300 // first col 00301 arm_radix8_butterfly_f32( pCol1, L, (float32_t *) S->pTwiddle, 2u); 00302 // second col 00303 arm_radix8_butterfly_f32( pCol2, L, (float32_t *) S->pTwiddle, 2u); 00304 00305 } 00306 00307 void arm_cfft_radix8by4_f32( arm_cfft_instance_f32 * S, float32_t * p1) 00308 { 00309 uint32_t L = S->fftLen >> 1; 00310 float32_t * pCol1, *pCol2, *pCol3, *pCol4, *pEnd1, *pEnd2, *pEnd3, *pEnd4; 00311 const float32_t *tw2, *tw3, *tw4; 00312 float32_t * p2 = p1 + L; 00313 float32_t * p3 = p2 + L; 00314 float32_t * p4 = p3 + L; 00315 float32_t t2[4], t3[4], t4[4], twR, twI; 00316 float32_t p1ap3_0, p1sp3_0, p1ap3_1, p1sp3_1; 00317 float32_t m0, m1, m2, m3; 00318 uint32_t l, twMod2, twMod3, twMod4; 00319 00320 pCol1 = p1; // points to real values by default 00321 pCol2 = p2; 00322 pCol3 = p3; 00323 pCol4 = p4; 00324 pEnd1 = p2 - 1; // points to imaginary values by default 00325 pEnd2 = p3 - 1; 00326 pEnd3 = p4 - 1; 00327 pEnd4 = pEnd3 + L; 00328 00329 tw2 = tw3 = tw4 = (float32_t *) S->pTwiddle; 00330 00331 L >>= 1; 00332 00333 // do four dot Fourier transform 00334 00335 twMod2 = 2; 00336 twMod3 = 4; 00337 twMod4 = 6; 00338 00339 // TOP 00340 p1ap3_0 = p1[0] + p3[0]; 00341 p1sp3_0 = p1[0] - p3[0]; 00342 p1ap3_1 = p1[1] + p3[1]; 00343 p1sp3_1 = p1[1] - p3[1]; 00344 00345 // col 2 00346 t2[0] = p1sp3_0 + p2[1] - p4[1]; 00347 t2[1] = p1sp3_1 - p2[0] + p4[0]; 00348 // col 3 00349 t3[0] = p1ap3_0 - p2[0] - p4[0]; 00350 t3[1] = p1ap3_1 - p2[1] - p4[1]; 00351 // col 4 00352 t4[0] = p1sp3_0 - p2[1] + p4[1]; 00353 t4[1] = p1sp3_1 + p2[0] - p4[0]; 00354 // col 1 00355 *p1++ = p1ap3_0 + p2[0] + p4[0]; 00356 *p1++ = p1ap3_1 + p2[1] + p4[1]; 00357 00358 // Twiddle factors are ones 00359 *p2++ = t2[0]; 00360 *p2++ = t2[1]; 00361 *p3++ = t3[0]; 00362 *p3++ = t3[1]; 00363 *p4++ = t4[0]; 00364 *p4++ = t4[1]; 00365 00366 tw2 += twMod2; 00367 tw3 += twMod3; 00368 tw4 += twMod4; 00369 00370 for (l = (L - 2) >> 1; l > 0; l-- ) 00371 { 00372 00373 // TOP 00374 p1ap3_0 = p1[0] + p3[0]; 00375 p1sp3_0 = p1[0] - p3[0]; 00376 p1ap3_1 = p1[1] + p3[1]; 00377 p1sp3_1 = p1[1] - p3[1]; 00378 // col 2 00379 t2[0] = p1sp3_0 + p2[1] - p4[1]; 00380 t2[1] = p1sp3_1 - p2[0] + p4[0]; 00381 // col 3 00382 t3[0] = p1ap3_0 - p2[0] - p4[0]; 00383 t3[1] = p1ap3_1 - p2[1] - p4[1]; 00384 // col 4 00385 t4[0] = p1sp3_0 - p2[1] + p4[1]; 00386 t4[1] = p1sp3_1 + p2[0] - p4[0]; 00387 // col 1 - top 00388 *p1++ = p1ap3_0 + p2[0] + p4[0]; 00389 *p1++ = p1ap3_1 + p2[1] + p4[1]; 00390 00391 // BOTTOM 00392 p1ap3_1 = pEnd1[-1] + pEnd3[-1]; 00393 p1sp3_1 = pEnd1[-1] - pEnd3[-1]; 00394 p1ap3_0 = pEnd1[0] + pEnd3[0]; 00395 p1sp3_0 = pEnd1[0] - pEnd3[0]; 00396 // col 2 00397 t2[2] = pEnd2[0] - pEnd4[0] + p1sp3_1; 00398 t2[3] = pEnd1[0] - pEnd3[0] - pEnd2[-1] + pEnd4[-1]; 00399 // col 3 00400 t3[2] = p1ap3_1 - pEnd2[-1] - pEnd4[-1]; 00401 t3[3] = p1ap3_0 - pEnd2[0] - pEnd4[0]; 00402 // col 4 00403 t4[2] = pEnd2[0] - pEnd4[0] - p1sp3_1; 00404 t4[3] = pEnd4[-1] - pEnd2[-1] - p1sp3_0; 00405 // col 1 - Bottom 00406 *pEnd1-- = p1ap3_0 + pEnd2[0] + pEnd4[0]; 00407 *pEnd1-- = p1ap3_1 + pEnd2[-1] + pEnd4[-1]; 00408 00409 // COL 2 00410 // read twiddle factors 00411 twR = *tw2++; 00412 twI = *tw2++; 00413 // multiply by twiddle factors 00414 // let Z1 = a + i(b), Z2 = c + i(d) 00415 // => Z1 * Z2 = (a*c - b*d) + i(b*c + a*d) 00416 // Top 00417 m0 = t2[0] * twR; 00418 m1 = t2[1] * twI; 00419 m2 = t2[1] * twR; 00420 m3 = t2[0] * twI; 00421 00422 *p2++ = m0 + m1; 00423 *p2++ = m2 - m3; 00424 // use vertical symmetry col 2 00425 // 0.9997 - 0.0245i <==> 0.0245 - 0.9997i 00426 // Bottom 00427 m0 = t2[3] * twI; 00428 m1 = t2[2] * twR; 00429 m2 = t2[2] * twI; 00430 m3 = t2[3] * twR; 00431 00432 *pEnd2-- = m0 - m1; 00433 *pEnd2-- = m2 + m3; 00434 00435 // COL 3 00436 twR = tw3[0]; 00437 twI = tw3[1]; 00438 tw3 += twMod3; 00439 // Top 00440 m0 = t3[0] * twR; 00441 m1 = t3[1] * twI; 00442 m2 = t3[1] * twR; 00443 m3 = t3[0] * twI; 00444 00445 *p3++ = m0 + m1; 00446 *p3++ = m2 - m3; 00447 // use vertical symmetry col 3 00448 // 0.9988 - 0.0491i <==> -0.9988 - 0.0491i 00449 // Bottom 00450 m0 = -t3[3] * twR; 00451 m1 = t3[2] * twI; 00452 m2 = t3[2] * twR; 00453 m3 = t3[3] * twI; 00454 00455 *pEnd3-- = m0 - m1; 00456 *pEnd3-- = m3 - m2; 00457 00458 // COL 4 00459 twR = tw4[0]; 00460 twI = tw4[1]; 00461 tw4 += twMod4; 00462 // Top 00463 m0 = t4[0] * twR; 00464 m1 = t4[1] * twI; 00465 m2 = t4[1] * twR; 00466 m3 = t4[0] * twI; 00467 00468 *p4++ = m0 + m1; 00469 *p4++ = m2 - m3; 00470 // use vertical symmetry col 4 00471 // 0.9973 - 0.0736i <==> -0.0736 + 0.9973i 00472 // Bottom 00473 m0 = t4[3] * twI; 00474 m1 = t4[2] * twR; 00475 m2 = t4[2] * twI; 00476 m3 = t4[3] * twR; 00477 00478 *pEnd4-- = m0 - m1; 00479 *pEnd4-- = m2 + m3; 00480 } 00481 00482 //MIDDLE 00483 // Twiddle factors are 00484 // 1.0000 0.7071-0.7071i -1.0000i -0.7071-0.7071i 00485 p1ap3_0 = p1[0] + p3[0]; 00486 p1sp3_0 = p1[0] - p3[0]; 00487 p1ap3_1 = p1[1] + p3[1]; 00488 p1sp3_1 = p1[1] - p3[1]; 00489 00490 // col 2 00491 t2[0] = p1sp3_0 + p2[1] - p4[1]; 00492 t2[1] = p1sp3_1 - p2[0] + p4[0]; 00493 // col 3 00494 t3[0] = p1ap3_0 - p2[0] - p4[0]; 00495 t3[1] = p1ap3_1 - p2[1] - p4[1]; 00496 // col 4 00497 t4[0] = p1sp3_0 - p2[1] + p4[1]; 00498 t4[1] = p1sp3_1 + p2[0] - p4[0]; 00499 // col 1 - Top 00500 *p1++ = p1ap3_0 + p2[0] + p4[0]; 00501 *p1++ = p1ap3_1 + p2[1] + p4[1]; 00502 00503 // COL 2 00504 twR = tw2[0]; 00505 twI = tw2[1]; 00506 00507 m0 = t2[0] * twR; 00508 m1 = t2[1] * twI; 00509 m2 = t2[1] * twR; 00510 m3 = t2[0] * twI; 00511 00512 *p2++ = m0 + m1; 00513 *p2++ = m2 - m3; 00514 // COL 3 00515 twR = tw3[0]; 00516 twI = tw3[1]; 00517 00518 m0 = t3[0] * twR; 00519 m1 = t3[1] * twI; 00520 m2 = t3[1] * twR; 00521 m3 = t3[0] * twI; 00522 00523 *p3++ = m0 + m1; 00524 *p3++ = m2 - m3; 00525 // COL 4 00526 twR = tw4[0]; 00527 twI = tw4[1]; 00528 00529 m0 = t4[0] * twR; 00530 m1 = t4[1] * twI; 00531 m2 = t4[1] * twR; 00532 m3 = t4[0] * twI; 00533 00534 *p4++ = m0 + m1; 00535 *p4++ = m2 - m3; 00536 00537 // first col 00538 arm_radix8_butterfly_f32( pCol1, L, (float32_t *) S->pTwiddle, 4u); 00539 // second col 00540 arm_radix8_butterfly_f32( pCol2, L, (float32_t *) S->pTwiddle, 4u); 00541 // third col 00542 arm_radix8_butterfly_f32( pCol3, L, (float32_t *) S->pTwiddle, 4u); 00543 // fourth col 00544 arm_radix8_butterfly_f32( pCol4, L, (float32_t *) S->pTwiddle, 4u); 00545 00546 } 00547 00548 /** 00549 * @addtogroup ComplexFFT 00550 * @{ 00551 */ 00552 00553 /** 00554 * @details 00555 * @brief Processing function for the floating-point complex FFT. 00556 * @param[in] *S points to an instance of the floating-point CFFT structure. 00557 * @param[in, out] *p1 points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place. 00558 * @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. 00559 * @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. 00560 * @return none. 00561 */ 00562 00563 void arm_cfft_f32( 00564 const arm_cfft_instance_f32 * S, 00565 float32_t * p1, 00566 uint8_t ifftFlag, 00567 uint8_t bitReverseFlag) 00568 { 00569 00570 uint32_t L = S->fftLen, l; 00571 float32_t invL, * pSrc; 00572 00573 if(ifftFlag == 1u) 00574 { 00575 /* Conjugate input data */ 00576 pSrc = p1 + 1; 00577 for(l=0; l<L; l++) { 00578 *pSrc = -*pSrc; 00579 pSrc += 2; 00580 } 00581 } 00582 00583 switch (L) { 00584 case 16: 00585 case 128: 00586 case 1024: 00587 arm_cfft_radix8by2_f32 ( (arm_cfft_instance_f32 *) S, p1); 00588 break; 00589 case 32: 00590 case 256: 00591 case 2048: 00592 arm_cfft_radix8by4_f32 ( (arm_cfft_instance_f32 *) S, p1); 00593 break; 00594 case 64: 00595 case 512: 00596 case 4096: 00597 arm_radix8_butterfly_f32( p1, L, (float32_t *) S->pTwiddle, 1); 00598 break; 00599 } 00600 00601 if( bitReverseFlag ) 00602 arm_bitreversal_32((uint32_t*)p1,S->bitRevLength,S->pBitRevTable); 00603 00604 if(ifftFlag == 1u) 00605 { 00606 invL = 1.0f/(float32_t)L; 00607 /* Conjugate and scale output data */ 00608 pSrc = p1; 00609 for(l=0; l<L; l++) { 00610 *pSrc++ *= invL ; 00611 *pSrc = -(*pSrc) * invL; 00612 pSrc++; 00613 } 00614 } 00615 } 00616
Generated on Tue Jul 12 2022 18:44:08 by
1.7.2
