arm_dct4_f32.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /* ----------------------------------------------------------------------
  2. * Project: CMSIS DSP Library
  3. * Title: arm_dct4_f32.c
  4. * Description: Processing function of DCT4 & IDCT4 F32
  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. * @ingroup groupTransforms
  31. */
  32. /**
  33. * @defgroup DCT4_IDCT4 DCT Type IV Functions
  34. * Representation of signals by minimum number of values is important for storage and transmission.
  35. * The possibility of large discontinuity between the beginning and end of a period of a signal
  36. * in DFT can be avoided by extending the signal so that it is even-symmetric.
  37. * Discrete Cosine Transform (DCT) is constructed such that its energy is heavily concentrated in the lower part of the
  38. * spectrum and is very widely used in signal and image coding applications.
  39. * The family of DCTs (DCT type- 1,2,3,4) is the outcome of different combinations of homogeneous boundary conditions.
  40. * DCT has an excellent energy-packing capability, hence has many applications and in data compression in particular.
  41. *
  42. * DCT is essentially the Discrete Fourier Transform(DFT) of an even-extended real signal.
  43. * Reordering of the input data makes the computation of DCT just a problem of
  44. * computing the DFT of a real signal with a few additional operations.
  45. * This approach provides regular, simple, and very efficient DCT algorithms for practical hardware and software implementations.
  46. *
  47. * DCT type-II can be implemented using Fast fourier transform (FFT) internally, as the transform is applied on real values, Real FFT can be used.
  48. * DCT4 is implemented using DCT2 as their implementations are similar except with some added pre-processing and post-processing.
  49. * DCT2 implementation can be described in the following steps:
  50. * - Re-ordering input
  51. * - Calculating Real FFT
  52. * - Multiplication of weights and Real FFT output and getting real part from the product.
  53. *
  54. * This process is explained by the block diagram below:
  55. * \image html DCT4.gif "Discrete Cosine Transform - type-IV"
  56. *
  57. * \par Algorithm:
  58. * The N-point type-IV DCT is defined as a real, linear transformation by the formula:
  59. * \image html DCT4Equation.gif
  60. * where <code>k = 0,1,2,.....N-1</code>
  61. *\par
  62. * Its inverse is defined as follows:
  63. * \image html IDCT4Equation.gif
  64. * where <code>n = 0,1,2,.....N-1</code>
  65. *\par
  66. * The DCT4 matrices become involutory (i.e. they are self-inverse) by multiplying with an overall scale factor of sqrt(2/N).
  67. * The symmetry of the transform matrix indicates that the fast algorithms for the forward
  68. * and inverse transform computation are identical.
  69. * Note that the implementation of Inverse DCT4 and DCT4 is same, hence same process function can be used for both.
  70. *
  71. * \par Lengths supported by the transform:
  72. * As DCT4 internally uses Real FFT, it supports all the lengths 128, 512, 2048 and 8192.
  73. * The library provides separate functions for Q15, Q31, and floating-point data types.
  74. * \par Instance Structure
  75. * The instances for Real FFT and FFT, cosine values table and twiddle factor table are stored in an instance data structure.
  76. * A separate instance structure must be defined for each transform.
  77. * There are separate instance structure declarations for each of the 3 supported data types.
  78. *
  79. * \par Initialization Functions
  80. * There is also an associated initialization function for each data type.
  81. * The initialization function performs the following operations:
  82. * - Sets the values of the internal structure fields.
  83. * - Initializes Real FFT as its process function is used internally in DCT4, by calling arm_rfft_init_f32().
  84. * \par
  85. * Use of the initialization function is optional.
  86. * However, if the initialization function is used, then the instance structure cannot be placed into a const data section.
  87. * To place an instance structure into a const data section, the instance structure must be manually initialized.
  88. * Manually initialize the instance structure as follows:
  89. * <pre>
  90. *arm_dct4_instance_f32 S = {N, Nby2, normalize, pTwiddle, pCosFactor, pRfft, pCfft};
  91. *arm_dct4_instance_q31 S = {N, Nby2, normalize, pTwiddle, pCosFactor, pRfft, pCfft};
  92. *arm_dct4_instance_q15 S = {N, Nby2, normalize, pTwiddle, pCosFactor, pRfft, pCfft};
  93. * </pre>
  94. * where \c N is the length of the DCT4; \c Nby2 is half of the length of the DCT4;
  95. * \c normalize is normalizing factor used and is equal to <code>sqrt(2/N)</code>;
  96. * \c pTwiddle points to the twiddle factor table;
  97. * \c pCosFactor points to the cosFactor table;
  98. * \c pRfft points to the real FFT instance;
  99. * \c pCfft points to the complex FFT instance;
  100. * The CFFT and RFFT structures also needs to be initialized, refer to arm_cfft_radix4_f32()
  101. * and arm_rfft_f32() respectively for details regarding static initialization.
  102. *
  103. * \par Fixed-Point Behavior
  104. * Care must be taken when using the fixed-point versions of the DCT4 transform functions.
  105. * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered.
  106. * Refer to the function specific documentation below for usage guidelines.
  107. */
  108. /**
  109. * @addtogroup DCT4_IDCT4
  110. * @{
  111. */
  112. /**
  113. * @brief Processing function for the floating-point DCT4/IDCT4.
  114. * @param[in] *S points to an instance of the floating-point DCT4/IDCT4 structure.
  115. * @param[in] *pState points to state buffer.
  116. * @param[in,out] *pInlineBuffer points to the in-place input and output buffer.
  117. * @return none.
  118. */
  119. void arm_dct4_f32(
  120. const arm_dct4_instance_f32 * S,
  121. float32_t * pState,
  122. float32_t * pInlineBuffer)
  123. {
  124. uint32_t i; /* Loop counter */
  125. float32_t *weights = S->pTwiddle; /* Pointer to the Weights table */
  126. float32_t *cosFact = S->pCosFactor; /* Pointer to the cos factors table */
  127. float32_t *pS1, *pS2, *pbuff; /* Temporary pointers for input buffer and pState buffer */
  128. float32_t in; /* Temporary variable */
  129. /* DCT4 computation involves DCT2 (which is calculated using RFFT)
  130. * along with some pre-processing and post-processing.
  131. * Computational procedure is explained as follows:
  132. * (a) Pre-processing involves multiplying input with cos factor,
  133. * r(n) = 2 * u(n) * cos(pi*(2*n+1)/(4*n))
  134. * where,
  135. * r(n) -- output of preprocessing
  136. * u(n) -- input to preprocessing(actual Source buffer)
  137. * (b) Calculation of DCT2 using FFT is divided into three steps:
  138. * Step1: Re-ordering of even and odd elements of input.
  139. * Step2: Calculating FFT of the re-ordered input.
  140. * Step3: Taking the real part of the product of FFT output and weights.
  141. * (c) Post-processing - DCT4 can be obtained from DCT2 output using the following equation:
  142. * Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
  143. * where,
  144. * Y4 -- DCT4 output, Y2 -- DCT2 output
  145. * (d) Multiplying the output with the normalizing factor sqrt(2/N).
  146. */
  147. /*-------- Pre-processing ------------*/
  148. /* Multiplying input with cos factor i.e. r(n) = 2 * x(n) * cos(pi*(2*n+1)/(4*n)) */
  149. arm_scale_f32(pInlineBuffer, 2.0f, pInlineBuffer, S->N);
  150. arm_mult_f32(pInlineBuffer, cosFact, pInlineBuffer, S->N);
  151. /* ----------------------------------------------------------------
  152. * Step1: Re-ordering of even and odd elements as,
  153. * pState[i] = pInlineBuffer[2*i] and
  154. * pState[N-i-1] = pInlineBuffer[2*i+1] where i = 0 to N/2
  155. ---------------------------------------------------------------------*/
  156. /* pS1 initialized to pState */
  157. pS1 = pState;
  158. /* pS2 initialized to pState+N-1, so that it points to the end of the state buffer */
  159. pS2 = pState + (S->N - 1U);
  160. /* pbuff initialized to input buffer */
  161. pbuff = pInlineBuffer;
  162. #if defined (ARM_MATH_DSP)
  163. /* Run the below code for Cortex-M4 and Cortex-M3 */
  164. /* Initializing the loop counter to N/2 >> 2 for loop unrolling by 4 */
  165. i = (uint32_t) S->Nby2 >> 2U;
  166. /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
  167. ** a second loop below computes the remaining 1 to 3 samples. */
  168. do
  169. {
  170. /* Re-ordering of even and odd elements */
  171. /* pState[i] = pInlineBuffer[2*i] */
  172. *pS1++ = *pbuff++;
  173. /* pState[N-i-1] = pInlineBuffer[2*i+1] */
  174. *pS2-- = *pbuff++;
  175. *pS1++ = *pbuff++;
  176. *pS2-- = *pbuff++;
  177. *pS1++ = *pbuff++;
  178. *pS2-- = *pbuff++;
  179. *pS1++ = *pbuff++;
  180. *pS2-- = *pbuff++;
  181. /* Decrement the loop counter */
  182. i--;
  183. } while (i > 0U);
  184. /* pbuff initialized to input buffer */
  185. pbuff = pInlineBuffer;
  186. /* pS1 initialized to pState */
  187. pS1 = pState;
  188. /* Initializing the loop counter to N/4 instead of N for loop unrolling */
  189. i = (uint32_t) S->N >> 2U;
  190. /* Processing with loop unrolling 4 times as N is always multiple of 4.
  191. * Compute 4 outputs at a time */
  192. do
  193. {
  194. /* Writing the re-ordered output back to inplace input buffer */
  195. *pbuff++ = *pS1++;
  196. *pbuff++ = *pS1++;
  197. *pbuff++ = *pS1++;
  198. *pbuff++ = *pS1++;
  199. /* Decrement the loop counter */
  200. i--;
  201. } while (i > 0U);
  202. /* ---------------------------------------------------------
  203. * Step2: Calculate RFFT for N-point input
  204. * ---------------------------------------------------------- */
  205. /* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
  206. arm_rfft_f32(S->pRfft, pInlineBuffer, pState);
  207. /*----------------------------------------------------------------------
  208. * Step3: Multiply the FFT output with the weights.
  209. *----------------------------------------------------------------------*/
  210. arm_cmplx_mult_cmplx_f32(pState, weights, pState, S->N);
  211. /* ----------- Post-processing ---------- */
  212. /* DCT-IV can be obtained from DCT-II by the equation,
  213. * Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
  214. * Hence, Y4(0) = Y2(0)/2 */
  215. /* Getting only real part from the output and Converting to DCT-IV */
  216. /* Initializing the loop counter to N >> 2 for loop unrolling by 4 */
  217. i = ((uint32_t) S->N - 1U) >> 2U;
  218. /* pbuff initialized to input buffer. */
  219. pbuff = pInlineBuffer;
  220. /* pS1 initialized to pState */
  221. pS1 = pState;
  222. /* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
  223. in = *pS1++ * (float32_t) 0.5;
  224. /* input buffer acts as inplace, so output values are stored in the input itself. */
  225. *pbuff++ = in;
  226. /* pState pointer is incremented twice as the real values are located alternatively in the array */
  227. pS1++;
  228. /* First part of the processing with loop unrolling. Compute 4 outputs at a time.
  229. ** a second loop below computes the remaining 1 to 3 samples. */
  230. do
  231. {
  232. /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
  233. /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
  234. in = *pS1++ - in;
  235. *pbuff++ = in;
  236. /* points to the next real value */
  237. pS1++;
  238. in = *pS1++ - in;
  239. *pbuff++ = in;
  240. pS1++;
  241. in = *pS1++ - in;
  242. *pbuff++ = in;
  243. pS1++;
  244. in = *pS1++ - in;
  245. *pbuff++ = in;
  246. pS1++;
  247. /* Decrement the loop counter */
  248. i--;
  249. } while (i > 0U);
  250. /* If the blockSize is not a multiple of 4, compute any remaining output samples here.
  251. ** No loop unrolling is used. */
  252. i = ((uint32_t) S->N - 1U) % 0x4U;
  253. while (i > 0U)
  254. {
  255. /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
  256. /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
  257. in = *pS1++ - in;
  258. *pbuff++ = in;
  259. /* points to the next real value */
  260. pS1++;
  261. /* Decrement the loop counter */
  262. i--;
  263. }
  264. /*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
  265. /* Initializing the loop counter to N/4 instead of N for loop unrolling */
  266. i = (uint32_t) S->N >> 2U;
  267. /* pbuff initialized to the pInlineBuffer(now contains the output values) */
  268. pbuff = pInlineBuffer;
  269. /* Processing with loop unrolling 4 times as N is always multiple of 4. Compute 4 outputs at a time */
  270. do
  271. {
  272. /* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
  273. in = *pbuff;
  274. *pbuff++ = in * S->normalize;
  275. in = *pbuff;
  276. *pbuff++ = in * S->normalize;
  277. in = *pbuff;
  278. *pbuff++ = in * S->normalize;
  279. in = *pbuff;
  280. *pbuff++ = in * S->normalize;
  281. /* Decrement the loop counter */
  282. i--;
  283. } while (i > 0U);
  284. #else
  285. /* Run the below code for Cortex-M0 */
  286. /* Initializing the loop counter to N/2 */
  287. i = (uint32_t) S->Nby2;
  288. do
  289. {
  290. /* Re-ordering of even and odd elements */
  291. /* pState[i] = pInlineBuffer[2*i] */
  292. *pS1++ = *pbuff++;
  293. /* pState[N-i-1] = pInlineBuffer[2*i+1] */
  294. *pS2-- = *pbuff++;
  295. /* Decrement the loop counter */
  296. i--;
  297. } while (i > 0U);
  298. /* pbuff initialized to input buffer */
  299. pbuff = pInlineBuffer;
  300. /* pS1 initialized to pState */
  301. pS1 = pState;
  302. /* Initializing the loop counter */
  303. i = (uint32_t) S->N;
  304. do
  305. {
  306. /* Writing the re-ordered output back to inplace input buffer */
  307. *pbuff++ = *pS1++;
  308. /* Decrement the loop counter */
  309. i--;
  310. } while (i > 0U);
  311. /* ---------------------------------------------------------
  312. * Step2: Calculate RFFT for N-point input
  313. * ---------------------------------------------------------- */
  314. /* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
  315. arm_rfft_f32(S->pRfft, pInlineBuffer, pState);
  316. /*----------------------------------------------------------------------
  317. * Step3: Multiply the FFT output with the weights.
  318. *----------------------------------------------------------------------*/
  319. arm_cmplx_mult_cmplx_f32(pState, weights, pState, S->N);
  320. /* ----------- Post-processing ---------- */
  321. /* DCT-IV can be obtained from DCT-II by the equation,
  322. * Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
  323. * Hence, Y4(0) = Y2(0)/2 */
  324. /* Getting only real part from the output and Converting to DCT-IV */
  325. /* pbuff initialized to input buffer. */
  326. pbuff = pInlineBuffer;
  327. /* pS1 initialized to pState */
  328. pS1 = pState;
  329. /* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
  330. in = *pS1++ * (float32_t) 0.5;
  331. /* input buffer acts as inplace, so output values are stored in the input itself. */
  332. *pbuff++ = in;
  333. /* pState pointer is incremented twice as the real values are located alternatively in the array */
  334. pS1++;
  335. /* Initializing the loop counter */
  336. i = ((uint32_t) S->N - 1U);
  337. do
  338. {
  339. /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
  340. /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
  341. in = *pS1++ - in;
  342. *pbuff++ = in;
  343. /* points to the next real value */
  344. pS1++;
  345. /* Decrement the loop counter */
  346. i--;
  347. } while (i > 0U);
  348. /*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
  349. /* Initializing the loop counter */
  350. i = (uint32_t) S->N;
  351. /* pbuff initialized to the pInlineBuffer(now contains the output values) */
  352. pbuff = pInlineBuffer;
  353. do
  354. {
  355. /* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
  356. in = *pbuff;
  357. *pbuff++ = in * S->normalize;
  358. /* Decrement the loop counter */
  359. i--;
  360. } while (i > 0U);
  361. #endif /* #if defined (ARM_MATH_DSP) */
  362. }
  363. /**
  364. * @} end of DCT4_IDCT4 group
  365. */