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 | |
9 | #include "kfc.h" |
10 | |
11 | typedef struct cached_fft *kfc_cfg; |
12 | |
13 | struct cached_fft |
14 | { |
15 | int nfft; |
16 | int inverse; |
17 | kiss_fft_cfg cfg; |
18 | kfc_cfg next; |
19 | }; |
20 | |
21 | static kfc_cfg cache_root=NULL; |
22 | static int ncached=0; |
23 | |
24 | static kiss_fft_cfg find_cached_fft(int nfft,int inverse) |
25 | { |
26 | size_t len; |
27 | kfc_cfg cur=cache_root; |
28 | kfc_cfg prev=NULL; |
29 | while ( cur ) { |
30 | if ( cur->nfft == nfft && inverse == cur->inverse ) |
31 | break;/*found the right node*/ |
32 | prev = cur; |
33 | cur = prev->next; |
34 | } |
35 | if (cur== NULL) { |
36 | /* no cached node found, need to create a new one*/ |
37 | kiss_fft_alloc(nfft,inverse,0,&len); |
38 | #ifdef USE_SIMD |
39 | int padding = (16-sizeof(struct cached_fft)) & 15; |
40 | // make sure the cfg aligns on a 16 byte boundary |
41 | len += padding; |
42 | #endif |
43 | cur = (kfc_cfg)KISS_FFT_MALLOC((sizeof(struct cached_fft) + len )); |
44 | if (cur == NULL) |
45 | return NULL; |
46 | cur->cfg = (kiss_fft_cfg)(cur+1); |
47 | #ifdef USE_SIMD |
48 | cur->cfg = (kiss_fft_cfg) ((char*)(cur+1)+padding); |
49 | #endif |
50 | kiss_fft_alloc(nfft,inverse,cur->cfg,&len); |
51 | cur->nfft=nfft; |
52 | cur->inverse=inverse; |
53 | cur->next = NULL; |
54 | if ( prev ) |
55 | prev->next = cur; |
56 | else |
57 | cache_root = cur; |
58 | ++ncached; |
59 | } |
60 | return cur->cfg; |
61 | } |
62 | |
63 | void kfc_cleanup(void) |
64 | { |
65 | kfc_cfg cur=cache_root; |
66 | kfc_cfg next=NULL; |
67 | while (cur){ |
68 | next = cur->next; |
69 | free(cur); |
70 | cur=next; |
71 | } |
72 | ncached=0; |
73 | cache_root = NULL; |
74 | } |
75 | void kfc_fft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout) |
76 | { |
77 | kiss_fft( find_cached_fft(nfft,0),fin,fout ); |
78 | } |
79 | |
80 | void kfc_ifft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout) |
81 | { |
82 | kiss_fft( find_cached_fft(nfft,1),fin,fout ); |
83 | } |
84 | |
85 | #ifdef KFC_TEST |
86 | static void check(int nc) |
87 | { |
88 | if (ncached != nc) { |
89 | fprintf(stderr,"ncached should be %d,but it is %d\n" ,nc,ncached); |
90 | exit(1); |
91 | } |
92 | } |
93 | |
94 | int main(void) |
95 | { |
96 | kiss_fft_cpx buf1[1024],buf2[1024]; |
97 | memset(buf1,0,sizeof(buf1)); |
98 | check(0); |
99 | kfc_fft(512,buf1,buf2); |
100 | check(1); |
101 | kfc_fft(512,buf1,buf2); |
102 | check(1); |
103 | kfc_ifft(512,buf1,buf2); |
104 | check(2); |
105 | kfc_cleanup(); |
106 | check(0); |
107 | return 0; |
108 | } |
109 | #endif |
110 | |