CMSIS DSP Software Library: arm_dct4_q31.c Source File

- Main Page
- Modules
- Data Structures
- Files
- Examples

- File List
- Globals

# arm_dct4_q31.c

Go to the documentation of this file.

    00001 /* ----------------------------------------------------------------------
    00002 * Copyright (C) 2010 ARM Limited. All rights reserved.
    00003 *
    00004 * $Date:        15. July 2011
    00005 * $Revision:    V1.0.10
    00006 *
    00007 * Project:      CMSIS DSP Library
    00008 * Title:        arm_dct4_q31.c
    00009 *
    00010 * Description:  Processing function of DCT4 & IDCT4 Q31.
    00011 *
    00012 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
    00013 *
    00014 * Version 1.0.10 2011/7/15
    00015 *    Big Endian support added and Merged M0 and M3/M4 Source code.
    00016 *
    00017 * Version 1.0.3 2010/11/29
    00018 *    Re-organized the CMSIS folders and updated documentation.
    00019 *
    00020 * Version 1.0.2 2010/11/11
    00021 *    Documentation updated.
    00022 *
    00023 * Version 1.0.1 2010/10/05
    00024 *    Production release and review comments incorporated.
    00025 *
    00026 * Version 1.0.0 2010/09/20
    00027 *    Production release and review comments incorporated.
    00028 * -------------------------------------------------------------------- */
    00029
    00030 #include "arm_math.h"
    00031
    00053 void arm_dct4_q31(
    00054   const arm_dct4_instance_q31 * S,
    00055   q31_t * pState,
    00056   q31_t * pInlineBuffer)
    00057 {
    00058   uint16_t i;                                    /* Loop counter */
    00059   q31_t *weights = S->pTwiddle;                  /* Pointer to the Weights table */
    00060   q31_t *cosFact = S->pCosFactor;                /* Pointer to the cos factors table */
    00061   q31_t *pS1, *pS2, *pbuff;                      /* Temporary pointers for input buffer and pState buffer */
    00062   q31_t in;                                      /* Temporary variable */
    00063
    00064
    00065   /* DCT4 computation involves DCT2 (which is calculated using RFFT)
    00066    * along with some pre-processing and post-processing.
    00067    * Computational procedure is explained as follows:
    00068    * (a) Pre-processing involves multiplying input with cos factor,
    00069    *     r(n) = 2 * u(n) * cos(pi*(2*n+1)/(4*n))
    00070    *              where,
    00071    *                 r(n) -- output of preprocessing
    00072    *                 u(n) -- input to preprocessing(actual Source buffer)
    00073    * (b) Calculation of DCT2 using FFT is divided into three steps:
    00074    *                  Step1: Re-ordering of even and odd elements of input.
    00075    *                  Step2: Calculating FFT of the re-ordered input.
    00076    *                  Step3: Taking the real part of the product of FFT output and weights.
    00077    * (c) Post-processing - DCT4 can be obtained from DCT2 output using the following equation:
    00078    *                   Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
    00079    *                        where,
    00080    *                           Y4 -- DCT4 output,   Y2 -- DCT2 output
    00081    * (d) Multiplying the output with the normalizing factor sqrt(2/N).
    00082    */
    00083
    00084         /*-------- Pre-processing ------------*/
    00085   /* Multiplying input with cos factor i.e. r(n) = 2 * x(n) * cos(pi*(2*n+1)/(4*n)) */
    00086   arm_mult_q31(pInlineBuffer, cosFact, pInlineBuffer, S->N);
    00087   arm_shift_q31(pInlineBuffer, 1, pInlineBuffer, S->N);
    00088
    00089   /* ----------------------------------------------------------------
    00090    * Step1: Re-ordering of even and odd elements as
    00091    *             pState[i] =  pInlineBuffer[2*i] and
    00092    *             pState[N-i-1] = pInlineBuffer[2*i+1] where i = 0 to N/2
    00093    ---------------------------------------------------------------------*/
    00094
    00095   /* pS1 initialized to pState */
    00096   pS1 = pState;
    00097
    00098   /* pS2 initialized to pState+N-1, so that it points to the end of the state buffer */
    00099   pS2 = pState + (S->N - 1u);
    00100
    00101   /* pbuff initialized to input buffer */
    00102   pbuff = pInlineBuffer;
    00103
    00104 #ifndef ARM_MATH_CM0
    00105
    00106   /* Run the below code for Cortex-M4 and Cortex-M3 */
    00107
    00108   /* Initializing the loop counter to N/2 >> 2 for loop unrolling by 4 */
    00109   i = S->Nby2 >> 2u;
    00110
    00111   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.
    00112    ** a second loop below computes the remaining 1 to 3 samples. */
    00113   do
    00114   {
    00115     /* Re-ordering of even and odd elements */
    00116     /* pState[i] =  pInlineBuffer[2*i] */
    00117     *pS1++ = *pbuff++;
    00118     /* pState[N-i-1] = pInlineBuffer[2*i+1] */
    00119     *pS2-- = *pbuff++;
    00120
    00121     *pS1++ = *pbuff++;
    00122     *pS2-- = *pbuff++;
    00123
    00124     *pS1++ = *pbuff++;
    00125     *pS2-- = *pbuff++;
    00126
    00127     *pS1++ = *pbuff++;
    00128     *pS2-- = *pbuff++;
    00129
    00130     /* Decrement the loop counter */
    00131     i--;
    00132   } while(i > 0u);
    00133
    00134   /* pbuff initialized to input buffer */
    00135   pbuff = pInlineBuffer;
    00136
    00137   /* pS1 initialized to pState */
    00138   pS1 = pState;
    00139
    00140   /* Initializing the loop counter to N/4 instead of N for loop unrolling */
    00141   i = S->N >> 2u;
    00142
    00143   /* Processing with loop unrolling 4 times as N is always multiple of 4.
    00144    * Compute 4 outputs at a time */
    00145   do
    00146   {
    00147     /* Writing the re-ordered output back to inplace input buffer */
    00148     *pbuff++ = *pS1++;
    00149     *pbuff++ = *pS1++;
    00150     *pbuff++ = *pS1++;
    00151     *pbuff++ = *pS1++;
    00152
    00153     /* Decrement the loop counter */
    00154     i--;
    00155   } while(i > 0u);
    00156
    00157
    00158   /* ---------------------------------------------------------
    00159    *     Step2: Calculate RFFT for N-point input
    00160    * ---------------------------------------------------------- */
    00161   /* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
    00162   arm_rfft_q31(S->pRfft, pInlineBuffer, pState);
    00163
    00164   /*----------------------------------------------------------------------
    00165    *  Step3: Multiply the FFT output with the weights.
    00166    *----------------------------------------------------------------------*/
    00167   arm_cmplx_mult_cmplx_q31(pState, weights, pState, S->N);
    00168
    00169   /* The output of complex multiplication is in 3.29 format.
    00170    * Hence changing the format of N (i.e. 2*N elements) complex numbers to 1.31 format by shifting left by 2 bits. */
    00171   arm_shift_q31(pState, 2, pState, S->N * 2);
    00172
    00173   /* ----------- Post-processing ---------- */
    00174   /* DCT-IV can be obtained from DCT-II by the equation,
    00175    *       Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
    00176    *       Hence, Y4(0) = Y2(0)/2  */
    00177   /* Getting only real part from the output and Converting to DCT-IV */
    00178
    00179   /* Initializing the loop counter to N >> 2 for loop unrolling by 4 */
    00180   i = (S->N - 1u) >> 2u;
    00181
    00182   /* pbuff initialized to input buffer. */
    00183   pbuff = pInlineBuffer;
    00184
    00185   /* pS1 initialized to pState */
    00186   pS1 = pState;
    00187
    00188   /* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
    00189   in = *pS1++ >> 1u;
    00190   /* input buffer acts as inplace, so output values are stored in the input itself. */
    00191   *pbuff++ = in;
    00192
    00193   /* pState pointer is incremented twice as the real values are located alternatively in the array */
    00194   pS1++;
    00195
    00196   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.
    00197    ** a second loop below computes the remaining 1 to 3 samples. */
    00198   do
    00199   {
    00200     /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
    00201     /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
    00202     in = *pS1++ - in;
    00203     *pbuff++ = in;
    00204     /* points to the next real value */
    00205     pS1++;
    00206
    00207     in = *pS1++ - in;
    00208     *pbuff++ = in;
    00209     pS1++;
    00210
    00211     in = *pS1++ - in;
    00212     *pbuff++ = in;
    00213     pS1++;
    00214
    00215     in = *pS1++ - in;
    00216     *pbuff++ = in;
    00217     pS1++;
    00218
    00219     /* Decrement the loop counter */
    00220     i--;
    00221   } while(i > 0u);
    00222
    00223   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.
    00224    ** No loop unrolling is used. */
    00225   i = (S->N - 1u) % 0x4u;
    00226
    00227   while(i > 0u)
    00228   {
    00229     /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
    00230     /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
    00231     in = *pS1++ - in;
    00232     *pbuff++ = in;
    00233     /* points to the next real value */
    00234     pS1++;
    00235
    00236     /* Decrement the loop counter */
    00237     i--;
    00238   }
    00239
    00240
    00241         /*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
    00242
    00243   /* Initializing the loop counter to N/4 instead of N for loop unrolling */
    00244   i = S->N >> 2u;
    00245
    00246   /* pbuff initialized to the pInlineBuffer(now contains the output values) */
    00247   pbuff = pInlineBuffer;
    00248
    00249   /* Processing with loop unrolling 4 times as N is always multiple of 4.  Compute 4 outputs at a time */
    00250   do
    00251   {
    00252     /* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
    00253     in = *pbuff;
    00254     *pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
    00255
    00256     in = *pbuff;
    00257     *pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
    00258
    00259     in = *pbuff;
    00260     *pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
    00261
    00262     in = *pbuff;
    00263     *pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
    00264
    00265     /* Decrement the loop counter */
    00266     i--;
    00267   } while(i > 0u);
    00268
    00269
    00270 #else
    00271
    00272   /* Run the below code for Cortex-M0 */
    00273
    00274   /* Initializing the loop counter to N/2 */
    00275   i = S->Nby2;
    00276
    00277   do
    00278   {
    00279     /* Re-ordering of even and odd elements */
    00280     /* pState[i] =  pInlineBuffer[2*i] */
    00281     *pS1++ = *pbuff++;
    00282     /* pState[N-i-1] = pInlineBuffer[2*i+1] */
    00283     *pS2-- = *pbuff++;
    00284
    00285     /* Decrement the loop counter */
    00286     i--;
    00287   } while(i > 0u);
    00288
    00289   /* pbuff initialized to input buffer */
    00290   pbuff = pInlineBuffer;
    00291
    00292   /* pS1 initialized to pState */
    00293   pS1 = pState;
    00294
    00295   /* Initializing the loop counter */
    00296   i = S->N;
    00297
    00298   do
    00299   {
    00300     /* Writing the re-ordered output back to inplace input buffer */
    00301     *pbuff++ = *pS1++;
    00302
    00303     /* Decrement the loop counter */
    00304     i--;
    00305   } while(i > 0u);
    00306
    00307
    00308   /* ---------------------------------------------------------
    00309    *     Step2: Calculate RFFT for N-point input
    00310    * ---------------------------------------------------------- */
    00311   /* pInlineBuffer is real input of length N , pState is the complex output of length 2N */
    00312   arm_rfft_q31(S->pRfft, pInlineBuffer, pState);
    00313
    00314   /*----------------------------------------------------------------------
    00315    *  Step3: Multiply the FFT output with the weights.
    00316    *----------------------------------------------------------------------*/
    00317   arm_cmplx_mult_cmplx_q31(pState, weights, pState, S->N);
    00318
    00319   /* The output of complex multiplication is in 3.29 format.
    00320    * Hence changing the format of N (i.e. 2*N elements) complex numbers to 1.31 format by shifting left by 2 bits. */
    00321   arm_shift_q31(pState, 2, pState, S->N * 2);
    00322
    00323   /* ----------- Post-processing ---------- */
    00324   /* DCT-IV can be obtained from DCT-II by the equation,
    00325    *       Y4(k) = Y2(k) - Y4(k-1) and Y4(-1) = Y4(0)
    00326    *       Hence, Y4(0) = Y2(0)/2  */
    00327   /* Getting only real part from the output and Converting to DCT-IV */
    00328
    00329   /* pbuff initialized to input buffer. */
    00330   pbuff = pInlineBuffer;
    00331
    00332   /* pS1 initialized to pState */
    00333   pS1 = pState;
    00334
    00335   /* Calculating Y4(0) from Y2(0) using Y4(0) = Y2(0)/2 */
    00336   in = *pS1++ >> 1u;
    00337   /* input buffer acts as inplace, so output values are stored in the input itself. */
    00338   *pbuff++ = in;
    00339
    00340   /* pState pointer is incremented twice as the real values are located alternatively in the array */
    00341   pS1++;
    00342
    00343   /* Initializing the loop counter */
    00344   i = (S->N - 1u);
    00345
    00346   while(i > 0u)
    00347   {
    00348     /* Calculating Y4(1) to Y4(N-1) from Y2 using equation Y4(k) = Y2(k) - Y4(k-1) */
    00349     /* pState pointer (pS1) is incremented twice as the real values are located alternatively in the array */
    00350     in = *pS1++ - in;
    00351     *pbuff++ = in;
    00352     /* points to the next real value */
    00353     pS1++;
    00354
    00355     /* Decrement the loop counter */
    00356     i--;
    00357   }
    00358
    00359
    00360         /*------------ Normalizing the output by multiplying with the normalizing factor ----------*/
    00361
    00362   /* Initializing the loop counter */
    00363   i = S->N;
    00364
    00365   /* pbuff initialized to the pInlineBuffer(now contains the output values) */
    00366   pbuff = pInlineBuffer;
    00367
    00368   do
    00369   {
    00370     /* Multiplying pInlineBuffer with the normalizing factor sqrt(2/N) */
    00371     in = *pbuff;
    00372     *pbuff++ = ((q31_t) (((q63_t) in * S->normalize) >> 31));
    00373
    00374     /* Decrement the loop counter */
    00375     i--;
    00376   } while(i > 0u);
    00377
    00378 #endif /* #ifndef ARM_MATH_CM0 */
    00379
    00380 }
    00381

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines