tizen 2.3 release
[framework/multimedia/gst-plugins-base0.10.git] / gst-libs / gst / fft / kiss_fftr_f32.c
1 /*
2 Copyright (c) 2003-2004, Mark Borgerding
3
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7
8     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9     * 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     * 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
12 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 */
14
15 #include "kiss_fftr_f32.h"
16 #include "_kiss_fft_guts_f32.h"
17
18 struct kiss_fftr_f32_state
19 {
20   kiss_fft_f32_cfg substate;
21   kiss_fft_f32_cpx *tmpbuf;
22   kiss_fft_f32_cpx *super_twiddles;
23 #ifdef USE_SIMD
24   long pad;
25 #endif
26 };
27
28 kiss_fftr_f32_cfg
29 kiss_fftr_f32_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem)
30 {
31   int i;
32   kiss_fftr_f32_cfg st = NULL;
33   size_t subsize, memneeded;
34
35   if (nfft & 1) {
36     fprintf (stderr, "Real FFT optimization must be even.\n");
37     return NULL;
38   }
39   nfft >>= 1;
40
41   kiss_fft_f32_alloc (nfft, inverse_fft, NULL, &subsize);
42   memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_f32_state))
43       + ALIGN_STRUCT (subsize) + sizeof (kiss_fft_f32_cpx) * (nfft * 3 / 2);
44
45   if (lenmem == NULL) {
46     st = (kiss_fftr_f32_cfg) KISS_FFT_F32_MALLOC (memneeded);
47   } else {
48     if (*lenmem >= memneeded)
49       st = (kiss_fftr_f32_cfg) mem;
50     *lenmem = memneeded;
51   }
52   if (!st)
53     return NULL;
54
55   st->substate = (kiss_fft_f32_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_f32_state)));       /*just beyond kiss_fftr_f32_state struct */
56   st->tmpbuf =
57       (kiss_fft_f32_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize));
58   st->super_twiddles = st->tmpbuf + nfft;
59   kiss_fft_f32_alloc (nfft, inverse_fft, st->substate, &subsize);
60
61   for (i = 0; i < nfft / 2; ++i) {
62     double phase =
63         -3.14159265358979323846264338327 * ((double) (i + 1) / nfft + .5);
64
65     if (inverse_fft)
66       phase *= -1;
67     kf_cexp (st->super_twiddles + i, phase);
68   }
69   return st;
70 }
71
72 void
73 kiss_fftr_f32 (kiss_fftr_f32_cfg st, const kiss_fft_f32_scalar * timedata,
74     kiss_fft_f32_cpx * freqdata)
75 {
76   /* input buffer timedata is stored row-wise */
77   int k, ncfft;
78   kiss_fft_f32_cpx fpnk, fpk, f1k, f2k, tw, tdc;
79
80   if (st->substate->inverse) {
81     fprintf (stderr, "kiss fft usage error: improper alloc\n");
82     exit (1);
83   }
84
85   ncfft = st->substate->nfft;
86
87   /*perform the parallel fft of two real signals packed in real,imag */
88   kiss_fft_f32 (st->substate, (const kiss_fft_f32_cpx *) timedata, st->tmpbuf);
89   /* The real part of the DC element of the frequency spectrum in st->tmpbuf
90    * contains the sum of the even-numbered elements of the input time sequence
91    * The imag part is the sum of the odd-numbered elements
92    *
93    * The sum of tdc.r and tdc.i is the sum of the input time sequence. 
94    *      yielding DC of input time sequence
95    * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... 
96    *      yielding Nyquist bin of input time sequence
97    */
98
99   tdc.r = st->tmpbuf[0].r;
100   tdc.i = st->tmpbuf[0].i;
101   C_FIXDIV (tdc, 2);
102   CHECK_OVERFLOW_OP (tdc.r, +, tdc.i);
103   CHECK_OVERFLOW_OP (tdc.r, -, tdc.i);
104   freqdata[0].r = tdc.r + tdc.i;
105   freqdata[ncfft].r = tdc.r - tdc.i;
106 #ifdef USE_SIMD
107   freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps (0);
108 #else
109   freqdata[ncfft].i = freqdata[0].i = 0;
110 #endif
111
112   for (k = 1; k <= ncfft / 2; ++k) {
113     fpk = st->tmpbuf[k];
114     fpnk.r = st->tmpbuf[ncfft - k].r;
115     fpnk.i = -st->tmpbuf[ncfft - k].i;
116     C_FIXDIV (fpk, 2);
117     C_FIXDIV (fpnk, 2);
118
119     C_ADD (f1k, fpk, fpnk);
120     C_SUB (f2k, fpk, fpnk);
121     C_MUL (tw, f2k, st->super_twiddles[k - 1]);
122
123     freqdata[k].r = HALF_OF (f1k.r + tw.r);
124     freqdata[k].i = HALF_OF (f1k.i + tw.i);
125     freqdata[ncfft - k].r = HALF_OF (f1k.r - tw.r);
126     freqdata[ncfft - k].i = HALF_OF (tw.i - f1k.i);
127   }
128 }
129
130 void
131 kiss_fftri_f32 (kiss_fftr_f32_cfg st, const kiss_fft_f32_cpx * freqdata,
132     kiss_fft_f32_scalar * timedata)
133 {
134   /* input buffer timedata is stored row-wise */
135   int k, ncfft;
136
137   if (st->substate->inverse == 0) {
138     fprintf (stderr, "kiss fft usage error: improper alloc\n");
139     exit (1);
140   }
141
142   ncfft = st->substate->nfft;
143
144   st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
145   st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
146   C_FIXDIV (st->tmpbuf[0], 2);
147
148   for (k = 1; k <= ncfft / 2; ++k) {
149     kiss_fft_f32_cpx fk, fnkc, fek, fok, tmp;
150
151     fk = freqdata[k];
152     fnkc.r = freqdata[ncfft - k].r;
153     fnkc.i = -freqdata[ncfft - k].i;
154     C_FIXDIV (fk, 2);
155     C_FIXDIV (fnkc, 2);
156
157     C_ADD (fek, fk, fnkc);
158     C_SUB (tmp, fk, fnkc);
159     C_MUL (fok, tmp, st->super_twiddles[k - 1]);
160     C_ADD (st->tmpbuf[k], fek, fok);
161     C_SUB (st->tmpbuf[ncfft - k], fek, fok);
162 #ifdef USE_SIMD
163     st->tmpbuf[ncfft - k].i *= _mm_set1_ps (-1.0);
164 #else
165     st->tmpbuf[ncfft - k].i *= -1;
166 #endif
167   }
168   kiss_fft_f32 (st->substate, st->tmpbuf, (kiss_fft_f32_cpx *) timedata);
169 }