arm_cfft_f32.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /* ----------------------------------------------------------------------
  2. * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
  3. *
  4. * $Date: 31. July 2014
  5. * $Revision: V1.4.4
  6. *
  7. * Project: CMSIS DSP Library
  8. * Title: arm_cfft_f32.c
  9. *
  10. * Description: Combined Radix Decimation in Frequency CFFT Floating point processing function
  11. *
  12. * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions
  16. * are met:
  17. * - Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright
  20. * notice, this list of conditions and the following disclaimer in
  21. * the documentation and/or other materials provided with the
  22. * distribution.
  23. * - Neither the name of ARM LIMITED nor the names of its contributors
  24. * may be used to endorse or promote products derived from this
  25. * software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  35. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. * -------------------------------------------------------------------- */
  40. #include "arm_math.h"
  41. #include "arm_common_tables.h"
  42. extern void arm_radix8_butterfly_f32(
  43. float32_t * pSrc,
  44. uint16_t fftLen,
  45. const float32_t * pCoef,
  46. uint16_t twidCoefModifier);
  47. extern void arm_bitreversal_32(
  48. uint32_t * pSrc,
  49. const uint16_t bitRevLen,
  50. const uint16_t * pBitRevTable);
  51. /**
  52. * @ingroup groupTransforms
  53. */
  54. /**
  55. * @defgroup ComplexFFT Complex FFT Functions
  56. *
  57. * \par
  58. * The Fast Fourier Transform (FFT) is an efficient algorithm for computing the
  59. * Discrete Fourier Transform (DFT). The FFT can be orders of magnitude faster
  60. * than the DFT, especially for long lengths.
  61. * The algorithms described in this section
  62. * operate on complex data. A separate set of functions is devoted to handling
  63. * of real sequences.
  64. * \par
  65. * There are separate algorithms for handling floating-point, Q15, and Q31 data
  66. * types. The algorithms available for each data type are described next.
  67. * \par
  68. * The FFT functions operate in-place. That is, the array holding the input data
  69. * will also be used to hold the corresponding result. The input data is complex
  70. * and contains <code>2*fftLen</code> interleaved values as shown below.
  71. * <pre> {real[0], imag[0], real[1], imag[1],..} </pre>
  72. * The FFT result will be contained in the same array and the frequency domain
  73. * values will have the same interleaving.
  74. *
  75. * \par Floating-point
  76. * The floating-point complex FFT uses a mixed-radix algorithm. Multiple radix-8
  77. * stages are performed along with a single radix-2 or radix-4 stage, as needed.
  78. * The algorithm supports lengths of [16, 32, 64, ..., 4096] and each length uses
  79. * a different twiddle factor table.
  80. * \par
  81. * The function uses the standard FFT definition and output values may grow by a
  82. * factor of <code>fftLen</code> when computing the forward transform. The
  83. * inverse transform includes a scale of <code>1/fftLen</code> as part of the
  84. * calculation and this matches the textbook definition of the inverse FFT.
  85. * \par
  86. * Pre-initialized data structures containing twiddle factors and bit reversal
  87. * tables are provided and defined in <code>arm_const_structs.h</code>. Include
  88. * this header in your function and then pass one of the constant structures as
  89. * an argument to arm_cfft_f32. For example:
  90. * \par
  91. * <code>arm_cfft_f32(arm_cfft_sR_f32_len64, pSrc, 1, 1)</code>
  92. * \par
  93. * computes a 64-point inverse complex FFT including bit reversal.
  94. * The data structures are treated as constant data and not modified during the
  95. * calculation. The same data structure can be reused for multiple transforms
  96. * including mixing forward and inverse transforms.
  97. * \par
  98. * Earlier releases of the library provided separate radix-2 and radix-4
  99. * algorithms that operated on floating-point data. These functions are still
  100. * provided but are deprecated. The older functions are slower and less general
  101. * than the new functions.
  102. * \par
  103. * An example of initialization of the constants for the arm_cfft_f32 function follows:
  104. * \code
  105. * const static arm_cfft_instance_f32 *S;
  106. * ...
  107. * switch (length) {
  108. * case 16:
  109. * S = &arm_cfft_sR_f32_len16;
  110. * break;
  111. * case 32:
  112. * S = &arm_cfft_sR_f32_len32;
  113. * break;
  114. * case 64:
  115. * S = &arm_cfft_sR_f32_len64;
  116. * break;
  117. * case 128:
  118. * S = &arm_cfft_sR_f32_len128;
  119. * break;
  120. * case 256:
  121. * S = &arm_cfft_sR_f32_len256;
  122. * break;
  123. * case 512:
  124. * S = &arm_cfft_sR_f32_len512;
  125. * break;
  126. * case 1024:
  127. * S = &arm_cfft_sR_f32_len1024;
  128. * break;
  129. * case 2048:
  130. * S = &arm_cfft_sR_f32_len2048;
  131. * break;
  132. * case 4096:
  133. * S = &arm_cfft_sR_f32_len4096;
  134. * break;
  135. * }
  136. * \endcode
  137. * \par Q15 and Q31
  138. * The floating-point complex FFT uses a mixed-radix algorithm. Multiple radix-4
  139. * stages are performed along with a single radix-2 stage, as needed.
  140. * The algorithm supports lengths of [16, 32, 64, ..., 4096] and each length uses
  141. * a different twiddle factor table.
  142. * \par
  143. * The function uses the standard FFT definition and output values may grow by a
  144. * factor of <code>fftLen</code> when computing the forward transform. The
  145. * inverse transform includes a scale of <code>1/fftLen</code> as part of the
  146. * calculation and this matches the textbook definition of the inverse FFT.
  147. * \par
  148. * Pre-initialized data structures containing twiddle factors and bit reversal
  149. * tables are provided and defined in <code>arm_const_structs.h</code>. Include
  150. * this header in your function and then pass one of the constant structures as
  151. * an argument to arm_cfft_q31. For example:
  152. * \par
  153. * <code>arm_cfft_q31(arm_cfft_sR_q31_len64, pSrc, 1, 1)</code>
  154. * \par
  155. * computes a 64-point inverse complex FFT including bit reversal.
  156. * The data structures are treated as constant data and not modified during the
  157. * calculation. The same data structure can be reused for multiple transforms
  158. * including mixing forward and inverse transforms.
  159. * \par
  160. * Earlier releases of the library provided separate radix-2 and radix-4
  161. * algorithms that operated on floating-point data. These functions are still
  162. * provided but are deprecated. The older functions are slower and less general
  163. * than the new functions.
  164. * \par
  165. * An example of initialization of the constants for the arm_cfft_q31 function follows:
  166. * \code
  167. * const static arm_cfft_instance_q31 *S;
  168. * ...
  169. * switch (length) {
  170. * case 16:
  171. * S = &arm_cfft_sR_q31_len16;
  172. * break;
  173. * case 32:
  174. * S = &arm_cfft_sR_q31_len32;
  175. * break;
  176. * case 64:
  177. * S = &arm_cfft_sR_q31_len64;
  178. * break;
  179. * case 128:
  180. * S = &arm_cfft_sR_q31_len128;
  181. * break;
  182. * case 256:
  183. * S = &arm_cfft_sR_q31_len256;
  184. * break;
  185. * case 512:
  186. * S = &arm_cfft_sR_q31_len512;
  187. * break;
  188. * case 1024:
  189. * S = &arm_cfft_sR_q31_len1024;
  190. * break;
  191. * case 2048:
  192. * S = &arm_cfft_sR_q31_len2048;
  193. * break;
  194. * case 4096:
  195. * S = &arm_cfft_sR_q31_len4096;
  196. * break;
  197. * }
  198. * \endcode
  199. *
  200. */
  201. void arm_cfft_radix8by2_f32( arm_cfft_instance_f32 * S, float32_t * p1)
  202. {
  203. uint32_t L = S->fftLen;
  204. float32_t * pCol1, * pCol2, * pMid1, * pMid2;
  205. float32_t * p2 = p1 + L;
  206. const float32_t * tw = (float32_t *) S->pTwiddle;
  207. float32_t t1[4], t2[4], t3[4], t4[4], twR, twI;
  208. float32_t m0, m1, m2, m3;
  209. uint32_t l;
  210. pCol1 = p1;
  211. pCol2 = p2;
  212. // Define new length
  213. L >>= 1;
  214. // Initialize mid pointers
  215. pMid1 = p1 + L;
  216. pMid2 = p2 + L;
  217. // do two dot Fourier transform
  218. for ( l = L >> 2; l > 0; l-- )
  219. {
  220. t1[0] = p1[0];
  221. t1[1] = p1[1];
  222. t1[2] = p1[2];
  223. t1[3] = p1[3];
  224. t2[0] = p2[0];
  225. t2[1] = p2[1];
  226. t2[2] = p2[2];
  227. t2[3] = p2[3];
  228. t3[0] = pMid1[0];
  229. t3[1] = pMid1[1];
  230. t3[2] = pMid1[2];
  231. t3[3] = pMid1[3];
  232. t4[0] = pMid2[0];
  233. t4[1] = pMid2[1];
  234. t4[2] = pMid2[2];
  235. t4[3] = pMid2[3];
  236. *p1++ = t1[0] + t2[0];
  237. *p1++ = t1[1] + t2[1];
  238. *p1++ = t1[2] + t2[2];
  239. *p1++ = t1[3] + t2[3]; // col 1
  240. t2[0] = t1[0] - t2[0];
  241. t2[1] = t1[1] - t2[1];
  242. t2[2] = t1[2] - t2[2];
  243. t2[3] = t1[3] - t2[3]; // for col 2
  244. *pMid1++ = t3[0] + t4[0];
  245. *pMid1++ = t3[1] + t4[1];
  246. *pMid1++ = t3[2] + t4[2];
  247. *pMid1++ = t3[3] + t4[3]; // col 1
  248. t4[0] = t4[0] - t3[0];
  249. t4[1] = t4[1] - t3[1];
  250. t4[2] = t4[2] - t3[2];
  251. t4[3] = t4[3] - t3[3]; // for col 2
  252. twR = *tw++;
  253. twI = *tw++;
  254. // multiply by twiddle factors
  255. m0 = t2[0] * twR;
  256. m1 = t2[1] * twI;
  257. m2 = t2[1] * twR;
  258. m3 = t2[0] * twI;
  259. // R = R * Tr - I * Ti
  260. *p2++ = m0 + m1;
  261. // I = I * Tr + R * Ti
  262. *p2++ = m2 - m3;
  263. // use vertical symmetry
  264. // 0.9988 - 0.0491i <==> -0.0491 - 0.9988i
  265. m0 = t4[0] * twI;
  266. m1 = t4[1] * twR;
  267. m2 = t4[1] * twI;
  268. m3 = t4[0] * twR;
  269. *pMid2++ = m0 - m1;
  270. *pMid2++ = m2 + m3;
  271. twR = *tw++;
  272. twI = *tw++;
  273. m0 = t2[2] * twR;
  274. m1 = t2[3] * twI;
  275. m2 = t2[3] * twR;
  276. m3 = t2[2] * twI;
  277. *p2++ = m0 + m1;
  278. *p2++ = m2 - m3;
  279. m0 = t4[2] * twI;
  280. m1 = t4[3] * twR;
  281. m2 = t4[3] * twI;
  282. m3 = t4[2] * twR;
  283. *pMid2++ = m0 - m1;
  284. *pMid2++ = m2 + m3;
  285. }
  286. // first col
  287. arm_radix8_butterfly_f32( pCol1, L, (float32_t *) S->pTwiddle, 2u);
  288. // second col
  289. arm_radix8_butterfly_f32( pCol2, L, (float32_t *) S->pTwiddle, 2u);
  290. }
  291. void arm_cfft_radix8by4_f32( arm_cfft_instance_f32 * S, float32_t * p1)
  292. {
  293. uint32_t L = S->fftLen >> 1;
  294. float32_t * pCol1, *pCol2, *pCol3, *pCol4, *pEnd1, *pEnd2, *pEnd3, *pEnd4;
  295. const float32_t *tw2, *tw3, *tw4;
  296. float32_t * p2 = p1 + L;
  297. float32_t * p3 = p2 + L;
  298. float32_t * p4 = p3 + L;
  299. float32_t t2[4], t3[4], t4[4], twR, twI;
  300. float32_t p1ap3_0, p1sp3_0, p1ap3_1, p1sp3_1;
  301. float32_t m0, m1, m2, m3;
  302. uint32_t l, twMod2, twMod3, twMod4;
  303. pCol1 = p1; // points to real values by default
  304. pCol2 = p2;
  305. pCol3 = p3;
  306. pCol4 = p4;
  307. pEnd1 = p2 - 1; // points to imaginary values by default
  308. pEnd2 = p3 - 1;
  309. pEnd3 = p4 - 1;
  310. pEnd4 = pEnd3 + L;
  311. tw2 = tw3 = tw4 = (float32_t *) S->pTwiddle;
  312. L >>= 1;
  313. // do four dot Fourier transform
  314. twMod2 = 2;
  315. twMod3 = 4;
  316. twMod4 = 6;
  317. // TOP
  318. p1ap3_0 = p1[0] + p3[0];
  319. p1sp3_0 = p1[0] - p3[0];
  320. p1ap3_1 = p1[1] + p3[1];
  321. p1sp3_1 = p1[1] - p3[1];
  322. // col 2
  323. t2[0] = p1sp3_0 + p2[1] - p4[1];
  324. t2[1] = p1sp3_1 - p2[0] + p4[0];
  325. // col 3
  326. t3[0] = p1ap3_0 - p2[0] - p4[0];
  327. t3[1] = p1ap3_1 - p2[1] - p4[1];
  328. // col 4
  329. t4[0] = p1sp3_0 - p2[1] + p4[1];
  330. t4[1] = p1sp3_1 + p2[0] - p4[0];
  331. // col 1
  332. *p1++ = p1ap3_0 + p2[0] + p4[0];
  333. *p1++ = p1ap3_1 + p2[1] + p4[1];
  334. // Twiddle factors are ones
  335. *p2++ = t2[0];
  336. *p2++ = t2[1];
  337. *p3++ = t3[0];
  338. *p3++ = t3[1];
  339. *p4++ = t4[0];
  340. *p4++ = t4[1];
  341. tw2 += twMod2;
  342. tw3 += twMod3;
  343. tw4 += twMod4;
  344. for (l = (L - 2) >> 1; l > 0; l-- )
  345. {
  346. // TOP
  347. p1ap3_0 = p1[0] + p3[0];
  348. p1sp3_0 = p1[0] - p3[0];
  349. p1ap3_1 = p1[1] + p3[1];
  350. p1sp3_1 = p1[1] - p3[1];
  351. // col 2
  352. t2[0] = p1sp3_0 + p2[1] - p4[1];
  353. t2[1] = p1sp3_1 - p2[0] + p4[0];
  354. // col 3
  355. t3[0] = p1ap3_0 - p2[0] - p4[0];
  356. t3[1] = p1ap3_1 - p2[1] - p4[1];
  357. // col 4
  358. t4[0] = p1sp3_0 - p2[1] + p4[1];
  359. t4[1] = p1sp3_1 + p2[0] - p4[0];
  360. // col 1 - top
  361. *p1++ = p1ap3_0 + p2[0] + p4[0];
  362. *p1++ = p1ap3_1 + p2[1] + p4[1];
  363. // BOTTOM
  364. p1ap3_1 = pEnd1[-1] + pEnd3[-1];
  365. p1sp3_1 = pEnd1[-1] - pEnd3[-1];
  366. p1ap3_0 = pEnd1[0] + pEnd3[0];
  367. p1sp3_0 = pEnd1[0] - pEnd3[0];
  368. // col 2
  369. t2[2] = pEnd2[0] - pEnd4[0] + p1sp3_1;
  370. t2[3] = pEnd1[0] - pEnd3[0] - pEnd2[-1] + pEnd4[-1];
  371. // col 3
  372. t3[2] = p1ap3_1 - pEnd2[-1] - pEnd4[-1];
  373. t3[3] = p1ap3_0 - pEnd2[0] - pEnd4[0];
  374. // col 4
  375. t4[2] = pEnd2[0] - pEnd4[0] - p1sp3_1;
  376. t4[3] = pEnd4[-1] - pEnd2[-1] - p1sp3_0;
  377. // col 1 - Bottom
  378. *pEnd1-- = p1ap3_0 + pEnd2[0] + pEnd4[0];
  379. *pEnd1-- = p1ap3_1 + pEnd2[-1] + pEnd4[-1];
  380. // COL 2
  381. // read twiddle factors
  382. twR = *tw2++;
  383. twI = *tw2++;
  384. // multiply by twiddle factors
  385. // let Z1 = a + i(b), Z2 = c + i(d)
  386. // => Z1 * Z2 = (a*c - b*d) + i(b*c + a*d)
  387. // Top
  388. m0 = t2[0] * twR;
  389. m1 = t2[1] * twI;
  390. m2 = t2[1] * twR;
  391. m3 = t2[0] * twI;
  392. *p2++ = m0 + m1;
  393. *p2++ = m2 - m3;
  394. // use vertical symmetry col 2
  395. // 0.9997 - 0.0245i <==> 0.0245 - 0.9997i
  396. // Bottom
  397. m0 = t2[3] * twI;
  398. m1 = t2[2] * twR;
  399. m2 = t2[2] * twI;
  400. m3 = t2[3] * twR;
  401. *pEnd2-- = m0 - m1;
  402. *pEnd2-- = m2 + m3;
  403. // COL 3
  404. twR = tw3[0];
  405. twI = tw3[1];
  406. tw3 += twMod3;
  407. // Top
  408. m0 = t3[0] * twR;
  409. m1 = t3[1] * twI;
  410. m2 = t3[1] * twR;
  411. m3 = t3[0] * twI;
  412. *p3++ = m0 + m1;
  413. *p3++ = m2 - m3;
  414. // use vertical symmetry col 3
  415. // 0.9988 - 0.0491i <==> -0.9988 - 0.0491i
  416. // Bottom
  417. m0 = -t3[3] * twR;
  418. m1 = t3[2] * twI;
  419. m2 = t3[2] * twR;
  420. m3 = t3[3] * twI;
  421. *pEnd3-- = m0 - m1;
  422. *pEnd3-- = m3 - m2;
  423. // COL 4
  424. twR = tw4[0];
  425. twI = tw4[1];
  426. tw4 += twMod4;
  427. // Top
  428. m0 = t4[0] * twR;
  429. m1 = t4[1] * twI;
  430. m2 = t4[1] * twR;
  431. m3 = t4[0] * twI;
  432. *p4++ = m0 + m1;
  433. *p4++ = m2 - m3;
  434. // use vertical symmetry col 4
  435. // 0.9973 - 0.0736i <==> -0.0736 + 0.9973i
  436. // Bottom
  437. m0 = t4[3] * twI;
  438. m1 = t4[2] * twR;
  439. m2 = t4[2] * twI;
  440. m3 = t4[3] * twR;
  441. *pEnd4-- = m0 - m1;
  442. *pEnd4-- = m2 + m3;
  443. }
  444. //MIDDLE
  445. // Twiddle factors are
  446. // 1.0000 0.7071-0.7071i -1.0000i -0.7071-0.7071i
  447. p1ap3_0 = p1[0] + p3[0];
  448. p1sp3_0 = p1[0] - p3[0];
  449. p1ap3_1 = p1[1] + p3[1];
  450. p1sp3_1 = p1[1] - p3[1];
  451. // col 2
  452. t2[0] = p1sp3_0 + p2[1] - p4[1];
  453. t2[1] = p1sp3_1 - p2[0] + p4[0];
  454. // col 3
  455. t3[0] = p1ap3_0 - p2[0] - p4[0];
  456. t3[1] = p1ap3_1 - p2[1] - p4[1];
  457. // col 4
  458. t4[0] = p1sp3_0 - p2[1] + p4[1];
  459. t4[1] = p1sp3_1 + p2[0] - p4[0];
  460. // col 1 - Top
  461. *p1++ = p1ap3_0 + p2[0] + p4[0];
  462. *p1++ = p1ap3_1 + p2[1] + p4[1];
  463. // COL 2
  464. twR = tw2[0];
  465. twI = tw2[1];
  466. m0 = t2[0] * twR;
  467. m1 = t2[1] * twI;
  468. m2 = t2[1] * twR;
  469. m3 = t2[0] * twI;
  470. *p2++ = m0 + m1;
  471. *p2++ = m2 - m3;
  472. // COL 3
  473. twR = tw3[0];
  474. twI = tw3[1];
  475. m0 = t3[0] * twR;
  476. m1 = t3[1] * twI;
  477. m2 = t3[1] * twR;
  478. m3 = t3[0] * twI;
  479. *p3++ = m0 + m1;
  480. *p3++ = m2 - m3;
  481. // COL 4
  482. twR = tw4[0];
  483. twI = tw4[1];
  484. m0 = t4[0] * twR;
  485. m1 = t4[1] * twI;
  486. m2 = t4[1] * twR;
  487. m3 = t4[0] * twI;
  488. *p4++ = m0 + m1;
  489. *p4++ = m2 - m3;
  490. // first col
  491. arm_radix8_butterfly_f32( pCol1, L, (float32_t *) S->pTwiddle, 4u);
  492. // second col
  493. arm_radix8_butterfly_f32( pCol2, L, (float32_t *) S->pTwiddle, 4u);
  494. // third col
  495. arm_radix8_butterfly_f32( pCol3, L, (float32_t *) S->pTwiddle, 4u);
  496. // fourth col
  497. arm_radix8_butterfly_f32( pCol4, L, (float32_t *) S->pTwiddle, 4u);
  498. }
  499. /**
  500. * @addtogroup ComplexFFT
  501. * @{
  502. */
  503. /**
  504. * @details
  505. * @brief Processing function for the floating-point complex FFT.
  506. * @param[in] *S points to an instance of the floating-point CFFT structure.
  507. * @param[in, out] *p1 points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
  508. * @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
  509. * @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
  510. * @return none.
  511. */
  512. void arm_cfft_f32(
  513. const arm_cfft_instance_f32 * S,
  514. float32_t * p1,
  515. uint8_t ifftFlag,
  516. uint8_t bitReverseFlag)
  517. {
  518. uint32_t L = S->fftLen, l;
  519. float32_t invL, * pSrc;
  520. if(ifftFlag == 1u)
  521. {
  522. /* Conjugate input data */
  523. pSrc = p1 + 1;
  524. for(l=0; l<L; l++)
  525. {
  526. *pSrc = -*pSrc;
  527. pSrc += 2;
  528. }
  529. }
  530. switch (L)
  531. {
  532. case 16:
  533. case 128:
  534. case 1024:
  535. arm_cfft_radix8by2_f32 ( (arm_cfft_instance_f32 *) S, p1);
  536. break;
  537. case 32:
  538. case 256:
  539. case 2048:
  540. arm_cfft_radix8by4_f32 ( (arm_cfft_instance_f32 *) S, p1);
  541. break;
  542. case 64:
  543. case 512:
  544. case 4096:
  545. arm_radix8_butterfly_f32( p1, L, (float32_t *) S->pTwiddle, 1);
  546. break;
  547. }
  548. if( bitReverseFlag )
  549. arm_bitreversal_32((uint32_t*)p1,S->bitRevLength,S->pBitRevTable);
  550. if(ifftFlag == 1u)
  551. {
  552. invL = 1.0f/(float32_t)L;
  553. /* Conjugate and scale output data */
  554. pSrc = p1;
  555. for(l=0; l<L; l++)
  556. {
  557. *pSrc++ *= invL ;
  558. *pSrc = -(*pSrc) * invL;
  559. pSrc++;
  560. }
  561. }
  562. }
  563. /**
  564. * @} end of ComplexFFT group
  565. */