1/*
2 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 *
10 *  This file was originally licensed as follows. It has been
11 *  relicensed with permission from the copyright holders.
12 */
13
14/**
15 *
16 * File Name:  omxSP_FFTInit_C_SC16.c
17 * OpenMAX DL: v1.0.2
18 * Last Modified Revision:   15322
19 * Last Modified Date:       Wed, 15 Oct 2008
20 *
21 * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
22 *
23 *
24 * Description:
25 * Initializes the specification structures required
26 */
27
28 #include <stdint.h>
29
30#include "dl/api/arm/armOMX.h"
31#include "dl/api/omxtypes.h"
32#include "dl/sp/api/armSP.h"
33#include "dl/sp/api/omxSP.h"
34
35/**
36 * Function: omxSP_FFTInit_C_SC16
37 *
38 * Description:
39 * These functions initialize the specification structures required for the
40 * complex FFT and IFFT functions.
41 *
42 * Remarks:
43 * Desired block length is specified as an input. The function is used to
44 * initialize the specification structures for functions <FFTFwd_CToC_SC16_Sfs>
45 * and <FFTInv_CToC_SC16_Sfs>. Memory for the specification structure *pFFTSpec
46 * must be allocated prior to calling this function. The space required for
47 * *pFFTSpec, in bytes, can be determined using <FFTGetBufSize_C_SC16>.
48 *
49 * Parameters:
50 * [in]  order          base-2 logarithm of the desired block length;
51 *                              valid in the range [0,12].
52 * [out] pFFTSpec               pointer to initialized specification structure.
53 *
54 * Return Value:
55 * Standard omxError result. See enumeration for possible result codes.
56 *
57 */
58
59OMXResult omxSP_FFTInit_C_SC16(
60     OMXFFTSpec_C_SC16* pFFTSpec,
61     OMX_INT order
62 )
63 {
64    OMX_INT     i,j;
65    OMX_SC16    *pTwiddle, *pBuf;
66    OMX_U16     *pBitRev;
67    OMX_INT     Nby2,N,M,diff,step;
68    OMX_U32             pTmp;
69    ARMsFFTSpec_SC16 *pFFTStruct = 0;
70    OMX_S16     x,y,xNeg;
71    OMX_S32     xS32,yS32;
72
73
74    pFFTStruct = (ARMsFFTSpec_SC16 *) pFFTSpec;
75
76    /* if order zero no init is needed */
77    if (order == 0)
78    {
79        pFFTStruct->N = 1;
80        return OMX_Sts_NoErr;
81    }
82
83    /* Do the initializations */
84    Nby2 = 1 << (order - 1);
85    N = Nby2 << 1;
86    M = N>>3;
87
88    pBitRev = NULL ;
89
90    pTwiddle = (OMX_SC16 *)
91        (sizeof(ARMsFFTSpec_SC16) + (OMX_S8*) pFFTSpec);
92
93    /* Align to 32 byte boundary */
94    pTmp = ((uintptr_t)pTwiddle)&31;              /* (uintptr_t)pTwiddle % 32 */
95    if(pTmp != 0)
96        pTwiddle = (OMX_SC16*) ((OMX_S8*)pTwiddle + (32-pTmp));
97
98    pBuf = (OMX_SC16 *)
99        (sizeof(OMX_SC16) * (3*N/4) + (OMX_S8*) pTwiddle);
100
101    /* Align to 32 byte boundary */
102    pTmp = ((uintptr_t)pBuf)&31;                 /* (uintptr_t)pBuf % 32 */
103    if(pTmp != 0)
104        pBuf = (OMX_SC16*) ((OMX_S8*)pBuf + (32-pTmp));
105
106
107
108    /*
109     * Filling Twiddle factors :
110     * The original twiddle table "armSP_FFT_S16TwiddleTable" is of size (MaxSize/8 + 1)
111     * Rest of the values i.e., upto MaxSize are calculated using the symmetries of sin and cos
112     * The max size of the twiddle table needed is 3N/4 for a radix-4 stage
113     *
114     * W = (-2 * PI) / N
115     * N = 1 << order
116     * W = -PI >> (order - 1)
117     */
118
119
120
121    diff = 12 - order;
122    step = 1<<diff;             /* step into the twiddle table for the current order */
123
124    xS32 = armSP_FFT_S32TwiddleTable[0];
125    yS32 = armSP_FFT_S32TwiddleTable[1];
126    x = (xS32+0x8000)>>16;
127    y = (yS32+0x8000)>>16;
128
129    xNeg = 0x7FFF;
130
131    if(order >=3)
132    {
133            /* i = 0 case */
134            pTwiddle[0].Re = x;
135            pTwiddle[0].Im = y;
136            pTwiddle[2*M].Re = -y;
137            pTwiddle[2*M].Im = xNeg;
138            pTwiddle[4*M].Re = xNeg;
139            pTwiddle[4*M].Im = y;
140
141
142        for (i=1; i<=M; i++)
143          {
144            j = i*step;
145
146            xS32 = armSP_FFT_S32TwiddleTable[2*j];
147            yS32 = armSP_FFT_S32TwiddleTable[2*j+1];
148            x = (xS32+0x8000)>>16;
149            y = (yS32+0x8000)>>16;
150
151            pTwiddle[i].Re = x;
152            pTwiddle[i].Im = y;
153            pTwiddle[2*M-i].Re = -y;
154            pTwiddle[2*M-i].Im = -x;
155            pTwiddle[2*M+i].Re = y;
156            pTwiddle[2*M+i].Im = -x;
157            pTwiddle[4*M-i].Re = -x;
158            pTwiddle[4*M-i].Im = y;
159            pTwiddle[4*M+i].Re = -x;
160            pTwiddle[4*M+i].Im = -y;
161            pTwiddle[6*M-i].Re = y;
162            pTwiddle[6*M-i].Im = x;
163        }
164
165
166    }
167    else
168    {
169        if (order == 2)
170        {
171            pTwiddle[0].Re = x;
172            pTwiddle[0].Im = y;
173            pTwiddle[1].Re = -y;
174            pTwiddle[1].Im = xNeg;
175            pTwiddle[2].Re = xNeg;
176            pTwiddle[2].Im = y;
177
178        }
179        if (order == 1)
180        {
181            pTwiddle[0].Re = x;
182            pTwiddle[0].Im = y;
183
184        }
185
186
187    }
188
189
190    /* Update the structure */
191    pFFTStruct->N = N;
192    pFFTStruct->pTwiddle = pTwiddle;
193    pFFTStruct->pBitRev = pBitRev;
194    pFFTStruct->pBuf = pBuf;
195
196    return OMX_Sts_NoErr;
197}
198
199/*****************************************************************************
200 *                              END OF FILE
201 *****************************************************************************/
202
203