1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_rfft_f32.c
4 * Description: RFFT & RIFFT Floating point process function
5 *
6 * $Date: 23 April 2021
7 * $Revision: V1.9.0
8 *
9 * Target Processor: Cortex-M and Cortex-A cores
10 * -------------------------------------------------------------------- */
11 /*
12 * Copyright (C) 2010-2021 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
29 #include "dsp/transform_functions.h"
30
31 /* ----------------------------------------------------------------------
32 * Internal functions prototypes
33 * -------------------------------------------------------------------- */
34
35 extern void arm_radix4_butterfly_f32(
36 float32_t * pSrc,
37 uint16_t fftLen,
38 const float32_t * pCoef,
39 uint16_t twidCoefModifier);
40
41 extern void arm_radix4_butterfly_inverse_f32(
42 float32_t * pSrc,
43 uint16_t fftLen,
44 const float32_t * pCoef,
45 uint16_t twidCoefModifier,
46 float32_t onebyfftLen);
47
48 extern void arm_bitreversal_f32(
49 float32_t * pSrc,
50 uint16_t fftSize,
51 uint16_t bitRevFactor,
52 const uint16_t * pBitRevTab);
53
54 void arm_split_rfft_f32(
55 float32_t * pSrc,
56 uint32_t fftLen,
57 const float32_t * pATable,
58 const float32_t * pBTable,
59 float32_t * pDst,
60 uint32_t modifier);
61
62 void arm_split_rifft_f32(
63 float32_t * pSrc,
64 uint32_t fftLen,
65 const float32_t * pATable,
66 const float32_t * pBTable,
67 float32_t * pDst,
68 uint32_t modifier);
69
70 /**
71 @ingroup groupTransforms
72 */
73
74 /**
75 @addtogroup RealFFT
76 @{
77 */
78
79 /**
80 @brief Processing function for the floating-point RFFT/RIFFT.
81 Source buffer is modified by this function.
82
83 @deprecated Do not use this function. It has been superceded by \ref arm_rfft_fast_f32 and will be removed in the future.
84 @param[in] S points to an instance of the floating-point RFFT/RIFFT structure
85 @param[in] pSrc points to the input buffer
86 @param[out] pDst points to the output buffer
87 @return none
88
89 @par
90 For the RIFFT, the source buffer must at least have length
91 fftLenReal + 2.
92 The last two elements must be equal to what would be generated
93 by the RFFT:
94 (pSrc[0] - pSrc[1]) and 0.0f
95 */
96
arm_rfft_f32(const arm_rfft_instance_f32 * S,float32_t * pSrc,float32_t * pDst)97 void arm_rfft_f32(
98 const arm_rfft_instance_f32 * S,
99 float32_t * pSrc,
100 float32_t * pDst)
101 {
102 const arm_cfft_radix4_instance_f32 *S_CFFT = S->pCfft;
103
104 /* Calculation of Real IFFT of input */
105 if (S->ifftFlagR == 1U)
106 {
107 /* Real IFFT core process */
108 arm_split_rifft_f32 (pSrc, S->fftLenBy2, S->pTwiddleAReal, S->pTwiddleBReal, pDst, S->twidCoefRModifier);
109
110
111 /* Complex radix-4 IFFT process */
112 arm_radix4_butterfly_inverse_f32 (pDst, S_CFFT->fftLen, S_CFFT->pTwiddle, S_CFFT->twidCoefModifier, S_CFFT->onebyfftLen);
113
114 /* Bit reversal process */
115 if (S->bitReverseFlagR == 1U)
116 {
117 arm_bitreversal_f32 (pDst, S_CFFT->fftLen, S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
118 }
119 }
120 else
121 {
122 /* Calculation of RFFT of input */
123
124 /* Complex radix-4 FFT process */
125 arm_radix4_butterfly_f32 (pSrc, S_CFFT->fftLen, S_CFFT->pTwiddle, S_CFFT->twidCoefModifier);
126
127 /* Bit reversal process */
128 if (S->bitReverseFlagR == 1U)
129 {
130 arm_bitreversal_f32 (pSrc, S_CFFT->fftLen, S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
131 }
132
133 /* Real FFT core process */
134 arm_split_rfft_f32 (pSrc, S->fftLenBy2, S->pTwiddleAReal, S->pTwiddleBReal, pDst, S->twidCoefRModifier);
135 }
136
137 }
138
139 /**
140 @} end of RealFFT group
141 */
142
143 /**
144 @brief Core Real FFT process
145 @param[in] pSrc points to input buffer
146 @param[in] fftLen length of FFT
147 @param[in] pATable points to twiddle Coef A buffer
148 @param[in] pBTable points to twiddle Coef B buffer
149 @param[out] pDst points to output buffer
150 @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table
151 @return none
152 */
153
arm_split_rfft_f32(float32_t * pSrc,uint32_t fftLen,const float32_t * pATable,const float32_t * pBTable,float32_t * pDst,uint32_t modifier)154 void arm_split_rfft_f32(
155 float32_t * pSrc,
156 uint32_t fftLen,
157 const float32_t * pATable,
158 const float32_t * pBTable,
159 float32_t * pDst,
160 uint32_t modifier)
161 {
162 uint32_t i; /* Loop Counter */
163 float32_t outR, outI; /* Temporary variables for output */
164 const float32_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
165 float32_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
166 float32_t *pDst1 = &pDst[2], *pDst2 = &pDst[(4U * fftLen) - 1U]; /* temp pointers for output buffer */
167 float32_t *pSrc1 = &pSrc[2], *pSrc2 = &pSrc[(2U * fftLen) - 1U]; /* temp pointers for input buffer */
168
169 /* Init coefficient pointers */
170 pCoefA = &pATable[modifier * 2];
171 pCoefB = &pBTable[modifier * 2];
172
173 i = fftLen - 1U;
174
175 while (i > 0U)
176 {
177 /*
178 outR = ( pSrc[2 * i] * pATable[2 * i]
179 - pSrc[2 * i + 1] * pATable[2 * i + 1]
180 + pSrc[2 * n - 2 * i] * pBTable[2 * i]
181 + pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
182
183 outI = ( pIn[2 * i + 1] * pATable[2 * i]
184 + pIn[2 * i] * pATable[2 * i + 1]
185 + pIn[2 * n - 2 * i] * pBTable[2 * i + 1]
186 - pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
187 */
188
189 /* read pATable[2 * i] */
190 CoefA1 = *pCoefA++;
191 /* pATable[2 * i + 1] */
192 CoefA2 = *pCoefA;
193
194 /* pSrc[2 * i] * pATable[2 * i] */
195 outR = *pSrc1 * CoefA1;
196 /* pSrc[2 * i] * CoefA2 */
197 outI = *pSrc1++ * CoefA2;
198
199 /* (pSrc[2 * i + 1] + pSrc[2 * fftLen - 2 * i + 1]) * CoefA2 */
200 outR -= (*pSrc1 + *pSrc2) * CoefA2;
201 /* pSrc[2 * i + 1] * CoefA1 */
202 outI += *pSrc1++ * CoefA1;
203
204 CoefB1 = *pCoefB;
205
206 /* pSrc[2 * fftLen - 2 * i + 1] * CoefB1 */
207 outI -= *pSrc2-- * CoefB1;
208 /* pSrc[2 * fftLen - 2 * i] * CoefA2 */
209 outI -= *pSrc2 * CoefA2;
210
211 /* pSrc[2 * fftLen - 2 * i] * CoefB1 */
212 outR += *pSrc2-- * CoefB1;
213
214 /* write output */
215 *pDst1++ = outR;
216 *pDst1++ = outI;
217
218 /* write complex conjugate output */
219 *pDst2-- = -outI;
220 *pDst2-- = outR;
221
222 /* update coefficient pointer */
223 pCoefB = pCoefB + (modifier * 2U);
224 pCoefA = pCoefA + ((modifier * 2U) - 1U);
225
226 i--;
227
228 }
229
230 pDst[2U * fftLen] = pSrc[0] - pSrc[1];
231 pDst[(2U * fftLen) + 1U] = 0.0f;
232
233 pDst[0] = pSrc[0] + pSrc[1];
234 pDst[1] = 0.0f;
235
236 }
237
238
239 /**
240 @brief Core Real IFFT process
241 @param[in] pSrc points to input buffer
242 @param[in] fftLen length of FFT
243 @param[in] pATable points to twiddle Coef A buffer
244 @param[in] pBTable points to twiddle Coef B buffer
245 @param[out] pDst points to output buffer
246 @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table
247 @return none
248 */
249
arm_split_rifft_f32(float32_t * pSrc,uint32_t fftLen,const float32_t * pATable,const float32_t * pBTable,float32_t * pDst,uint32_t modifier)250 void arm_split_rifft_f32(
251 float32_t * pSrc,
252 uint32_t fftLen,
253 const float32_t * pATable,
254 const float32_t * pBTable,
255 float32_t * pDst,
256 uint32_t modifier)
257 {
258 float32_t outR, outI; /* Temporary variables for output */
259 const float32_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
260 float32_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
261 float32_t *pSrc1 = &pSrc[0], *pSrc2 = &pSrc[(2U * fftLen) + 1U];
262
263 pCoefA = &pATable[0];
264 pCoefB = &pBTable[0];
265
266 while (fftLen > 0U)
267 {
268 /*
269 outR = ( pIn[2 * i] * pATable[2 * i]
270 + pIn[2 * i + 1] * pATable[2 * i + 1]
271 + pIn[2 * n - 2 * i] * pBTable[2 * i]
272 - pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
273
274 outI = ( pIn[2 * i + 1] * pATable[2 * i]
275 - pIn[2 * i] * pATable[2 * i + 1]
276 - pIn[2 * n - 2 * i] * pBTable[2 * i + 1]
277 - pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
278 */
279
280 CoefA1 = *pCoefA++;
281 CoefA2 = *pCoefA;
282
283 /* outR = (pSrc[2 * i] * CoefA1 */
284 outR = *pSrc1 * CoefA1;
285
286 /* - pSrc[2 * i] * CoefA2 */
287 outI = -(*pSrc1++) * CoefA2;
288
289 /* (pSrc[2 * i + 1] + pSrc[2 * fftLen - 2 * i + 1]) * CoefA2 */
290 outR += (*pSrc1 + *pSrc2) * CoefA2;
291
292 /* pSrc[2 * i + 1] * CoefA1 */
293 outI += (*pSrc1++) * CoefA1;
294
295 CoefB1 = *pCoefB;
296
297 /* - pSrc[2 * fftLen - 2 * i + 1] * CoefB1 */
298 outI -= *pSrc2-- * CoefB1;
299
300 /* pSrc[2 * fftLen - 2 * i] * CoefB1 */
301 outR += *pSrc2 * CoefB1;
302
303 /* pSrc[2 * fftLen - 2 * i] * CoefA2 */
304 outI += *pSrc2-- * CoefA2;
305
306 /* write output */
307 *pDst++ = outR;
308 *pDst++ = outI;
309
310 /* update coefficient pointer */
311 pCoefB = pCoefB + (modifier * 2);
312 pCoefA = pCoefA + (modifier * 2 - 1);
313
314 /* Decrement loop count */
315 fftLen--;
316 }
317
318 }
319