summaryrefslogtreecommitdiff
path: root/codec2_fft.c
diff options
context:
space:
mode:
authorerdgeist@erdgeist.org <erdgeist@bauklotz.fritz.box>2019-07-04 23:26:09 +0200
committererdgeist@erdgeist.org <erdgeist@bauklotz.fritz.box>2019-07-04 23:26:09 +0200
commitf02dfce6e6c34b3d8a7b8a0e784b506178e331fa (patch)
tree45556e6104242d4702689760433d7321ae74ec17 /codec2_fft.c
stripdown of version 0.9
Diffstat (limited to 'codec2_fft.c')
-rw-r--r--codec2_fft.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/codec2_fft.c b/codec2_fft.c
new file mode 100644
index 0000000..14b8670
--- /dev/null
+++ b/codec2_fft.c
@@ -0,0 +1,158 @@
1/*
2 * codec2_fft.c
3 *
4 * Created on: 24.09.2016
5 * Author: danilo
6 */
7
8#include "codec2_fft.h"
9
10#include "debug_alloc.h"
11
12#ifdef USE_KISS_FFT
13#include "_kiss_fft_guts.h"
14
15#else
16#if 0
17// caching constants in RAM did not seem to have an effect on performance
18// TODO: Decide what to with this code
19#define FFT_INIT_CACHE_SIZE 4
20const arm_cfft_instance_f32* fft_init_cache[FFT_INIT_CACHE_SIZE];
21
22static const arm_cfft_instance_f32* arm_fft_instance2ram(const arm_cfft_instance_f32* in)
23{
24
25 arm_cfft_instance_f32* out = malloc(sizeof(arm_cfft_instance_f32));
26
27 if (out) {
28 memcpy(out,in,sizeof(arm_cfft_instance_f32));
29 out->pBitRevTable = malloc(out->bitRevLength * sizeof(uint16_t));
30 out->pTwiddle = malloc(out->fftLen * sizeof(float32_t));
31 memcpy((void*)out->pBitRevTable,in->pBitRevTable,out->bitRevLength * sizeof(uint16_t));
32 memcpy((void*)out->pTwiddle,in->pTwiddle,out->fftLen * sizeof(float32_t));
33 }
34 return out;
35}
36
37
38static const arm_cfft_instance_f32* arm_fft_cache_get(const arm_cfft_instance_f32* romfft)
39{
40 const arm_cfft_instance_f32* retval = NULL;
41 static int used = 0;
42 for (int i = 0; fft_init_cache[i] != NULL && i < used; i++)
43 {
44 if (romfft->fftLen == fft_init_cache[i]->fftLen)
45 {
46 retval = fft_init_cache[i];
47 break;
48 }
49 }
50 if (retval == NULL && used < FFT_INIT_CACHE_SIZE)
51 {
52 retval = arm_fft_instance2ram(romfft);
53 fft_init_cache[used++] = retval;
54 }
55 if (retval == NULL)
56 {
57 retval = romfft;
58 }
59 return retval;
60}
61#endif
62#endif
63
64void codec2_fft_free(codec2_fft_cfg cfg)
65{
66#ifdef USE_KISS_FFT
67 KISS_FFT_FREE(cfg);
68#else
69 FREE(cfg);
70#endif
71}
72
73codec2_fft_cfg codec2_fft_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem)
74{
75 codec2_fft_cfg retval;
76#ifdef USE_KISS_FFT
77 retval = kiss_fft_alloc(nfft, inverse_fft, mem, lenmem);
78#else
79 retval = MALLOC(sizeof(codec2_fft_struct));
80 retval->inverse = inverse_fft;
81 switch(nfft)
82 {
83 case 128:
84 retval->instance = &arm_cfft_sR_f32_len128;
85 break;
86 case 256:
87 retval->instance = &arm_cfft_sR_f32_len256;
88 break;
89 case 512:
90 retval->instance = &arm_cfft_sR_f32_len512;
91 break;
92// case 1024:
93// retval->instance = &arm_cfft_sR_f32_len1024;
94// break;
95 default:
96 abort();
97 }
98 // retval->instance = arm_fft_cache_get(retval->instance);
99#endif
100 return retval;
101}
102
103codec2_fftr_cfg codec2_fftr_alloc(int nfft, int inverse_fft, void* mem, size_t* lenmem)
104{
105 codec2_fftr_cfg retval;
106#ifdef USE_KISS_FFT
107 retval = kiss_fftr_alloc(nfft, inverse_fft, mem, lenmem);
108#else
109 retval = MALLOC(sizeof(codec2_fftr_struct));
110 retval->inverse = inverse_fft;
111 retval->instance = MALLOC(sizeof(arm_rfft_fast_instance_f32));
112 arm_rfft_fast_init_f32(retval->instance,nfft);
113 // memcpy(&retval->instance->Sint,arm_fft_cache_get(&retval->instance->Sint),sizeof(arm_cfft_instance_f32));
114#endif
115 return retval;
116}
117void codec2_fftr_free(codec2_fftr_cfg cfg)
118{
119#ifdef USE_KISS_FFT
120 KISS_FFT_FREE(cfg);
121#else
122 FREE(cfg->instance);
123 FREE(cfg);
124#endif
125}
126
127// there is a little overhead for inplace kiss_fft but this is
128// on the powerful platforms like the Raspberry or even x86 PC based ones
129// not noticeable
130// the reduced usage of RAM and increased performance on STM32 platforms
131// should be worth it.
132void codec2_fft_inplace(codec2_fft_cfg cfg, codec2_fft_cpx* inout)
133{
134
135#ifdef USE_KISS_FFT
136 kiss_fft_cpx in[512];
137 // decide whether to use the local stack based buffer for in
138 // or to allow kiss_fft to allocate RAM
139 // second part is just to play safe since first method
140 // is much faster and uses less RAM
141 if (cfg->nfft <= 512)
142 {
143 memcpy(in,inout,cfg->nfft*sizeof(kiss_fft_cpx));
144 kiss_fft(cfg, in, (kiss_fft_cpx*)inout);
145 }
146 else
147 {
148 kiss_fft(cfg, (kiss_fft_cpx*)inout, (kiss_fft_cpx*)inout);
149 }
150#else
151 arm_cfft_f32(cfg->instance,(float*)inout,cfg->inverse,1);
152 if (cfg->inverse)
153 {
154 arm_scale_f32((float*)inout,cfg->instance->fftLen,(float*)inout,cfg->instance->fftLen*2);
155 }
156
157#endif
158}