1/*
2 *  Copyright (c) 2014 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
11#include "dl/api/omxtypes.h"
12#include "dl/sp/api/armSP.h"
13#include "dl/sp/api/omxSP.h"
14
15extern void armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace(
16    const OMX_FC32* pSrc,
17    OMX_FC32* pDst,
18    OMX_FC32* pTwiddle,
19    long* subFFTNum,
20    long* subFFTSize);
21
22extern void armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace(
23    const OMX_FC32* pSrc,
24    OMX_FC32* pDst,
25    OMX_FC32* pTwiddle,
26    long* subFFTNum,
27    long* subFFTSize);
28
29extern void armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace(
30    const OMX_FC32* pSrc,
31    OMX_FC32* pDst,
32    OMX_FC32* pTwiddle,
33    long* subFFTNum,
34    long* subFFTSize);
35
36extern void armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace(
37    const OMX_FC32* pSrc,
38    OMX_FC32* pDst,
39    OMX_FC32* pTwiddle,
40    long* subFFTNum,
41    long* subFFTSize);
42
43extern void armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace(
44    const OMX_FC32* pSrc,
45    OMX_FC32* pDst,
46    OMX_FC32* pTwiddle,
47    long* subFFTNum,
48    long* subFFTSize);
49
50extern void armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace(
51    const OMX_FC32* pSrc,
52    OMX_FC32* pDst,
53    OMX_FC32* pTwiddle,
54    long* subFFTNum,
55    long* subFFTSize);
56
57extern void armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace(
58    const OMX_FC32* pSrc,
59    OMX_FC32* pDst,
60    OMX_FC32* pTwiddle,
61    long* subFFTNum,
62    long* subFFTSize);
63
64/**
65 * Function:  omxSP_FFTFwd_CToC_FC32_Sfs   (2.2.4.2.2)
66 *
67 * Description:
68 * Compute an FFT for a complex signal of length of 2^order,
69 * where 0 <= order <= 15.
70 * Transform length is determined by the specification structure, which
71 * must be initialized prior to calling the FFT function using the appropriate
72 * helper, i.e., <FFTInit_C_sc32> or <FFTInit_C_SC16>. The relationship
73 * between the input and output sequences can be expressed in terms of the
74 * DFT, i.e.,
75 *
76 *      X[k] = SUM[n=0...N-1]x[n].e^(-jnk.2.pi/N)
77 *      k = 0,1,2,..., N-1
78 *      N = 2^order
79 *
80 * Input Arguments:
81 *   pSrc - pointer to the input signal, a complex-valued vector of length
82 *            2^order; must be aligned on a 32 byte boundary.
83 *   pFFTSpec - pointer to the preallocated and initialized specification
84 *            structure
85 *
86 * Output Arguments:
87 *   pDst - pointer to the complex-valued output vector, of length 2^order;
88 *            must be aligned on an 32-byte boundary.
89 *
90 * Return Value:
91 *
92 *    OMX_Sts_NoErr - no error
93 *    OMX_Sts_BadArgErr - returned if one or more of the following conditions
94 *              is true:
95 *    -   one or more of the following pointers is NULL: pSrc, pDst, or
96 *              pFFTSpec.
97 *    -    pSrc or pDst is not 32-byte aligned
98 *
99 */
100
101OMXResult omxSP_FFTFwd_CToC_FC32_Sfs(const OMX_FC32* pSrc,
102                                     OMX_FC32* pDst,
103                                     const OMXFFTSpec_C_FC32* pFFTSpec) {
104  ARMsFFTSpec_FC32* spec = (ARMsFFTSpec_FC32*)pFFTSpec;
105  int order;
106  long subFFTSize;
107  long subFFTNum;
108  OMX_FC32* pTwiddle;
109  OMX_FC32* pOut;
110
111  /*
112   * Check args are not NULL and the source and destination pointers
113   * are properly aligned.
114   */
115  if (!validateParametersFC32(pSrc, pDst, spec))
116    return OMX_Sts_BadArgErr;
117
118  order = fastlog2(spec->N);
119
120  subFFTSize = 1;
121  subFFTNum = spec->N;
122  pTwiddle = spec->pTwiddle;
123  pOut = spec->pBuf;
124
125  if (order > 3) {
126    OMX_FC32* argDst;
127
128    /*
129     * Set up argDst and pOut appropriately so that pOut = pDst for
130     * the very last FFT stage.
131     */
132    if ((order & 2) == 0) {
133      argDst = pOut;
134      pOut = pDst;
135    } else {
136      argDst = pDst;
137    }
138
139    /*
140     * Odd order uses a radix 8 first stage; even order, a radix 4
141     * first stage.
142     */
143    if (order & 1) {
144      armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace(
145          pSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize);
146    } else {
147      armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace(
148          pSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize);
149    }
150
151    /*
152     * Now use radix 4 stages to finish rest of the FFT
153     */
154    if (subFFTNum >= 4) {
155      while (subFFTNum > 4) {
156        OMX_FC32* tmp;
157
158        armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace(
159            argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize);
160        /*
161         * Swap argDst and pOut
162         */
163        tmp = pOut;
164        pOut = argDst;
165        argDst = tmp;
166      }
167
168      armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace(
169          argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize);
170    }
171  } else if (order == 3) {
172    armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace(
173        pSrc, pDst, pTwiddle, &subFFTNum, &subFFTSize);
174    armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace(
175        pDst, pOut, pTwiddle, &subFFTNum, &subFFTSize);
176    armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace(
177        pOut, pDst, pTwiddle, &subFFTNum, &subFFTSize);
178  } else if (order == 2) {
179    armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace(
180        pSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize);
181    armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace(
182        pOut, pDst, pTwiddle, &subFFTNum, &subFFTSize);
183  } else {
184    /* Order = 1 */
185    armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace(
186        pSrc, pDst, pTwiddle, &subFFTNum, &subFFTSize);
187  }
188
189  return OMX_Sts_NoErr;
190}
191