LMMS
Loading...
Searching...
No Matches
eel_fft.h
Go to the documentation of this file.
1#ifndef __EEL_FFT_H_
2#define __EEL_FFT_H_
3
4#include "../fft.h"
5#if WDL_FFT_REALSIZE != EEL_F_SIZE
6#error WDL_FFT_REALSIZE -- EEL_F_SIZE size mismatch
7#endif
8
9#ifndef EEL_FFT_MINBITLEN
10#define EEL_FFT_MINBITLEN 4
11#endif
12
13#ifndef EEL_FFT_MAXBITLEN
14#define EEL_FFT_MAXBITLEN 15
15#endif
16
17#ifndef EEL_FFT_MINBITLEN_REORDER
18#define EEL_FFT_MINBITLEN_REORDER (EEL_FFT_MINBITLEN-1)
19#endif
20
21//#define EEL_SUPER_FAST_FFT_REORDERING // quite a bit faster (50-100%) than "normal", but uses a 256kb lookup
22//#define EEL_SLOW_FFT_REORDERING // 20%-80% slower than normal, alloca() use, no reason to ever use this
23
24#ifdef EEL_SUPER_FAST_FFT_REORDERING
25static int *fft_reorder_table_for_bitsize(int bitsz)
26{
27 static int s_tab[ (2 << EEL_FFT_MAXBITLEN) + 24*(EEL_FFT_MAXBITLEN-EEL_FFT_MINBITLEN_REORDER+1) ]; // big 256kb table, ugh
28 if (bitsz<=EEL_FFT_MINBITLEN_REORDER) return s_tab;
29 return s_tab + (1<<bitsz) + (bitsz-EEL_FFT_MINBITLEN_REORDER) * 24;
30}
31static void fft_make_reorder_table(int bitsz, int *tab)
32{
33 const int fft_sz=1<<bitsz;
34 char flag[1<<EEL_FFT_MAXBITLEN];
35 int x;
36 int *tabstart = tab;
37 memset(flag,0,fft_sz);
38
39 for (x=0;x<fft_sz;x++)
40 {
41 int fx;
42 if (!flag[x] && (fx=WDL_fft_permute(fft_sz,x))!=x)
43 {
44 flag[x]=1;
45 *tab++ = x;
46 do
47 {
48 flag[fx]=1;
49 *tab++ = fx;
50 fx = WDL_fft_permute(fft_sz, fx);
51 }
52 while (fx != x);
53 *tab++ = 0; // delimit a run
54 }
55 else flag[x]=1;
56 }
57 *tab++ = 0; // doublenull terminated
58}
59
60static void fft_reorder_buffer(int bitsz, WDL_FFT_COMPLEX *data, int fwd)
61{
62 const int *tab=fft_reorder_table_for_bitsize(bitsz);
63 if (!fwd)
64 {
65 while (*tab)
66 {
67 const int sidx=*tab++;
69 for (;;)
70 {
72 const int idx=*tab++;
73 if (!idx) break;
74 ta=data[idx];
75 data[idx]=a;
76 a=ta;
77 }
78 data[sidx] = a;
79 }
80 }
81 else
82 {
83 while (*tab)
84 {
85 const int sidx=*tab++;
86 int lidx = sidx;
87 const WDL_FFT_COMPLEX sta=data[lidx];
88 for (;;)
89 {
90 const int idx=*tab++;
91 if (!idx) break;
92
93 data[lidx]=data[idx];
94 lidx=idx;
95 }
96 data[lidx] = sta;
97 }
98 }
99 return 1;
100}
101#else
102#ifndef EEL_SLOW_FFT_REORDERING
103 // moderate speed mode, minus the big 256k table
104
105static void fft_reorder_buffer(int bitsz, WDL_FFT_COMPLEX *data, int fwd)
106{
107 // this is a good compromise, quite a bit faster than out of place reordering, but no separate 256kb lookup required
108 /*
109 these generated via:
110 static void fft_make_reorder_table(int bitsz)
111 {
112 int fft_sz=1<<bitsz,x;
113 char flag[65536]={0,};
114 printf("static const int tab%d[]={ ",fft_sz);
115 for (x=0;x<fft_sz;x++)
116 {
117 int fx;
118 if (!flag[x] && (fx=WDL_fft_permute(fft_sz,x))!=x)
119 {
120 printf("%d, ",x);
121 do { flag[fx]=1; fx = WDL_fft_permute(fft_sz, fx); } while (fx != x);
122 }
123 flag[x]=1;
124 }
125 printf(" 0 };\n");
126 }
127 */
128
129 static const int tab4_8_32[]={ 1, 0 };
130 static const int tab16[]={ 1, 3, 0 };
131 static const int tab64[]={ 1, 3, 9, 0 };
132 static const int tab128[]={ 1, 3, 4, 9, 14, 0 };
133 static const int tab256[]={ 1, 3, 6, 12, 13, 14, 19, 0 };
134 static const int tab512[]={ 1, 4, 7, 9, 18, 50, 115, 0 };
135 static const int tab1024[]={ 1, 3, 4, 25, 26, 77, 79, 0 };
136 static const int tab2048[]={ 1, 58, 59, 106, 135, 206, 210, 212, 0 };
137 static const int tab4096[]={ 1, 3, 12, 25, 54, 221, 313, 431, 453, 0 };
138 static const int tab8192[]={ 1, 12, 18, 26, 30, 100, 101, 106, 113, 144, 150, 237, 244, 247, 386, 468, 513, 1210, 4839, 0 };
139 static const int tab16384[]={ 1, 3, 6, 24, 1219, 0 };
140 static const int tab32768[]={ 1, 3, 4, 7, 13, 18, 31, 64, 113, 145, 203, 246, 594, 956, 1871, 2439, 4959, 19175, 0 };
141 const int *tab;
142
143 switch (bitsz)
144 {
145 case 1: return; // no reorder necessary
146 case 2:
147 case 3:
148 case 5: tab = tab4_8_32; break;
149 case 4: tab=tab16; break;
150 case 6: tab=tab64; break;
151 case 7: tab=tab128; break;
152 case 8: tab=tab256; break;
153 case 9: tab=tab512; break;
154 case 10: tab=tab1024; break;
155 case 11: tab=tab2048; break;
156 case 12: tab=tab4096; break;
157 case 13: tab=tab8192; break;
158 case 14: tab=tab16384; break;
159 case 15: tab=tab32768; break;
160 default: return; // no reorder possible
161 }
162
163 const int fft_sz=1<<bitsz;
164 const int *tb2 = WDL_fft_permute_tab(fft_sz);
165 if (!tb2) return; // ugh
166
167 if (!fwd)
168 {
169 while (*tab)
170 {
171 const int sidx=*tab++;
172 WDL_FFT_COMPLEX a=data[sidx];
173 int idx=sidx;
174 for (;;)
175 {
177 idx=tb2[idx];
178 if (idx==sidx) break;
179 ta=data[idx];
180 data[idx]=a;
181 a=ta;
182 }
183 data[sidx] = a;
184 }
185 }
186 else
187 {
188 while (*tab)
189 {
190 const int sidx=*tab++;
191 int lidx = sidx;
192 const WDL_FFT_COMPLEX sta=data[lidx];
193 for (;;)
194 {
195 const int idx=tb2[lidx];
196 if (idx==sidx) break;
197
198 data[lidx]=data[idx];
199 lidx=idx;
200 }
201 data[lidx] = sta;
202 }
203 }
204}
205
206#endif // not fast ,not slow, just right
207
208#endif
209
210//#define TIMING
211//#include "../timing.h"
212
213// 0=fw, 1=iv, 2=fwreal, 3=ireal, 4=permutec, 6=permuter
214// low bit: is inverse
215// second bit: was isreal, but no longer used
216// third bit: is permute
217static void FFT(int sizebits, EEL_F *data, int dir)
218{
219 if (dir >= 4 && dir < 8)
220 {
221 if (dir == 4 || dir == 5)
222 {
223 //timingEnter(0);
224#if defined(EEL_SUPER_FAST_FFT_REORDERING) || !defined(EEL_SLOW_FFT_REORDERING)
225 fft_reorder_buffer(sizebits,(WDL_FFT_COMPLEX*)data,dir==4);
226#else
227 // old blech
228 const int flen=1<<sizebits;
229 int x;
230 EEL_F *tmp=(EEL_F*)alloca(sizeof(EEL_F)*flen*2);
231 const int flen2=flen+flen;
232 // reorder entries, now
233 memcpy(tmp,data,sizeof(EEL_F)*flen*2);
234
235 if (dir == 4)
236 {
237 for (x = 0; x < flen2; x += 2)
238 {
239 int y=WDL_fft_permute(flen,x/2)*2;
240 data[x]=tmp[y];
241 data[x+1]=tmp[y+1];
242 }
243 }
244 else
245 {
246 for (x = 0; x < flen2; x += 2)
247 {
248 int y=WDL_fft_permute(flen,x/2)*2;
249 data[y]=tmp[x];
250 data[y+1]=tmp[x+1];
251 }
252 }
253#endif
254 //timingLeave(0);
255 }
256 }
257 else if (dir >= 0 && dir < 2)
258 {
259 WDL_fft((WDL_FFT_COMPLEX*)data,1<<sizebits,dir&1);
260 }
261 else if (dir >= 2 && dir < 4)
262 {
263 WDL_real_fft((WDL_FFT_REAL*)data,1<<sizebits,dir&1);
264 }
265}
266
267
268
269static EEL_F * fft_func(int dir, EEL_F **blocks, EEL_F *start, EEL_F *length)
270{
271 const int offs = (int)(*start + 0.0001);
272 const int itemSizeShift=(dir&2)?0:1;
273 int l=(int)(*length + 0.0001);
274 int bitl=0;
275 int ilen;
276 EEL_F *ptr;
277 while (l>1 && bitl < EEL_FFT_MAXBITLEN)
278 {
279 bitl++;
280 l>>=1;
281 }
282 if (bitl < ((dir&4) ? EEL_FFT_MINBITLEN_REORDER : EEL_FFT_MINBITLEN)) // smallest FFT is 16 item, smallest reorder is 8 item
283 {
284 return start;
285 }
286 ilen=1<<bitl;
287
288
289 // check to make sure we don't cross a boundary
290 if (offs/NSEEL_RAM_ITEMSPERBLOCK != (offs + (ilen<<itemSizeShift) - 1)/NSEEL_RAM_ITEMSPERBLOCK)
291 {
292 return start;
293 }
294
295 ptr=__NSEEL_RAMAlloc(blocks,offs);
296 if (!ptr || ptr==&nseel_ramalloc_onfail)
297 {
298 return start;
299 }
300
301 FFT(bitl,ptr,dir);
302
303 return start;
304}
305
306static EEL_F * NSEEL_CGEN_CALL eel_fft(EEL_F **blocks, EEL_F *start, EEL_F *length)
307{
308 return fft_func(0,blocks,start,length);
309}
310
311static EEL_F * NSEEL_CGEN_CALL eel_ifft(EEL_F **blocks, EEL_F *start, EEL_F *length)
312{
313 return fft_func(1,blocks,start,length);
314}
315
316static EEL_F * NSEEL_CGEN_CALL eel_fft_real(EEL_F **blocks, EEL_F *start, EEL_F *length)
317{
318 return fft_func(2,blocks,start,length);
319}
320
321static EEL_F * NSEEL_CGEN_CALL eel_ifft_real(EEL_F **blocks, EEL_F *start, EEL_F *length)
322{
323 return fft_func(3,blocks,start,length);
324}
325
326static EEL_F * NSEEL_CGEN_CALL eel_fft_permute(EEL_F **blocks, EEL_F *start, EEL_F *length)
327{
328 return fft_func(4,blocks,start,length);
329}
330
331static EEL_F * NSEEL_CGEN_CALL eel_ifft_permute(EEL_F **blocks, EEL_F *start, EEL_F *length)
332{
333 return fft_func(5,blocks,start,length);
334}
335
336static EEL_F * NSEEL_CGEN_CALL eel_convolve_c(EEL_F **blocks,EEL_F *dest, EEL_F *src, EEL_F *lenptr)
337{
338 const int dest_offs = (int)(*dest + 0.0001);
339 const int src_offs = (int)(*src + 0.0001);
340 const int len = ((int)(*lenptr + 0.0001)) * 2;
341 EEL_F *srcptr,*destptr;
342
343 if (len < 1 || len > NSEEL_RAM_ITEMSPERBLOCK || dest_offs < 0 || src_offs < 0 ||
345 if ((dest_offs&(NSEEL_RAM_ITEMSPERBLOCK-1)) + len > NSEEL_RAM_ITEMSPERBLOCK) return dest;
346 if ((src_offs&(NSEEL_RAM_ITEMSPERBLOCK-1)) + len > NSEEL_RAM_ITEMSPERBLOCK) return dest;
347
348 srcptr = __NSEEL_RAMAlloc(blocks,src_offs);
349 if (!srcptr || srcptr==&nseel_ramalloc_onfail) return dest;
350 destptr = __NSEEL_RAMAlloc(blocks,dest_offs);
351 if (!destptr || destptr==&nseel_ramalloc_onfail) return dest;
352
353
354 WDL_fft_complexmul((WDL_FFT_COMPLEX*)destptr,(WDL_FFT_COMPLEX*)srcptr,(len/2)&~1);
355
356 return dest;
357}
358
360{
361 WDL_fft_init();
362#if defined(EEL_SUPER_FAST_FFT_REORDERING)
363 if (!fft_reorder_table_for_bitsize(EEL_FFT_MINBITLEN_REORDER)[0])
364 {
365 int x;
366 for (x=EEL_FFT_MINBITLEN_REORDER;x<=EEL_FFT_MAXBITLEN;x++) fft_make_reorder_table(x,fft_reorder_table_for_bitsize(x));
367 }
368#endif
376}
377
378#ifdef EEL_WANT_DOCUMENTATION
379static const char *eel_fft_function_reference =
380"convolve_c\tdest,src,size\tMultiplies each of size complex pairs in dest by the complex pairs in src. Often used for convolution.\0"
381"fft\tbuffer,size\tPerforms a FFT on the data in the local memory buffer at the offset specified by the first parameter. The size of the FFT is specified "
382 "by the second parameter, which must be 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, or 32768. The outputs are permuted, so if "
383 "you plan to use them in-order, call fft_permute(buffer, size) before and fft_ipermute(buffer,size) after your in-order use. Your inputs or "
384 "outputs will need to be scaled down by 1/size, if used.\n"
385 "Note that fft()/ifft() require real / imaginary input pairs, so a 256 point FFT actually works with 512 items.\n"
386 "Note that fft()/ifft() must NOT cross a 65,536 item boundary, so be sure to specify the offset accordingly.\0"
387"ifft\tbuffer,size\tPerform an inverse FFT. For more information see fft().\0"
388"fft_real\tbuffer,size\tPerforms an FFT, but takes size input samples and produces size/2 complex output pairs. Usually used along with fft_permute(size/2). Inputs/outputs will need to be scaled by 0.5/size.\0"
389"ifft_real\tbuffer,size\tPerforms an inverse FFT, but takes size/2 complex input pairs and produces size real output values. Usually used along with fft_ipermute(size/2).\0"
390"fft_permute\tbuffer,size\tPermute the output of fft() to have bands in-order. See fft() for more information.\0"
391"fft_ipermute\tbuffer,size\tPermute the input for ifft(), taking bands from in-order to the order ifft() requires. See fft() for more information.\0"
392;
393#endif
394
395
396#endif
float WDL_FFT_REAL
Definition fft.h:42
uint8_t a
Definition Spc_Cpu.h:141
int * l
Definition inflate.c:1579
int y
Definition inflate.c:1588
unsigned x[BMAX+1]
Definition inflate.c:1586
static EEL_F *NSEEL_CGEN_CALL eel_fft(EEL_F **blocks, EEL_F *start, EEL_F *length)
Definition eel_fft.h:306
static EEL_F *NSEEL_CGEN_CALL eel_ifft(EEL_F **blocks, EEL_F *start, EEL_F *length)
Definition eel_fft.h:311
static void FFT(int sizebits, EEL_F *data, int dir)
Definition eel_fft.h:217
void EEL_fft_register()
Definition eel_fft.h:359
#define EEL_FFT_MINBITLEN
Definition eel_fft.h:10
static EEL_F *NSEEL_CGEN_CALL eel_convolve_c(EEL_F **blocks, EEL_F *dest, EEL_F *src, EEL_F *lenptr)
Definition eel_fft.h:336
#define EEL_FFT_MAXBITLEN
Definition eel_fft.h:14
static EEL_F *NSEEL_CGEN_CALL eel_ifft_real(EEL_F **blocks, EEL_F *start, EEL_F *length)
Definition eel_fft.h:321
static EEL_F *NSEEL_CGEN_CALL eel_ifft_permute(EEL_F **blocks, EEL_F *start, EEL_F *length)
Definition eel_fft.h:331
#define EEL_FFT_MINBITLEN_REORDER
Definition eel_fft.h:18
static EEL_F * fft_func(int dir, EEL_F **blocks, EEL_F *start, EEL_F *length)
Definition eel_fft.h:269
static EEL_F *NSEEL_CGEN_CALL eel_fft_permute(EEL_F **blocks, EEL_F *start, EEL_F *length)
Definition eel_fft.h:326
static EEL_F *NSEEL_CGEN_CALL eel_fft_real(EEL_F **blocks, EEL_F *start, EEL_F *length)
Definition eel_fft.h:316
static void fft_reorder_buffer(int bitsz, WDL_FFT_COMPLEX *data, int fwd)
Definition eel_fft.h:105
#define NSEEL_addfunc_retptr(name, np, pproc, fptr)
Definition eel_import.h:55
void *(* NSEEL_PProc_RAM)(void *data, int data_size, struct _compileContext *ctx)
Definition eel_import.h:39
int * WDL_fft_permute_tab(int fftsize)
Definition fft.c:1022
void WDL_fft_complexmul(WDL_FFT_COMPLEX *a, WDL_FFT_COMPLEX *b, int n)
Definition fft.c:580
void WDL_real_fft(WDL_FFT_REAL *buf, int len, int isInverse)
Definition fft.c:1178
void WDL_fft_init()
Definition fft.c:1030
int WDL_fft_permute(int fftsize, int idx)
Definition fft.c:1018
void WDL_fft(WDL_FFT_COMPLEX *buf, int len, int isInverse)
Definition fft.c:1065
virtual ASIOError start()=0
JSAMPIMAGE data
Definition jpeglib.h:945
EEL_F *NSEEL_CGEN_CALL __NSEEL_RAMAlloc(EEL_F **blocks, unsigned int w)
Definition nseel-ram.c:139
EEL_F nseel_ramalloc_onfail
Definition nseel-ram.c:92
#define NSEEL_CGEN_CALL
Definition ns-eel.h:44
#define NSEEL_RAM_ITEMSPERBLOCK
Definition ns-eel.h:235
#define NSEEL_RAM_BLOCKS
Definition ns-eel.h:234
png_uint_32 length
Definition png.c:2247
Definition fft.h:49
memcpy(hh, h, RAND_HEAD_LEN)
int flag
Definition unix.c:754
typedef int(UZ_EXP MsgFn)()