QuakeGod
2023-10-08 483170e190a0dd4666b2a63e5d31466052ba0c6a
提交 | 用户 | age
483170 1 /* ----------------------------------------------------------------------    
Q 2 * Copyright (C) 2010-2014 ARM Limited. All rights reserved.    
3 *    
4 * $Date:        19. March 2015 
5 * $Revision:     V.1.4.5  
6 *    
7 * Project:         CMSIS DSP Library    
8 * Title:        arm_rfft_q31.c    
9 *    
10 * Description:    RFFT & RIFFT Q31 process function    
11 *    
12 *    
13 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
14 *  
15 * Redistribution and use in source and binary forms, with or without 
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *   - Redistributions of source code must retain the above copyright
19 *     notice, this list of conditions and the following disclaimer.
20 *   - Redistributions in binary form must reproduce the above copyright
21 *     notice, this list of conditions and the following disclaimer in
22 *     the documentation and/or other materials provided with the 
23 *     distribution.
24 *   - Neither the name of ARM LIMITED nor the names of its contributors
25 *     may be used to endorse or promote products derived from this
26 *     software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
32 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.    
40 * -------------------------------------------------------------------- */
41
42 #include "arm_math.h"
43
44 /*--------------------------------------------------------------------    
45 *        Internal functions prototypes    
46 --------------------------------------------------------------------*/
47
48 void arm_split_rfft_q31(
49     q31_t * pSrc,
50     uint32_t fftLen,
51     q31_t * pATable,
52     q31_t * pBTable,
53     q31_t * pDst,
54     uint32_t modifier);
55
56 void arm_split_rifft_q31(
57     q31_t * pSrc,
58     uint32_t fftLen,
59     q31_t * pATable,
60     q31_t * pBTable,
61     q31_t * pDst,
62     uint32_t modifier);
63
64 /**    
65 * @addtogroup RealFFT    
66 * @{    
67 */
68
69 /**    
70 * @brief Processing function for the Q31 RFFT/RIFFT.   
71 * @param[in]  *S    points to an instance of the Q31 RFFT/RIFFT structure.   
72 * @param[in]  *pSrc points to the input buffer.   
73 * @param[out] *pDst points to the output buffer.   
74 * @return none.   
75 *    
76 * \par Input an output formats:   
77 * \par    
78 * Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.   
79 * Hence the output format is different for different RFFT sizes.    
80 * The input and output formats for different RFFT sizes and number of bits to upscale are mentioned in the tables below for RFFT and RIFFT:   
81 * \par    
82 * \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"    
83 *    
84 * \par    
85 * \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"    
86 */
87 void arm_rfft_q31(
88     const arm_rfft_instance_q31 * S,
89     q31_t * pSrc,
90     q31_t * pDst)
91 {
92     const arm_cfft_instance_q31 *S_CFFT = S->pCfft;
93     uint32_t i;
94     uint32_t L2 = S->fftLenReal >> 1;
95
96     /* Calculation of RIFFT of input */
97     if(S->ifftFlagR == 1u)
98     {
99         /*  Real IFFT core process */
100         arm_split_rifft_q31(pSrc, L2, S->pTwiddleAReal,
101                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
102         
103         /* Complex IFFT process */
104         arm_cfft_q31(S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR);
105         
106         for(i=0;i<S->fftLenReal;i++)
107         {
108             pDst[i] = pDst[i] << 1;
109         }
110     }
111     else
112     {
113         /* Calculation of RFFT of input */
114         
115         /* Complex FFT process */
116         arm_cfft_q31(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR);
117
118         /*  Real FFT core process */
119         arm_split_rfft_q31(pSrc, L2, S->pTwiddleAReal,
120                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
121     }
122 }
123
124 /**    
125 * @} end of RealFFT group    
126 */
127
128 /**    
129 * @brief  Core Real FFT process    
130 * @param[in]   *pSrc                 points to the input buffer.    
131 * @param[in]   fftLen                  length of FFT.   
132 * @param[in]   *pATable             points to the twiddle Coef A buffer.    
133 * @param[in]   *pBTable             points to the twiddle Coef B buffer.    
134 * @param[out]  *pDst                 points to the output buffer.    
135 * @param[in]   modifier             twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.   
136 * @return none.    
137 */
138 void arm_split_rfft_q31(
139     q31_t * pSrc,
140     uint32_t fftLen,
141     q31_t * pATable,
142     q31_t * pBTable,
143     q31_t * pDst,
144     uint32_t modifier)
145 {
146     uint32_t i;                                    /* Loop Counter */
147     q31_t outR, outI;                              /* Temporary variables for output */
148     q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
149     q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
150     q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[(4u * fftLen) - 1u];
151     q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[(2u * fftLen) - 1u];
152
153     /* Init coefficient pointers */
154     pCoefA = &pATable[modifier * 2u];
155     pCoefB = &pBTable[modifier * 2u];
156
157     i = fftLen - 1u;
158
159     while(i > 0u)
160     {
161         /*    
162         outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]    
163         + pSrc[2 * n - 2 * i] * pBTable[2 * i] +    
164         pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
165         */
166
167         /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +    
168         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
169         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
170
171         CoefA1 = *pCoefA++;
172         CoefA2 = *pCoefA;
173
174         /* outR = (pSrc[2 * i] * pATable[2 * i] */    
175         mult_32x32_keep32_R(outR, *pIn1, CoefA1);
176
177         /* outI = pIn[2 * i] * pATable[2 * i + 1] */
178         mult_32x32_keep32_R(outI, *pIn1++, CoefA2);
179
180         /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
181         multSub_32x32_keep32_R(outR, *pIn1, CoefA2);
182
183         /* (pIn[2 * i + 1] * pATable[2 * i] */
184         multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
185
186         /* pSrc[2 * n - 2 * i] * pBTable[2 * i]  */
187         multSub_32x32_keep32_R(outR, *pIn2, CoefA2);
188         CoefB1 = *pCoefB;
189
190         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
191         multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
192
193         /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
194         multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
195
196         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
197         multSub_32x32_keep32_R(outI, *pIn2--, CoefA2);
198
199         /* write output */
200         *pOut1++ = outR;
201         *pOut1++ = outI;
202
203         /* write complex conjugate output */
204         *pOut2-- = -outI;
205         *pOut2-- = outR;
206
207         /* update coefficient pointer */
208         pCoefB = pCoefB + (modifier * 2u);
209         pCoefA = pCoefA + ((modifier * 2u) - 1u);
210
211         i--;
212     }
213     pDst[2u * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
214     pDst[(2u * fftLen) + 1u] = 0;
215
216     pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
217     pDst[1] = 0;
218 }
219
220 /**    
221 * @brief  Core Real IFFT process    
222 * @param[in]   *pSrc                 points to the input buffer.   
223 * @param[in]   fftLen                  length of FFT.    
224 * @param[in]   *pATable             points to the twiddle Coef A buffer.   
225 * @param[in]   *pBTable             points to the twiddle Coef B buffer.    
226 * @param[out]  *pDst                 points to the output buffer.   
227 * @param[in]   modifier             twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.   
228 * @return none.    
229 */
230 void arm_split_rifft_q31(
231     q31_t * pSrc,
232     uint32_t fftLen,
233     q31_t * pATable,
234     q31_t * pBTable,
235     q31_t * pDst,
236     uint32_t modifier)
237 {
238     q31_t outR, outI;                              /* Temporary variables for output */
239     q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
240     q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
241     q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[(2u * fftLen) + 1u];
242
243     pCoefA = &pATable[0];
244     pCoefB = &pBTable[0];
245
246     while(fftLen > 0u)
247     {
248         /*    
249         outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +    
250         pIn[2 * n - 2 * i] * pBTable[2 * i] -    
251         pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
252
253         outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -    
254         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
255         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);   
256         */
257         CoefA1 = *pCoefA++;
258         CoefA2 = *pCoefA;
259
260         /* outR = (pIn[2 * i] * pATable[2 * i] */
261         mult_32x32_keep32_R(outR, *pIn1, CoefA1);
262
263         /* - pIn[2 * i] * pATable[2 * i + 1] */
264         mult_32x32_keep32_R(outI, *pIn1++, -CoefA2);
265         
266         /* pIn[2 * i + 1] * pATable[2 * i + 1] */
267         multAcc_32x32_keep32_R(outR, *pIn1, CoefA2);
268
269         /* pIn[2 * i + 1] * pATable[2 * i] */
270         multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
271
272         /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
273         multAcc_32x32_keep32_R(outR, *pIn2, CoefA2);
274         CoefB1 = *pCoefB;
275
276         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
277         multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
278
279         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
280         multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
281
282         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
283         multAcc_32x32_keep32_R(outI, *pIn2--, CoefA2);
284
285         /* write output */
286         *pDst++ = outR;
287         *pDst++ = outI;
288
289         /* update coefficient pointer */
290         pCoefB = pCoefB + (modifier * 2u);
291         pCoefA = pCoefA + ((modifier * 2u) - 1u);
292
293         /* Decrement loop count */
294         fftLen--;
295     }
296 }