Subversion Repositories testOled

Rev

Details | Last modification | View Log | RSS feed

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