arm_cfft_f32.c 17 KB

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