arm_dct4_q15.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: arm_dct4_q15.c
  4. * Description: Processing function of DCT4 & IDCT4 Q15
  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. /**
  30. * @addtogroup DCT4_IDCT4
  31. * @{
  32. */
  33. /**
  34. * @brief Processing function for the Q15 DCT4/IDCT4.
  35. * @param[in] *S points to an instance of the Q15 DCT4 structure.
  36. * @param[in] *pState points to state buffer.
  37. * @param[in,out] *pInlineBuffer points to the in-place input and output buffer.
  38. * @return none.
  39. *
  40. * \par Input an output formats:
  41. * Internally inputs are downscaled in the RFFT process function to avoid overflows.
  42. * Number of bits downscaled, depends on the size of the transform.
  43. * The input and output formats for different DCT sizes and number of bits to upscale are mentioned in the table below:
  44. *
  45. * \image html dct4FormatsQ15Table.gif
  46. */
  47. void arm_dct4_q15(
  48. const arm_dct4_instance_q15 * S,
  49. q15_t * pState,
  50. q15_t * pInlineBuffer)
  51. {
  52. uint32_t i; /* Loop counter */
  53. q15_t *weights = S->pTwiddle; /* Pointer to the Weights table */
  54. q15_t *cosFact = S->pCosFactor; /* Pointer to the cos factors table */
  55. q15_t *pS1, *pS2, *pbuff; /* Temporary pointers for input buffer and pState buffer */
  56. q15_t in; /* Temporary variable */
  57. /* DCT4 computation involves DCT2 (which is calculated using RFFT)
  58. * along with some pre-processing and post-processing.
  59. * Computational procedure is explained as follows:
  60. * (a) Pre-processing involves multiplying input with cos factor,
  61. * r(n) = 2 * u(n) * cos(pi*(2*n+1)/(4*n))
  62. * where,
  63. * r(n) -- output of preprocessing
  64. * u(n) -- input to preprocessing(actual Source buffer)
  65. * (b) Calculation of DCT2 using FFT is divided into three steps:
  66. * Step1: Re-ordering of even and odd elements of input.
  67. * Step2: Calculating FFT of the re-ordered input.
  68. * Step3: Taking the real part of the product of FFT output and weights.
  69. * (c) Post-processing - DCT4 can be obtained from DCT2 output using the following equation:
  70. * Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
  71. * where,
  72. * Y4 -- DCT4 output, Y2 -- DCT2 output
  73. * (d) Multiplying the output with the normalizing factor sqrt(2/N).
  74. */
  75. /*-------- Pre-processing ------------*/
  76. /* Multiplying input with cos factor i.e. r(n) = 2 * x(n) * cos(pi*(2*n+1)/(4*n)) */
  77. arm_mult_q15(pInlineBuffer, cosFact, pInlineBuffer, S->N);
  78. arm_shift_q15(pInlineBuffer, 1, pInlineBuffer, S->N);
  79. /* ----------------------------------------------------------------
  80. * Step1: Re-ordering of even and odd elements as
  81. * pState[i] = pInlineBuffer[2*i] and
  82. * pState[N-i-1] = pInlineBuffer[2*i+1] where i = 0 to N/2
  83. ---------------------------------------------------------------------*/
  84. /* pS1 initialized to pState */
  85. pS1 = pState;
  86. /* pS2 initialized to pState+N-1, so that it points to the end of the state buffer */
  87. pS2 = pState + (S->N - 1U);
  88. /* pbuff initialized to input buffer */
  89. pbuff = pInlineBuffer;
  90. #if defined (ARM_MATH_DSP)
  91. /* Run the below code for Cortex-M4 and Cortex-M3 */
  92. /* Initializing the loop counter to N/2 >> 2 for loop unrolling by 4 */
  93. i = (uint32_t) S->Nby2 >> 2U;
  94. /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
  95. ** a second loop below computes the remaining 1 to 3 samples. */
  96. do
  97. {
  98. /* Re-ordering of even and odd elements */
  99. /* pState[i] = pInlineBuffer[2*i] */
  100. *pS1++ = *pbuff++;
  101. /* pState[N-i-1] = pInlineBuffer[2*i+1] */
  102. *pS2-- = *pbuff++;
  103. *pS1++ = *pbuff++;
  104. *pS2-- = *pbuff++;
  105. *pS1++ = *pbuff++;
  106. *pS2-- = *pbuff++;
  107. *pS1++ = *pbuff++;
  108. *pS2-- = *pbuff++;
  109. /* Decrement the loop counter */
  110. i--;
  111. } while (i > 0U);
  112. /* pbuff initialized to input buffer */
  113. pbuff = pInlineBuffer;
  114. /* pS1 initialized to pState */
  115. pS1 = pState;
  116. /* Initializing the loop counter to N/4 instead of N for loop unrolling */
  117. i = (uint32_t) S->N >> 2U;
  118. /* Processing with loop unrolling 4 times as N is always multiple of 4.
  119. * Compute 4 outputs at a time */
  120. do
  121. {
  122. /* Writing the re-ordered output back to inplace input buffer */
  123. *pbuff++ = *pS1++;
  124. *pbuff++ = *pS1++;
  125. *pbuff++ = *pS1++;
  126. *pbuff++ = *pS1++;
  127. /* Decrement the loop counter */
  128. i--;
  129. } while (i > 0U);
  130. /* ---------------------------------------------------------
  131. * Step2: Calculate RFFT for N-point input
  132. * ---------------------------------------------------------- */
  133. /* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
  134. arm_rfft_q15(S->pRfft, pInlineBuffer, pState);
  135. /*----------------------------------------------------------------------
  136. * Step3: Multiply the FFT output with the weights.
  137. *----------------------------------------------------------------------*/
  138. arm_cmplx_mult_cmplx_q15(pState, weights, pState, S->N);
  139. /* The output of complex multiplication is in 3.13 format.
  140. * Hence changing the format of N (i.e. 2*N elements) complex numbers to 1.15 format by shifting left by 2 bits. */
  141. arm_shift_q15(pState, 2, pState, S->N * 2);
  142. /* ----------- Post-processing ---------- */
  143. /* DCT-IV can be obtained from DCT-II by the equation,
  144. * Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
  145. * Hence, Y4(0) = Y2(0)/2 */
  146. /* Getting only real part from the output and Converting to DCT-IV */
  147. /* Initializing the loop counter to N >> 2 for loop unrolling by 4 */
  148. i = ((uint32_t) S->N - 1U) >> 2U;
  149. /* pbuff initialized to input buffer. */
  150. pbuff = pInlineBuffer;
  151. /* pS1 initialized to pState */
  152. pS1 = pState;
  153. /* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
  154. in = *pS1++ >> 1U;
  155. /* input buffer acts as inplace, so output values are stored in the input itself. */
  156. *pbuff++ = in;
  157. /* pState pointer is incremented twice as the real values are located alternatively in the array */
  158. pS1++;
  159. /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
  160. ** a second loop below computes the remaining 1 to 3 samples. */
  161. do
  162. {
  163. /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
  164. /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
  165. in = *pS1++ - in;
  166. *pbuff++ = in;
  167. /* points to the next real value */
  168. pS1++;
  169. in = *pS1++ - in;
  170. *pbuff++ = in;
  171. pS1++;
  172. in = *pS1++ - in;
  173. *pbuff++ = in;
  174. pS1++;
  175. in = *pS1++ - in;
  176. *pbuff++ = in;
  177. pS1++;
  178. /* Decrement the loop counter */
  179. i--;
  180. } while (i > 0U);
  181. /* If the blockSize is not a multiple of 4, compute any remaining output samples here.
  182. ** No loop unrolling is used. */
  183. i = ((uint32_t) S->N - 1U) % 0x4U;
  184. while (i > 0U)
  185. {
  186. /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
  187. /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
  188. in = *pS1++ - in;
  189. *pbuff++ = in;
  190. /* points to the next real value */
  191. pS1++;
  192. /* Decrement the loop counter */
  193. i--;
  194. }
  195. /*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
  196. /* Initializing the loop counter to N/4 instead of N for loop unrolling */
  197. i = (uint32_t) S->N >> 2U;
  198. /* pbuff initialized to the pInlineBuffer(now contains the output values) */
  199. pbuff = pInlineBuffer;
  200. /* Processing with loop unrolling 4 times as N is always multiple of 4. Compute 4 outputs at a time */
  201. do
  202. {
  203. /* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
  204. in = *pbuff;
  205. *pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
  206. in = *pbuff;
  207. *pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
  208. in = *pbuff;
  209. *pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
  210. in = *pbuff;
  211. *pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
  212. /* Decrement the loop counter */
  213. i--;
  214. } while (i > 0U);
  215. #else
  216. /* Run the below code for Cortex-M0 */
  217. /* Initializing the loop counter to N/2 */
  218. i = (uint32_t) S->Nby2;
  219. do
  220. {
  221. /* Re-ordering of even and odd elements */
  222. /* pState[i] = pInlineBuffer[2*i] */
  223. *pS1++ = *pbuff++;
  224. /* pState[N-i-1] = pInlineBuffer[2*i+1] */
  225. *pS2-- = *pbuff++;
  226. /* Decrement the loop counter */
  227. i--;
  228. } while (i > 0U);
  229. /* pbuff initialized to input buffer */
  230. pbuff = pInlineBuffer;
  231. /* pS1 initialized to pState */
  232. pS1 = pState;
  233. /* Initializing the loop counter */
  234. i = (uint32_t) S->N;
  235. do
  236. {
  237. /* Writing the re-ordered output back to inplace input buffer */
  238. *pbuff++ = *pS1++;
  239. /* Decrement the loop counter */
  240. i--;
  241. } while (i > 0U);
  242. /* ---------------------------------------------------------
  243. * Step2: Calculate RFFT for N-point input
  244. * ---------------------------------------------------------- */
  245. /* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
  246. arm_rfft_q15(S->pRfft, pInlineBuffer, pState);
  247. /*----------------------------------------------------------------------
  248. * Step3: Multiply the FFT output with the weights.
  249. *----------------------------------------------------------------------*/
  250. arm_cmplx_mult_cmplx_q15(pState, weights, pState, S->N);
  251. /* The output of complex multiplication is in 3.13 format.
  252. * Hence changing the format of N (i.e. 2*N elements) complex numbers to 1.15 format by shifting left by 2 bits. */
  253. arm_shift_q15(pState, 2, pState, S->N * 2);
  254. /* ----------- Post-processing ---------- */
  255. /* DCT-IV can be obtained from DCT-II by the equation,
  256. * Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
  257. * Hence, Y4(0) = Y2(0)/2 */
  258. /* Getting only real part from the output and Converting to DCT-IV */
  259. /* Initializing the loop counter */
  260. i = ((uint32_t) S->N - 1U);
  261. /* pbuff initialized to input buffer. */
  262. pbuff = pInlineBuffer;
  263. /* pS1 initialized to pState */
  264. pS1 = pState;
  265. /* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
  266. in = *pS1++ >> 1U;
  267. /* input buffer acts as inplace, so output values are stored in the input itself. */
  268. *pbuff++ = in;
  269. /* pState pointer is incremented twice as the real values are located alternatively in the array */
  270. pS1++;
  271. do
  272. {
  273. /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
  274. /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
  275. in = *pS1++ - in;
  276. *pbuff++ = in;
  277. /* points to the next real value */
  278. pS1++;
  279. /* Decrement the loop counter */
  280. i--;
  281. } while (i > 0U);
  282. /*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
  283. /* Initializing the loop counter */
  284. i = (uint32_t) S->N;
  285. /* pbuff initialized to the pInlineBuffer(now contains the output values) */
  286. pbuff = pInlineBuffer;
  287. do
  288. {
  289. /* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
  290. in = *pbuff;
  291. *pbuff++ = ((q15_t) (((q31_t) in * S->normalize) >> 15));
  292. /* Decrement the loop counter */
  293. i--;
  294. } while (i > 0U);
  295. #endif /* #if defined (ARM_MATH_DSP) */
  296. }
  297. /**
  298. * @} end of DCT4_IDCT4 group
  299. */