1333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com/*
2333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com *
4333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com *  Use of this source code is governed by a BSD-style license
5333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com *  that can be found in the LICENSE file in the root of the source
6333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com *  tree. An additional intellectual property rights grant can be found
7333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com *  in the file PATENTS.  All contributing project authors may
8333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com *  be found in the AUTHORS file in the root of the source tree.
9333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com *
10333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com */
11333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
12333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com#include <stdint.h>
13333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
14333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com#include "dl/api/omxtypes.h"
15333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com#include "dl/sp/api/mipsSP.h"
16333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
17333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.comOMXResult mips_FFTFwd_RToCCS_F32_real(const OMX_F32* pSrc,
18333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com                                      OMX_F32* pDst,
19333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com                                      const MIPSFFTSpec_R_FC32* pFFTSpec) {
20333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  OMX_U32 num_transforms, step;
21333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  OMX_FC32* p_dst = (OMX_FC32*)pDst;
22333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  OMX_FC32* p_buf = (OMX_FC32*)pFFTSpec->pBuf;
23333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  OMX_F32 tmp1, tmp2, tmp3, tmp4;
24333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  OMX_F32* w_re_ptr;
25333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  OMX_F32* w_im_ptr;
26333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
27333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  /* Transform for order = 2. */
28333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  /* TODO: hard-code the offsets for p_src. */
29333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  if (pFFTSpec->order == 2) {
30333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_U16* p_bitrev = pFFTSpec->pBitRev;
31333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
32333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = pSrc[p_bitrev[0]] + pSrc[p_bitrev[1]];
33333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp2 = pSrc[p_bitrev[2]] + pSrc[p_bitrev[3]];
34333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp3 = pSrc[p_bitrev[0]] - pSrc[p_bitrev[1]];
35333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp4 = pSrc[p_bitrev[2]] - pSrc[p_bitrev[3]];
36333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
37333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[0].Re = tmp1 + tmp2;
38333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[2].Re = tmp1 - tmp2;
39333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[0].Im = 0.0f;
40333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[2].Im = 0.0f;
41333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[1].Re = tmp3;
42333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[1].Im = -tmp4;
43333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
44333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    return OMX_Sts_NoErr;
45333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  }
46333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
47333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  /*
48333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   * Loop performing sub-transforms of size 4, which contain two butterfly
49333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   * operations. Reading the input signal from split-radix bitreverse offsets.
50333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   */
51333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  num_transforms = (SUBTRANSFORM_CONST >> (16 - pFFTSpec->order)) | 1;
52333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  for (uint32_t n = 0; n < num_transforms; ++n) {
53333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_U32 offset = pFFTSpec->pOffset[n] << 2;
54333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_FC32* p_tmp = p_buf + offset;
55333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_U16* p_bitrev = pFFTSpec->pBitRev + offset;
56333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
57333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = pSrc[p_bitrev[0]] + pSrc[p_bitrev[1]];
58333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp2 = pSrc[p_bitrev[2]] + pSrc[p_bitrev[3]];
59333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp3 = pSrc[p_bitrev[0]] - pSrc[p_bitrev[1]];
60333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp4 = pSrc[p_bitrev[2]] - pSrc[p_bitrev[3]];
61333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
62333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[0].Re = tmp1 + tmp2;
63333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[2].Re = tmp1 - tmp2;
64333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[0].Im = 0.0f;
65333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[2].Im = 0.0f;
66333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[1].Re = tmp3;
67333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[3].Re = tmp3;
68333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[1].Im = -tmp4;
69333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[3].Im = tmp4;
70333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  }
71333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
72333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  /*
73333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   * Loop performing sub-transforms of size 8,
74333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   * which contain four butterfly operations.
75333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   */
76333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  num_transforms >>= 1;
77333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  if (!num_transforms) {
78333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    /*
79333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com     * Means the FFT size is equal to 8, so this is the last stage. Place the
80333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com     * output to the destination buffer and avoid unnecessary computations.
81333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com     */
82333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_FC32* p_tmp = p_buf;
83333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_U16* p_bitrev = pFFTSpec->pBitRev;
84333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_F32 tmp5;
85333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
86333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = pSrc[p_bitrev[4]] + pSrc[p_bitrev[5]];
87333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp2 = pSrc[p_bitrev[6]] + pSrc[p_bitrev[7]];
88333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp3 = tmp1 + tmp2;
89333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp4 = tmp1 - tmp2;
90333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
91333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = pSrc[p_bitrev[4]] - pSrc[p_bitrev[5]];
92333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp2 = pSrc[p_bitrev[6]] - pSrc[p_bitrev[7]];
93333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp5 = SQRT1_2 * (tmp1 + tmp2);
94333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = SQRT1_2 * (tmp1 - tmp2);
95333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
96333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[4].Re = p_tmp[0].Re - tmp3;
97333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[0].Re = p_tmp[0].Re + tmp3;
98333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[0].Im = p_tmp[0].Im;
99333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[4].Im = p_tmp[0].Im;
100333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[2].Re = p_tmp[2].Re;
101333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[2].Im = p_tmp[2].Im - tmp4;
102333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[1].Re = p_tmp[1].Re + tmp5;
103333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[1].Im = p_tmp[1].Im - tmp1;
104333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[3].Re = p_tmp[3].Re - tmp5;
105333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[3].Im = p_tmp[3].Im - tmp1;
106333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
107333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    return OMX_Sts_NoErr;
108333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  }
109333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
110333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  num_transforms |= 1;
111333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
112333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  for (uint32_t n = 0; n < num_transforms; ++n) {
113333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_U32 offset = pFFTSpec->pOffset[n] << 3;
114333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_FC32* p_tmp = p_buf + offset;
115333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_U16* p_bitrev = pFFTSpec->pBitRev + offset;
116333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_F32 tmp5;
117333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
118333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = pSrc[p_bitrev[4]] + pSrc[p_bitrev[5]];
119333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp2 = pSrc[p_bitrev[6]] + pSrc[p_bitrev[7]];
120333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp3 = tmp1 + tmp2;
121333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp4 = tmp1 - tmp2;
122333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
123333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = pSrc[p_bitrev[4]] - pSrc[p_bitrev[5]];
124333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp2 = pSrc[p_bitrev[6]] - pSrc[p_bitrev[7]];
125333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp5 = SQRT1_2 * (tmp1 + tmp2);
126333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = SQRT1_2 * (tmp1 - tmp2);
127333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
128333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[4].Re = p_tmp[0].Re - tmp3;
129333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[0].Re = p_tmp[0].Re + tmp3;
130333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[4].Im = p_tmp[0].Im;
131333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[6].Re = p_tmp[2].Re;
132333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[6].Im = p_tmp[2].Im + tmp4;
133333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[2].Im = p_tmp[2].Im - tmp4;
134333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
135333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[5].Re = p_tmp[1].Re - tmp5;
136333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[1].Re = p_tmp[1].Re + tmp5;
137333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[5].Im = p_tmp[1].Im + tmp1;
138333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[1].Im = p_tmp[1].Im - tmp1;
139333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[7].Re = p_tmp[3].Re + tmp5;
140333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[3].Re = p_tmp[3].Re - tmp5;
141333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[7].Im = p_tmp[3].Im + tmp1;
142333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_tmp[3].Im = p_tmp[3].Im - tmp1;
143333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  }
144333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
145333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  step = 1 << (TWIDDLE_TABLE_ORDER - 4);
146333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  /*
147333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   * Last FFT stage,  performing sub-transforms of size 16. Place the output
148333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   * into the destination buffer and avoid unnecessary computations.
149333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com   */
150333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  tmp1 = p_buf[8].Re + p_buf[12].Re;
151333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  tmp2 = p_buf[8].Re - p_buf[12].Re;
152333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  tmp3 = p_buf[8].Im + p_buf[12].Im;
153333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  tmp4 = p_buf[8].Im - p_buf[12].Im;
154333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
155333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  p_dst[8].Re = p_buf[0].Re - tmp1;
156333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  p_dst[0].Re = p_buf[0].Re + tmp1;
157333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  p_dst[8].Im = p_buf[0].Im - tmp3;
158333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  p_dst[0].Im = p_buf[0].Im + tmp3;
159333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  p_dst[4].Re = p_buf[4].Re + tmp4;
160333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  p_dst[4].Im = p_buf[4].Im - tmp2;
161333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
162333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  w_re_ptr = pFFTSpec->pTwiddle + step;
163333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  w_im_ptr =
164333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com      pFFTSpec->pTwiddle + (OMX_U32)(1 << TWIDDLE_TABLE_ORDER - 2) - step;
165333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
166333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  /* Loop performing split-radix butterfly operations. */
167333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  for (uint32_t n = 1; n < 4; ++n) {
168333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_F32 tmp5, tmp6;
169333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_F32 w_re = *w_re_ptr;
170333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    OMX_F32 w_im = *w_im_ptr;
171333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
172333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = w_re * p_buf[8 + n].Re + w_im * p_buf[8 + n].Im;
173333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp2 = w_re * p_buf[8 + n].Im - w_im * p_buf[8 + n].Re;
174333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp3 = w_re * p_buf[12 + n].Re - w_im * p_buf[12 + n].Im;
175333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp4 = w_re * p_buf[12 + n].Im + w_im * p_buf[12 + n].Re;
176333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
177333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp5 = tmp1 + tmp3;
178333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp1 = tmp1 - tmp3;
179333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp6 = tmp2 + tmp4;
180333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    tmp2 = tmp2 - tmp4;
181333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
182333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[n].Re = p_buf[n].Re + tmp5;
183333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[n].Im = p_buf[n].Im + tmp6;
184333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[4 + n].Re = p_buf[4 + n].Re + tmp2;
185333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    p_dst[4 + n].Im = p_buf[4 + n].Im - tmp1;
186333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com
187333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    w_re_ptr += step;
188333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com    w_im_ptr -= step;
189333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  }
190333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com  return OMX_Sts_NoErr;
191333c00b74820c9dc0022d124c5a10a788d74d5cartoy@google.com}
192