FastLED 3.9.15
Loading...
Searching...
No Matches
kiss_fftr.cpp.hpp
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
9#include "fl/stl/cstddef.h"
10#include "fl/stl/stdio.h"
11#include "fl/stl/noexcept.h"
12#include "kiss_fftr.h"
13#include "_kiss_fft_guts.h"
14#include "fl/stl/string.h"
15#include "fl/stl/cstring.h" // for fl::memset() and fl::memcpy()
16
17// Ensure NULL is defined (standard C macro)
18#ifndef NULL
19#define NULL 0
20#endif
21
22#include "fl/log/log.h"
23#include "fl/stl/malloc.h"
24#include "fl/system/exit.h"
25
30#ifdef USE_SIMD
31 void * pad;
32#endif
33};
34
35kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) FL_NOEXCEPT
36{
37 int i;
39 size_t subsize = 0, memneeded;
40
41 if (nfft & 1) {
42 //fprintf(stderr,"Real FFT optimization must be even.\n");
43 FL_WARN("Real FFT optimization must be even.");
44 return NULL;
45 }
46 nfft >>= 1;
47
48 kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
49 memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2);
50
51 if (lenmem == NULL) {
52 st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
53 } else {
54 if (*lenmem >= memneeded)
55 st = (kiss_fftr_cfg) mem;
56 *lenmem = memneeded;
57 }
58 if (!st)
59 return NULL;
60
61 st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
62
63 #pragma GCC diagnostic push
64 #pragma GCC diagnostic ignored "-Wcast-align"
65 // This cast alginment might be a problem, kiss_fft_cpx has alignment-2.
66 st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
67 #pragma GCC diagnostic pop
68
69 st->super_twiddles = st->tmpbuf + nfft;
70 kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
71
72 for (i = 0; i < nfft/2; ++i) {
73 double phase =
74 -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5);
75 if (inverse_fft)
76 phase *= -1;
77 kf_cexp (st->super_twiddles+i,phase);
78 }
79 return st;
80}
81
83{
84 /* input buffer timedata is stored row-wise */
85 int k,ncfft;
86 kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
87
88 if ( st->substate->inverse) {
89 //fprintf(stderr,"kiss fft usage error: improper alloc\n");
90 FL_WARN("kiss fft usage error: improper alloc");
91 fl::exit(1);
92 }
93
94 ncfft = st->substate->nfft;
95
96 /*perform the parallel fft of two real signals packed in real,imag*/
97 kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
98 /* The real part of the DC element of the frequency spectrum in st->tmpbuf
99 * contains the sum of the even-numbered elements of the input time sequence
100 * The imag part is the sum of the odd-numbered elements
101 *
102 * The sum of tdc.r and tdc.i is the sum of the input time sequence.
103 * yielding DC of input time sequence
104 * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
105 * yielding Nyquist bin of input time sequence
106 */
107
108 tdc.r = st->tmpbuf[0].r;
109 tdc.i = st->tmpbuf[0].i;
110 C_FIXDIV(tdc,2);
111 CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
112 CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
113 freqdata[0].r = tdc.r + tdc.i;
114 freqdata[ncfft].r = tdc.r - tdc.i;
115#ifdef USE_SIMD
116 freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
117#else
118 freqdata[ncfft].i = freqdata[0].i = 0;
119#endif
120
121 for ( k=1;k <= ncfft/2 ; ++k ) {
122 fpk = st->tmpbuf[k];
123 fpnk.r = st->tmpbuf[ncfft-k].r;
124 fpnk.i = - st->tmpbuf[ncfft-k].i;
125 C_FIXDIV(fpk,2);
126 C_FIXDIV(fpnk,2);
127
128 C_ADD( f1k, fpk , fpnk );
129 C_SUB( f2k, fpk , fpnk );
130 C_MUL( tw , f2k , st->super_twiddles[k-1]);
131
132 freqdata[k].r = HALF_OF(f1k.r + tw.r);
133 freqdata[k].i = HALF_OF(f1k.i + tw.i);
134 freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
135 freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
136 }
137}
138
140{
141 /* input buffer timedata is stored row-wise */
142 int k, ncfft;
143
144 if (st->substate->inverse == 0) {
145 //fprintf (stderr, "kiss fft usage error: improper alloc\n");
146 FL_WARN("kiss fft usage error: improper alloc");
147 fl::exit(1);
148 }
149
150 ncfft = st->substate->nfft;
151
152 st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
153 st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
154 C_FIXDIV(st->tmpbuf[0],2);
155
156 for (k = 1; k <= ncfft / 2; ++k) {
157 kiss_fft_cpx fk, fnkc, fek, fok, tmp;
158 fk = freqdata[k];
159 fnkc.r = freqdata[ncfft - k].r;
160 fnkc.i = -freqdata[ncfft - k].i;
161 C_FIXDIV( fk , 2 );
162 C_FIXDIV( fnkc , 2 );
163
164 C_ADD (fek, fk, fnkc);
165 C_SUB (tmp, fk, fnkc);
166 C_MUL (fok, tmp, st->super_twiddles[k-1]);
167 C_ADD (st->tmpbuf[k], fek, fok);
168 C_SUB (st->tmpbuf[ncfft - k], fek, fok);
169#ifdef USE_SIMD
170 st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
171#else
172 st->tmpbuf[ncfft - k].i *= -1;
173#endif
174 }
175 kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
176}
#define C_FIXDIV(c, div)
#define HALF_OF(x)
#define C_ADD(res, a, b)
#define CHECK_OVERFLOW_OP(a, op, b)
#define C_SUB(res, a, b)
#define C_MUL(m, a, b)
#define kf_cexp(x, phase)
void kiss_fft(kiss_fft_cfg cfg, const kiss_fft_cpx *fin, kiss_fft_cpx *fout) FL_NOEXCEPT
#define NULL
kiss_fft_cfg kiss_fft_alloc(int nfft, int inverse_fft, void *mem, size_t *lenmem) FL_NOEXCEPT
#define kiss_fft_scalar
Definition kiss_fft.h:69
struct kiss_fft_state * kiss_fft_cfg
Definition kiss_fft.h:89
#define KISS_FFT_MALLOC(nbytes)
Definition kiss_fft.h:60
kiss_fft_scalar r
Definition kiss_fft.h:85
kiss_fft_scalar i
Definition kiss_fft.h:86
void kiss_fftri(kiss_fftr_cfg st, const kiss_fft_cpx *freqdata, kiss_fft_scalar *timedata) FL_NOEXCEPT
void kiss_fftr(kiss_fftr_cfg st, const kiss_fft_scalar *timedata, kiss_fft_cpx *freqdata) FL_NOEXCEPT
kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem, size_t *lenmem) FL_NOEXCEPT
kiss_fft_cfg substate
kiss_fft_cpx * tmpbuf
kiss_fft_cpx * super_twiddles
struct kiss_fftr_state * kiss_fftr_cfg
Definition kiss_fftr.h:26
#define FL_WARN(X)
Definition log.h:276
Centralized logging categories for FastLED hardware interfaces and subsystems.
void exit(int code)
No-op exit function for embedded systems In embedded environments, calling exit is typically not mean...
Definition exit.h:8
#define FL_NOEXCEPT