arm_rfft_q31.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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_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. #include "arm_math.h"
  42. /*--------------------------------------------------------------------
  43. * Internal functions prototypes
  44. --------------------------------------------------------------------*/
  45. void arm_split_rfft_q31(
  46. q31_t * pSrc,
  47. uint32_t fftLen,
  48. q31_t * pATable,
  49. q31_t * pBTable,
  50. q31_t * pDst,
  51. uint32_t modifier);
  52. void arm_split_rifft_q31(
  53. q31_t * pSrc,
  54. uint32_t fftLen,
  55. q31_t * pATable,
  56. q31_t * pBTable,
  57. q31_t * pDst,
  58. uint32_t modifier);
  59. /**
  60. * @addtogroup RealFFT
  61. * @{
  62. */
  63. /**
  64. * @brief Processing function for the Q31 RFFT/RIFFT.
  65. * @param[in] *S points to an instance of the Q31 RFFT/RIFFT structure.
  66. * @param[in] *pSrc points to the input buffer.
  67. * @param[out] *pDst points to the output buffer.
  68. * @return none.
  69. *
  70. * \par Input an output formats:
  71. * \par
  72. * Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.
  73. * Hence the output format is different for different RFFT sizes.
  74. * 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:
  75. * \par
  76. * \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"
  77. *
  78. * \par
  79. * \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"
  80. */
  81. void arm_rfft_q31(
  82. const arm_rfft_instance_q31 * S,
  83. q31_t * pSrc,
  84. q31_t * pDst)
  85. {
  86. const arm_cfft_instance_q31 *S_CFFT = S->pCfft;
  87. uint32_t i;
  88. uint32_t L2 = S->fftLenReal >> 1;
  89. /* Calculation of RIFFT of input */
  90. if(S->ifftFlagR == 1u)
  91. {
  92. /* Real IFFT core process */
  93. arm_split_rifft_q31(pSrc, L2, S->pTwiddleAReal,
  94. S->pTwiddleBReal, pDst, S->twidCoefRModifier);
  95. /* Complex IFFT process */
  96. arm_cfft_q31(S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR);
  97. for(i=0;i<S->fftLenReal;i++)
  98. {
  99. pDst[i] = pDst[i] << 1;
  100. }
  101. }
  102. else
  103. {
  104. /* Calculation of RFFT of input */
  105. /* Complex FFT process */
  106. arm_cfft_q31(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR);
  107. /* Real FFT core process */
  108. arm_split_rfft_q31(pSrc, L2, S->pTwiddleAReal,
  109. S->pTwiddleBReal, pDst, S->twidCoefRModifier);
  110. }
  111. }
  112. /**
  113. * @} end of RealFFT group
  114. */
  115. /**
  116. * @brief Core Real FFT process
  117. * @param[in] *pSrc points to the input buffer.
  118. * @param[in] fftLen length of FFT.
  119. * @param[in] *pATable points to the twiddle Coef A buffer.
  120. * @param[in] *pBTable points to the twiddle Coef B buffer.
  121. * @param[out] *pDst points to the output buffer.
  122. * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
  123. * @return none.
  124. */
  125. void arm_split_rfft_q31(
  126. q31_t * pSrc,
  127. uint32_t fftLen,
  128. q31_t * pATable,
  129. q31_t * pBTable,
  130. q31_t * pDst,
  131. uint32_t modifier)
  132. {
  133. uint32_t i; /* Loop Counter */
  134. q31_t outR, outI; /* Temporary variables for output */
  135. q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
  136. q31_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
  137. q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[(4u * fftLen) - 1u];
  138. q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[(2u * fftLen) - 1u];
  139. /* Init coefficient pointers */
  140. pCoefA = &pATable[modifier * 2u];
  141. pCoefB = &pBTable[modifier * 2u];
  142. i = fftLen - 1u;
  143. while(i > 0u)
  144. {
  145. /*
  146. outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]
  147. + pSrc[2 * n - 2 * i] * pBTable[2 * i] +
  148. pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
  149. */
  150. /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +
  151. pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
  152. pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
  153. CoefA1 = *pCoefA++;
  154. CoefA2 = *pCoefA;
  155. /* outR = (pSrc[2 * i] * pATable[2 * i] */
  156. mult_32x32_keep32_R(outR, *pIn1, CoefA1);
  157. /* outI = pIn[2 * i] * pATable[2 * i + 1] */
  158. mult_32x32_keep32_R(outI, *pIn1++, CoefA2);
  159. /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
  160. multSub_32x32_keep32_R(outR, *pIn1, CoefA2);
  161. /* (pIn[2 * i + 1] * pATable[2 * i] */
  162. multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
  163. /* pSrc[2 * n - 2 * i] * pBTable[2 * i] */
  164. multSub_32x32_keep32_R(outR, *pIn2, CoefA2);
  165. CoefB1 = *pCoefB;
  166. /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
  167. multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
  168. /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
  169. multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
  170. /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
  171. multSub_32x32_keep32_R(outI, *pIn2--, CoefA2);
  172. /* write output */
  173. *pOut1++ = outR;
  174. *pOut1++ = outI;
  175. /* write complex conjugate output */
  176. *pOut2-- = -outI;
  177. *pOut2-- = outR;
  178. /* update coefficient pointer */
  179. pCoefB = pCoefB + (modifier * 2u);
  180. pCoefA = pCoefA + ((modifier * 2u) - 1u);
  181. i--;
  182. }
  183. pDst[2u * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
  184. pDst[(2u * fftLen) + 1u] = 0;
  185. pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
  186. pDst[1] = 0;
  187. }
  188. /**
  189. * @brief Core Real IFFT process
  190. * @param[in] *pSrc points to the input buffer.
  191. * @param[in] fftLen length of FFT.
  192. * @param[in] *pATable points to the twiddle Coef A buffer.
  193. * @param[in] *pBTable points to the twiddle Coef B buffer.
  194. * @param[out] *pDst points to the output buffer.
  195. * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
  196. * @return none.
  197. */
  198. void arm_split_rifft_q31(
  199. q31_t * pSrc,
  200. uint32_t fftLen,
  201. q31_t * pATable,
  202. q31_t * pBTable,
  203. q31_t * pDst,
  204. uint32_t modifier)
  205. {
  206. q31_t outR, outI; /* Temporary variables for output */
  207. q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
  208. q31_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
  209. q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[(2u * fftLen) + 1u];
  210. pCoefA = &pATable[0];
  211. pCoefB = &pBTable[0];
  212. while(fftLen > 0u)
  213. {
  214. /*
  215. outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
  216. pIn[2 * n - 2 * i] * pBTable[2 * i] -
  217. pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
  218. outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -
  219. pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
  220. pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
  221. */
  222. CoefA1 = *pCoefA++;
  223. CoefA2 = *pCoefA;
  224. /* outR = (pIn[2 * i] * pATable[2 * i] */
  225. mult_32x32_keep32_R(outR, *pIn1, CoefA1);
  226. /* - pIn[2 * i] * pATable[2 * i + 1] */
  227. mult_32x32_keep32_R(outI, *pIn1++, -CoefA2);
  228. /* pIn[2 * i + 1] * pATable[2 * i + 1] */
  229. multAcc_32x32_keep32_R(outR, *pIn1, CoefA2);
  230. /* pIn[2 * i + 1] * pATable[2 * i] */
  231. multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
  232. /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
  233. multAcc_32x32_keep32_R(outR, *pIn2, CoefA2);
  234. CoefB1 = *pCoefB;
  235. /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
  236. multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
  237. /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
  238. multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
  239. /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
  240. multAcc_32x32_keep32_R(outI, *pIn2--, CoefA2);
  241. /* write output */
  242. *pDst++ = outR;
  243. *pDst++ = outI;
  244. /* update coefficient pointer */
  245. pCoefB = pCoefB + (modifier * 2u);
  246. pCoefA = pCoefA + ((modifier * 2u) - 1u);
  247. /* Decrement loop count */
  248. fftLen--;
  249. }
  250. }