SAF
Loading...
Searching...
No Matches
kiss_fftr.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
3 * This file is part of KISS FFT - https://github.com/mborgerding/kissfft
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 * See COPYING file for more information.
7 */
8
16#include "kiss_fftr.h"
17#include "_kiss_fft_guts.h"
18
21 kiss_fft_cfg substate;
22 kiss_fft_cpx * tmpbuf;
23 kiss_fft_cpx * super_twiddles;
24#ifdef USE_SIMD
25 void * pad;
26#endif
27};
28
29kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
30{
31 int i;
32 kiss_fftr_cfg st = NULL;
33 size_t subsize = 0, 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_alloc (nfft, inverse_fft, NULL, &subsize);
42 memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2);
43
44 if (lenmem == NULL) {
45 st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
46 } else {
47 if (*lenmem >= memneeded)
48 st = (kiss_fftr_cfg) mem;
49 *lenmem = memneeded;
50 }
51 if (!st)
52 return NULL;
53
54 st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
55 st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
56 st->super_twiddles = st->tmpbuf + nfft;
57 kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
58
59 for (i = 0; i < nfft/2; ++i) {
60 double phase =
61 -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5);
62 if (inverse_fft)
63 phase *= -1;
64 kf_cexp (st->super_twiddles+i,phase);
65 }
66 return st;
67}
68
69void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
70{
71 /* input buffer timedata is stored row-wise */
72 int k,ncfft;
73 kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
74
75 if ( st->substate->inverse) {
76 fprintf(stderr,"kiss fft usage error: improper alloc\n");
77 exit(1);
78 }
79
80 ncfft = st->substate->nfft;
81
82 /*perform the parallel fft of two real signals packed in real,imag*/
83 kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
84 /* The real part of the DC element of the frequency spectrum in st->tmpbuf
85 * contains the sum of the even-numbered elements of the input time sequence
86 * The imag part is the sum of the odd-numbered elements
87 *
88 * The sum of tdc.r and tdc.i is the sum of the input time sequence.
89 * yielding DC of input time sequence
90 * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
91 * yielding Nyquist bin of input time sequence
92 */
93
94 tdc.r = st->tmpbuf[0].r;
95 tdc.i = st->tmpbuf[0].i;
96 C_FIXDIV(tdc,2);
97 CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
98 CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
99 freqdata[0].r = tdc.r + tdc.i;
100 freqdata[ncfft].r = tdc.r - tdc.i;
101#ifdef USE_SIMD
102 freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
103#else
104 freqdata[ncfft].i = freqdata[0].i = 0;
105#endif
106
107 for ( k=1;k <= ncfft/2 ; ++k ) {
108 fpk = st->tmpbuf[k];
109 fpnk.r = st->tmpbuf[ncfft-k].r;
110 fpnk.i = - st->tmpbuf[ncfft-k].i;
111 C_FIXDIV(fpk,2);
112 C_FIXDIV(fpnk,2);
113
114 C_ADD( f1k, fpk , fpnk );
115 C_SUB( f2k, fpk , fpnk );
116 C_MUL( tw , f2k , st->super_twiddles[k-1]);
117
118 freqdata[k].r = HALF_OF(f1k.r + tw.r);
119 freqdata[k].i = HALF_OF(f1k.i + tw.i);
120 freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
121 freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
122 }
123}
124
125void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
126{
127 /* input buffer timedata is stored row-wise */
128 int k, ncfft;
129
130 if (st->substate->inverse == 0) {
131 fprintf (stderr, "kiss fft usage error: improper alloc\n");
132 exit (1);
133 }
134
135 ncfft = st->substate->nfft;
136
137 st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
138 st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
139 C_FIXDIV(st->tmpbuf[0],2);
140
141 for (k = 1; k <= ncfft / 2; ++k) {
142 kiss_fft_cpx fk, fnkc, fek, fok, tmp;
143 fk = freqdata[k];
144 fnkc.r = freqdata[ncfft - k].r;
145 fnkc.i = -freqdata[ncfft - k].i;
146 C_FIXDIV( fk , 2 );
147 C_FIXDIV( fnkc , 2 );
148
149 C_ADD (fek, fk, fnkc);
150 C_SUB (tmp, fk, fnkc);
151 C_MUL (fok, tmp, st->super_twiddles[k-1]);
152 C_ADD (st->tmpbuf[k], fek, fok);
153 C_SUB (st->tmpbuf[ncfft - k], fek, fok);
154#ifdef USE_SIMD
155 st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
156#else
157 st->tmpbuf[ncfft - k].i *= -1;
158#endif
159 }
160 kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
161}
KISS FFT internals, taken from: https://github.com/mborgerding/kissfft.
void kiss_fft(kiss_fft_cfg cfg, const kiss_fft_cpx *fin, kiss_fft_cpx *fout)
kiss_fft(cfg,in_out_buf)
Definition kiss_fft.c:386
kiss_fft_cfg kiss_fft_alloc(int nfft, int inverse_fft, void *mem, size_t *lenmem)
kiss_fft_alloc
Definition kiss_fft.c:340
The default real <-> half-complex FFT.
Complex data type used by kissFFT.
Definition kiss_fft.h:79
Internal KissFFT structure.
Definition kiss_fftr.c:20