1*28e138c6SAndroid Build Coastguard Worker /*
2*28e138c6SAndroid Build Coastguard Worker Copyright (c) 2003-2004, Mark Borgerding
3*28e138c6SAndroid Build Coastguard Worker
4*28e138c6SAndroid Build Coastguard Worker All rights reserved.
5*28e138c6SAndroid Build Coastguard Worker
6*28e138c6SAndroid Build Coastguard Worker Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7*28e138c6SAndroid Build Coastguard Worker
8*28e138c6SAndroid Build Coastguard Worker * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9*28e138c6SAndroid Build Coastguard Worker * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10*28e138c6SAndroid Build Coastguard Worker * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11*28e138c6SAndroid Build Coastguard Worker
12*28e138c6SAndroid Build Coastguard Worker THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*28e138c6SAndroid Build Coastguard Worker */
14*28e138c6SAndroid Build Coastguard Worker
15*28e138c6SAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
16*28e138c6SAndroid Build Coastguard Worker #include "config.h"
17*28e138c6SAndroid Build Coastguard Worker #endif
18*28e138c6SAndroid Build Coastguard Worker
19*28e138c6SAndroid Build Coastguard Worker #include "os_support.h"
20*28e138c6SAndroid Build Coastguard Worker #include "kiss_fftr.h"
21*28e138c6SAndroid Build Coastguard Worker #include "_kiss_fft_guts.h"
22*28e138c6SAndroid Build Coastguard Worker
23*28e138c6SAndroid Build Coastguard Worker struct kiss_fftr_state{
24*28e138c6SAndroid Build Coastguard Worker kiss_fft_cfg substate;
25*28e138c6SAndroid Build Coastguard Worker kiss_fft_cpx * tmpbuf;
26*28e138c6SAndroid Build Coastguard Worker kiss_fft_cpx * super_twiddles;
27*28e138c6SAndroid Build Coastguard Worker #ifdef USE_SIMD
28*28e138c6SAndroid Build Coastguard Worker long pad;
29*28e138c6SAndroid Build Coastguard Worker #endif
30*28e138c6SAndroid Build Coastguard Worker };
31*28e138c6SAndroid Build Coastguard Worker
kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)32*28e138c6SAndroid Build Coastguard Worker kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
33*28e138c6SAndroid Build Coastguard Worker {
34*28e138c6SAndroid Build Coastguard Worker int i;
35*28e138c6SAndroid Build Coastguard Worker kiss_fftr_cfg st = NULL;
36*28e138c6SAndroid Build Coastguard Worker size_t subsize, memneeded;
37*28e138c6SAndroid Build Coastguard Worker
38*28e138c6SAndroid Build Coastguard Worker if (nfft & 1) {
39*28e138c6SAndroid Build Coastguard Worker speex_warning("Real FFT optimization must be even.\n");
40*28e138c6SAndroid Build Coastguard Worker return NULL;
41*28e138c6SAndroid Build Coastguard Worker }
42*28e138c6SAndroid Build Coastguard Worker nfft >>= 1;
43*28e138c6SAndroid Build Coastguard Worker
44*28e138c6SAndroid Build Coastguard Worker kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
45*28e138c6SAndroid Build Coastguard Worker memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 2);
46*28e138c6SAndroid Build Coastguard Worker
47*28e138c6SAndroid Build Coastguard Worker if (lenmem == NULL) {
48*28e138c6SAndroid Build Coastguard Worker st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
49*28e138c6SAndroid Build Coastguard Worker } else {
50*28e138c6SAndroid Build Coastguard Worker if (*lenmem >= memneeded)
51*28e138c6SAndroid Build Coastguard Worker st = (kiss_fftr_cfg) mem;
52*28e138c6SAndroid Build Coastguard Worker *lenmem = memneeded;
53*28e138c6SAndroid Build Coastguard Worker }
54*28e138c6SAndroid Build Coastguard Worker if (!st)
55*28e138c6SAndroid Build Coastguard Worker return NULL;
56*28e138c6SAndroid Build Coastguard Worker
57*28e138c6SAndroid Build Coastguard Worker st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
58*28e138c6SAndroid Build Coastguard Worker st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
59*28e138c6SAndroid Build Coastguard Worker st->super_twiddles = st->tmpbuf + nfft;
60*28e138c6SAndroid Build Coastguard Worker kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
61*28e138c6SAndroid Build Coastguard Worker
62*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
63*28e138c6SAndroid Build Coastguard Worker for (i=0;i<nfft;++i) {
64*28e138c6SAndroid Build Coastguard Worker spx_word32_t phase = i+(nfft>>1);
65*28e138c6SAndroid Build Coastguard Worker if (!inverse_fft)
66*28e138c6SAndroid Build Coastguard Worker phase = -phase;
67*28e138c6SAndroid Build Coastguard Worker kf_cexp2(st->super_twiddles+i, DIV32(SHL32(phase,16),nfft));
68*28e138c6SAndroid Build Coastguard Worker }
69*28e138c6SAndroid Build Coastguard Worker #else
70*28e138c6SAndroid Build Coastguard Worker for (i=0;i<nfft;++i) {
71*28e138c6SAndroid Build Coastguard Worker const double pi=3.14159265358979323846264338327;
72*28e138c6SAndroid Build Coastguard Worker double phase = pi*(((double)i) /nfft + .5);
73*28e138c6SAndroid Build Coastguard Worker if (!inverse_fft)
74*28e138c6SAndroid Build Coastguard Worker phase = -phase;
75*28e138c6SAndroid Build Coastguard Worker kf_cexp(st->super_twiddles+i, phase );
76*28e138c6SAndroid Build Coastguard Worker }
77*28e138c6SAndroid Build Coastguard Worker #endif
78*28e138c6SAndroid Build Coastguard Worker return st;
79*28e138c6SAndroid Build Coastguard Worker }
80*28e138c6SAndroid Build Coastguard Worker
kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar * timedata,kiss_fft_cpx * freqdata)81*28e138c6SAndroid Build Coastguard Worker void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
82*28e138c6SAndroid Build Coastguard Worker {
83*28e138c6SAndroid Build Coastguard Worker /* input buffer timedata is stored row-wise */
84*28e138c6SAndroid Build Coastguard Worker int k,ncfft;
85*28e138c6SAndroid Build Coastguard Worker kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
86*28e138c6SAndroid Build Coastguard Worker
87*28e138c6SAndroid Build Coastguard Worker if ( st->substate->inverse) {
88*28e138c6SAndroid Build Coastguard Worker speex_fatal("kiss fft usage error: improper alloc\n");
89*28e138c6SAndroid Build Coastguard Worker }
90*28e138c6SAndroid Build Coastguard Worker
91*28e138c6SAndroid Build Coastguard Worker ncfft = st->substate->nfft;
92*28e138c6SAndroid Build Coastguard Worker
93*28e138c6SAndroid Build Coastguard Worker /*perform the parallel fft of two real signals packed in real,imag*/
94*28e138c6SAndroid Build Coastguard Worker kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
95*28e138c6SAndroid Build Coastguard Worker /* The real part of the DC element of the frequency spectrum in st->tmpbuf
96*28e138c6SAndroid Build Coastguard Worker * contains the sum of the even-numbered elements of the input time sequence
97*28e138c6SAndroid Build Coastguard Worker * The imag part is the sum of the odd-numbered elements
98*28e138c6SAndroid Build Coastguard Worker *
99*28e138c6SAndroid Build Coastguard Worker * The sum of tdc.r and tdc.i is the sum of the input time sequence.
100*28e138c6SAndroid Build Coastguard Worker * yielding DC of input time sequence
101*28e138c6SAndroid Build Coastguard Worker * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
102*28e138c6SAndroid Build Coastguard Worker * yielding Nyquist bin of input time sequence
103*28e138c6SAndroid Build Coastguard Worker */
104*28e138c6SAndroid Build Coastguard Worker
105*28e138c6SAndroid Build Coastguard Worker tdc.r = st->tmpbuf[0].r;
106*28e138c6SAndroid Build Coastguard Worker tdc.i = st->tmpbuf[0].i;
107*28e138c6SAndroid Build Coastguard Worker C_FIXDIV(tdc,2);
108*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
109*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
110*28e138c6SAndroid Build Coastguard Worker freqdata[0].r = tdc.r + tdc.i;
111*28e138c6SAndroid Build Coastguard Worker freqdata[ncfft].r = tdc.r - tdc.i;
112*28e138c6SAndroid Build Coastguard Worker #ifdef USE_SIMD
113*28e138c6SAndroid Build Coastguard Worker freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
114*28e138c6SAndroid Build Coastguard Worker #else
115*28e138c6SAndroid Build Coastguard Worker freqdata[ncfft].i = freqdata[0].i = 0;
116*28e138c6SAndroid Build Coastguard Worker #endif
117*28e138c6SAndroid Build Coastguard Worker
118*28e138c6SAndroid Build Coastguard Worker for ( k=1;k <= ncfft/2 ; ++k ) {
119*28e138c6SAndroid Build Coastguard Worker fpk = st->tmpbuf[k];
120*28e138c6SAndroid Build Coastguard Worker fpnk.r = st->tmpbuf[ncfft-k].r;
121*28e138c6SAndroid Build Coastguard Worker fpnk.i = - st->tmpbuf[ncfft-k].i;
122*28e138c6SAndroid Build Coastguard Worker C_FIXDIV(fpk,2);
123*28e138c6SAndroid Build Coastguard Worker C_FIXDIV(fpnk,2);
124*28e138c6SAndroid Build Coastguard Worker
125*28e138c6SAndroid Build Coastguard Worker C_ADD( f1k, fpk , fpnk );
126*28e138c6SAndroid Build Coastguard Worker C_SUB( f2k, fpk , fpnk );
127*28e138c6SAndroid Build Coastguard Worker C_MUL( tw , f2k , st->super_twiddles[k]);
128*28e138c6SAndroid Build Coastguard Worker
129*28e138c6SAndroid Build Coastguard Worker freqdata[k].r = HALF_OF(f1k.r + tw.r);
130*28e138c6SAndroid Build Coastguard Worker freqdata[k].i = HALF_OF(f1k.i + tw.i);
131*28e138c6SAndroid Build Coastguard Worker freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
132*28e138c6SAndroid Build Coastguard Worker freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
133*28e138c6SAndroid Build Coastguard Worker }
134*28e138c6SAndroid Build Coastguard Worker }
135*28e138c6SAndroid Build Coastguard Worker
kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx * freqdata,kiss_fft_scalar * timedata)136*28e138c6SAndroid Build Coastguard Worker void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata, kiss_fft_scalar *timedata)
137*28e138c6SAndroid Build Coastguard Worker {
138*28e138c6SAndroid Build Coastguard Worker /* input buffer timedata is stored row-wise */
139*28e138c6SAndroid Build Coastguard Worker int k, ncfft;
140*28e138c6SAndroid Build Coastguard Worker
141*28e138c6SAndroid Build Coastguard Worker if (st->substate->inverse == 0) {
142*28e138c6SAndroid Build Coastguard Worker speex_fatal("kiss fft usage error: improper alloc\n");
143*28e138c6SAndroid Build Coastguard Worker }
144*28e138c6SAndroid Build Coastguard Worker
145*28e138c6SAndroid Build Coastguard Worker ncfft = st->substate->nfft;
146*28e138c6SAndroid Build Coastguard Worker
147*28e138c6SAndroid Build Coastguard Worker st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
148*28e138c6SAndroid Build Coastguard Worker st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
149*28e138c6SAndroid Build Coastguard Worker /*C_FIXDIV(st->tmpbuf[0],2);*/
150*28e138c6SAndroid Build Coastguard Worker
151*28e138c6SAndroid Build Coastguard Worker for (k = 1; k <= ncfft / 2; ++k) {
152*28e138c6SAndroid Build Coastguard Worker kiss_fft_cpx fk, fnkc, fek, fok, tmp;
153*28e138c6SAndroid Build Coastguard Worker fk = freqdata[k];
154*28e138c6SAndroid Build Coastguard Worker fnkc.r = freqdata[ncfft - k].r;
155*28e138c6SAndroid Build Coastguard Worker fnkc.i = -freqdata[ncfft - k].i;
156*28e138c6SAndroid Build Coastguard Worker /*C_FIXDIV( fk , 2 );
157*28e138c6SAndroid Build Coastguard Worker C_FIXDIV( fnkc , 2 );*/
158*28e138c6SAndroid Build Coastguard Worker
159*28e138c6SAndroid Build Coastguard Worker C_ADD (fek, fk, fnkc);
160*28e138c6SAndroid Build Coastguard Worker C_SUB (tmp, fk, fnkc);
161*28e138c6SAndroid Build Coastguard Worker C_MUL (fok, tmp, st->super_twiddles[k]);
162*28e138c6SAndroid Build Coastguard Worker C_ADD (st->tmpbuf[k], fek, fok);
163*28e138c6SAndroid Build Coastguard Worker C_SUB (st->tmpbuf[ncfft - k], fek, fok);
164*28e138c6SAndroid Build Coastguard Worker #ifdef USE_SIMD
165*28e138c6SAndroid Build Coastguard Worker st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
166*28e138c6SAndroid Build Coastguard Worker #else
167*28e138c6SAndroid Build Coastguard Worker st->tmpbuf[ncfft - k].i *= -1;
168*28e138c6SAndroid Build Coastguard Worker #endif
169*28e138c6SAndroid Build Coastguard Worker }
170*28e138c6SAndroid Build Coastguard Worker kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
171*28e138c6SAndroid Build Coastguard Worker }
172*28e138c6SAndroid Build Coastguard Worker
kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar * timedata,kiss_fft_scalar * freqdata)173*28e138c6SAndroid Build Coastguard Worker void kiss_fftr2(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_scalar *freqdata)
174*28e138c6SAndroid Build Coastguard Worker {
175*28e138c6SAndroid Build Coastguard Worker /* input buffer timedata is stored row-wise */
176*28e138c6SAndroid Build Coastguard Worker int k,ncfft;
177*28e138c6SAndroid Build Coastguard Worker kiss_fft_cpx f2k,tdc;
178*28e138c6SAndroid Build Coastguard Worker spx_word32_t f1kr, f1ki, twr, twi;
179*28e138c6SAndroid Build Coastguard Worker
180*28e138c6SAndroid Build Coastguard Worker if ( st->substate->inverse) {
181*28e138c6SAndroid Build Coastguard Worker speex_fatal("kiss fft usage error: improper alloc\n");
182*28e138c6SAndroid Build Coastguard Worker }
183*28e138c6SAndroid Build Coastguard Worker
184*28e138c6SAndroid Build Coastguard Worker ncfft = st->substate->nfft;
185*28e138c6SAndroid Build Coastguard Worker
186*28e138c6SAndroid Build Coastguard Worker /*perform the parallel fft of two real signals packed in real,imag*/
187*28e138c6SAndroid Build Coastguard Worker kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
188*28e138c6SAndroid Build Coastguard Worker /* The real part of the DC element of the frequency spectrum in st->tmpbuf
189*28e138c6SAndroid Build Coastguard Worker * contains the sum of the even-numbered elements of the input time sequence
190*28e138c6SAndroid Build Coastguard Worker * The imag part is the sum of the odd-numbered elements
191*28e138c6SAndroid Build Coastguard Worker *
192*28e138c6SAndroid Build Coastguard Worker * The sum of tdc.r and tdc.i is the sum of the input time sequence.
193*28e138c6SAndroid Build Coastguard Worker * yielding DC of input time sequence
194*28e138c6SAndroid Build Coastguard Worker * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
195*28e138c6SAndroid Build Coastguard Worker * yielding Nyquist bin of input time sequence
196*28e138c6SAndroid Build Coastguard Worker */
197*28e138c6SAndroid Build Coastguard Worker
198*28e138c6SAndroid Build Coastguard Worker tdc.r = st->tmpbuf[0].r;
199*28e138c6SAndroid Build Coastguard Worker tdc.i = st->tmpbuf[0].i;
200*28e138c6SAndroid Build Coastguard Worker C_FIXDIV(tdc,2);
201*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
202*28e138c6SAndroid Build Coastguard Worker CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
203*28e138c6SAndroid Build Coastguard Worker freqdata[0] = tdc.r + tdc.i;
204*28e138c6SAndroid Build Coastguard Worker freqdata[2*ncfft-1] = tdc.r - tdc.i;
205*28e138c6SAndroid Build Coastguard Worker
206*28e138c6SAndroid Build Coastguard Worker for ( k=1;k <= ncfft/2 ; ++k )
207*28e138c6SAndroid Build Coastguard Worker {
208*28e138c6SAndroid Build Coastguard Worker /*fpk = st->tmpbuf[k];
209*28e138c6SAndroid Build Coastguard Worker fpnk.r = st->tmpbuf[ncfft-k].r;
210*28e138c6SAndroid Build Coastguard Worker fpnk.i = - st->tmpbuf[ncfft-k].i;
211*28e138c6SAndroid Build Coastguard Worker C_FIXDIV(fpk,2);
212*28e138c6SAndroid Build Coastguard Worker C_FIXDIV(fpnk,2);
213*28e138c6SAndroid Build Coastguard Worker
214*28e138c6SAndroid Build Coastguard Worker C_ADD( f1k, fpk , fpnk );
215*28e138c6SAndroid Build Coastguard Worker C_SUB( f2k, fpk , fpnk );
216*28e138c6SAndroid Build Coastguard Worker
217*28e138c6SAndroid Build Coastguard Worker C_MUL( tw , f2k , st->super_twiddles[k]);
218*28e138c6SAndroid Build Coastguard Worker
219*28e138c6SAndroid Build Coastguard Worker freqdata[2*k-1] = HALF_OF(f1k.r + tw.r);
220*28e138c6SAndroid Build Coastguard Worker freqdata[2*k] = HALF_OF(f1k.i + tw.i);
221*28e138c6SAndroid Build Coastguard Worker freqdata[2*(ncfft-k)-1] = HALF_OF(f1k.r - tw.r);
222*28e138c6SAndroid Build Coastguard Worker freqdata[2*(ncfft-k)] = HALF_OF(tw.i - f1k.i);
223*28e138c6SAndroid Build Coastguard Worker */
224*28e138c6SAndroid Build Coastguard Worker
225*28e138c6SAndroid Build Coastguard Worker /*f1k.r = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1);
226*28e138c6SAndroid Build Coastguard Worker f1k.i = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1);
227*28e138c6SAndroid Build Coastguard Worker f2k.r = PSHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1);
228*28e138c6SAndroid Build Coastguard Worker f2k.i = SHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1);
229*28e138c6SAndroid Build Coastguard Worker
230*28e138c6SAndroid Build Coastguard Worker C_MUL( tw , f2k , st->super_twiddles[k]);
231*28e138c6SAndroid Build Coastguard Worker
232*28e138c6SAndroid Build Coastguard Worker freqdata[2*k-1] = HALF_OF(f1k.r + tw.r);
233*28e138c6SAndroid Build Coastguard Worker freqdata[2*k] = HALF_OF(f1k.i + tw.i);
234*28e138c6SAndroid Build Coastguard Worker freqdata[2*(ncfft-k)-1] = HALF_OF(f1k.r - tw.r);
235*28e138c6SAndroid Build Coastguard Worker freqdata[2*(ncfft-k)] = HALF_OF(tw.i - f1k.i);
236*28e138c6SAndroid Build Coastguard Worker */
237*28e138c6SAndroid Build Coastguard Worker f2k.r = SHR32(SUB32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),1);
238*28e138c6SAndroid Build Coastguard Worker f2k.i = PSHR32(ADD32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),1);
239*28e138c6SAndroid Build Coastguard Worker
240*28e138c6SAndroid Build Coastguard Worker f1kr = SHL32(ADD32(EXTEND32(st->tmpbuf[k].r), EXTEND32(st->tmpbuf[ncfft-k].r)),13);
241*28e138c6SAndroid Build Coastguard Worker f1ki = SHL32(SUB32(EXTEND32(st->tmpbuf[k].i), EXTEND32(st->tmpbuf[ncfft-k].i)),13);
242*28e138c6SAndroid Build Coastguard Worker
243*28e138c6SAndroid Build Coastguard Worker twr = SHR32(SUB32(MULT16_16(f2k.r,st->super_twiddles[k].r),MULT16_16(f2k.i,st->super_twiddles[k].i)), 1);
244*28e138c6SAndroid Build Coastguard Worker twi = SHR32(ADD32(MULT16_16(f2k.i,st->super_twiddles[k].r),MULT16_16(f2k.r,st->super_twiddles[k].i)), 1);
245*28e138c6SAndroid Build Coastguard Worker
246*28e138c6SAndroid Build Coastguard Worker #ifdef FIXED_POINT
247*28e138c6SAndroid Build Coastguard Worker freqdata[2*k-1] = PSHR32(f1kr + twr, 15);
248*28e138c6SAndroid Build Coastguard Worker freqdata[2*k] = PSHR32(f1ki + twi, 15);
249*28e138c6SAndroid Build Coastguard Worker freqdata[2*(ncfft-k)-1] = PSHR32(f1kr - twr, 15);
250*28e138c6SAndroid Build Coastguard Worker freqdata[2*(ncfft-k)] = PSHR32(twi - f1ki, 15);
251*28e138c6SAndroid Build Coastguard Worker #else
252*28e138c6SAndroid Build Coastguard Worker freqdata[2*k-1] = .5f*(f1kr + twr);
253*28e138c6SAndroid Build Coastguard Worker freqdata[2*k] = .5f*(f1ki + twi);
254*28e138c6SAndroid Build Coastguard Worker freqdata[2*(ncfft-k)-1] = .5f*(f1kr - twr);
255*28e138c6SAndroid Build Coastguard Worker freqdata[2*(ncfft-k)] = .5f*(twi - f1ki);
256*28e138c6SAndroid Build Coastguard Worker
257*28e138c6SAndroid Build Coastguard Worker #endif
258*28e138c6SAndroid Build Coastguard Worker }
259*28e138c6SAndroid Build Coastguard Worker }
260*28e138c6SAndroid Build Coastguard Worker
kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar * freqdata,kiss_fft_scalar * timedata)261*28e138c6SAndroid Build Coastguard Worker void kiss_fftri2(kiss_fftr_cfg st,const kiss_fft_scalar *freqdata,kiss_fft_scalar *timedata)
262*28e138c6SAndroid Build Coastguard Worker {
263*28e138c6SAndroid Build Coastguard Worker /* input buffer timedata is stored row-wise */
264*28e138c6SAndroid Build Coastguard Worker int k, ncfft;
265*28e138c6SAndroid Build Coastguard Worker
266*28e138c6SAndroid Build Coastguard Worker if (st->substate->inverse == 0) {
267*28e138c6SAndroid Build Coastguard Worker speex_fatal ("kiss fft usage error: improper alloc\n");
268*28e138c6SAndroid Build Coastguard Worker }
269*28e138c6SAndroid Build Coastguard Worker
270*28e138c6SAndroid Build Coastguard Worker ncfft = st->substate->nfft;
271*28e138c6SAndroid Build Coastguard Worker
272*28e138c6SAndroid Build Coastguard Worker st->tmpbuf[0].r = freqdata[0] + freqdata[2*ncfft-1];
273*28e138c6SAndroid Build Coastguard Worker st->tmpbuf[0].i = freqdata[0] - freqdata[2*ncfft-1];
274*28e138c6SAndroid Build Coastguard Worker /*C_FIXDIV(st->tmpbuf[0],2);*/
275*28e138c6SAndroid Build Coastguard Worker
276*28e138c6SAndroid Build Coastguard Worker for (k = 1; k <= ncfft / 2; ++k) {
277*28e138c6SAndroid Build Coastguard Worker kiss_fft_cpx fk, fnkc, fek, fok, tmp;
278*28e138c6SAndroid Build Coastguard Worker fk.r = freqdata[2*k-1];
279*28e138c6SAndroid Build Coastguard Worker fk.i = freqdata[2*k];
280*28e138c6SAndroid Build Coastguard Worker fnkc.r = freqdata[2*(ncfft - k)-1];
281*28e138c6SAndroid Build Coastguard Worker fnkc.i = -freqdata[2*(ncfft - k)];
282*28e138c6SAndroid Build Coastguard Worker /*C_FIXDIV( fk , 2 );
283*28e138c6SAndroid Build Coastguard Worker C_FIXDIV( fnkc , 2 );*/
284*28e138c6SAndroid Build Coastguard Worker
285*28e138c6SAndroid Build Coastguard Worker C_ADD (fek, fk, fnkc);
286*28e138c6SAndroid Build Coastguard Worker C_SUB (tmp, fk, fnkc);
287*28e138c6SAndroid Build Coastguard Worker C_MUL (fok, tmp, st->super_twiddles[k]);
288*28e138c6SAndroid Build Coastguard Worker C_ADD (st->tmpbuf[k], fek, fok);
289*28e138c6SAndroid Build Coastguard Worker C_SUB (st->tmpbuf[ncfft - k], fek, fok);
290*28e138c6SAndroid Build Coastguard Worker #ifdef USE_SIMD
291*28e138c6SAndroid Build Coastguard Worker st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
292*28e138c6SAndroid Build Coastguard Worker #else
293*28e138c6SAndroid Build Coastguard Worker st->tmpbuf[ncfft - k].i *= -1;
294*28e138c6SAndroid Build Coastguard Worker #endif
295*28e138c6SAndroid Build Coastguard Worker }
296*28e138c6SAndroid Build Coastguard Worker kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
297*28e138c6SAndroid Build Coastguard Worker }
298