├── CMakeLists.txt
├── LICENSE
├── README.md
├── dr_mp3.h
├── dr_wav.h
├── main.c
├── stb_fft.h
└── timing.h
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8)
2 | project(FFTResampler LANGUAGES C)
3 | set(CMAKE_POSITION_INDEPENDENT_CODE ON)
4 | SET(CMAKE_BUILD_TYPE "Release")
5 |
6 | include_directories(include)
7 | add_executable(${PROJECT_NAME} main.c)
8 |
9 | target_link_libraries(${PROJECT_NAME} -lm)
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Zhihan Gao
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FFTResampler
2 | A Simple and Efficient Implementation Of Fast Fourier Transform For Audio Resampler
3 |
4 |
5 | # Donating
6 |
7 | If you found this project useful, consider buying me a coffee
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 |
2 | #ifdef __cplusplus
3 | extern "C" {
4 | #endif
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #define DR_WAV_IMPLEMENTATION
11 |
12 | #include "dr_wav.h"
13 |
14 | #define DR_MP3_IMPLEMENTATION
15 |
16 |
17 | #include "dr_mp3.h"
18 |
19 | #include "timing.h"
20 |
21 |
22 | #define STB_FFT_IMPLEMENTAION
23 |
24 | #include "stb_fft.h"
25 |
26 | #ifndef max
27 | #define max(a, b) ((a) > (b) ? (a) : (b))
28 | #endif
29 |
30 |
31 | void wavWrite_f32(char *filename, float *buffer, int sampleRate, uint32_t totalSampleCount, uint32_t channels)
32 | {
33 | drwav_data_format format;
34 | format.container = drwav_container_riff;
35 | format.format = DR_WAVE_FORMAT_IEEE_FLOAT;
36 | format.channels = channels;
37 | format.sampleRate = (drwav_uint32) sampleRate;
38 | format.bitsPerSample = 32;
39 | drwav *pWav = drwav_open_file_write(filename, &format);
40 | if (pWav) {
41 | drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer);
42 | drwav_uninit(pWav);
43 | if (samplesWritten != totalSampleCount) {
44 | fprintf(stderr, "write file [%s] error.\n", filename);
45 | exit(1);
46 | }
47 | }
48 | }
49 |
50 | float *wavRead_f32(const char *filename, uint32_t *sampleRate, uint64_t *sampleCount, uint32_t *channels)
51 | {
52 | drwav_uint64 totalSampleCount = 0;
53 | float *input = drwav_open_file_and_read_pcm_frames_f32(filename, channels, sampleRate, &totalSampleCount);
54 | if (input == NULL) {
55 | drmp3_config pConfig;
56 | input = drmp3_open_file_and_read_f32(filename, &pConfig, &totalSampleCount);
57 | if (input != NULL) {
58 | *channels = pConfig.outputChannels;
59 | *sampleRate = pConfig.outputSampleRate;
60 | }
61 | }
62 | if (input == NULL) {
63 | fprintf(stderr, "read file [%s] error.\n", filename);
64 | exit(1);
65 | }
66 | *sampleCount = totalSampleCount * (*channels);
67 | return input;
68 | }
69 |
70 | void splitpath(const char *path, char *drv, char *dir, char *name, char *ext)
71 | {
72 | const char *end;
73 | const char *p;
74 | const char *s;
75 | if (path[0] && path[1] == ':') {
76 | if (drv) {
77 | *drv++ = *path++;
78 | *drv++ = *path++;
79 | *drv = '\0';
80 | }
81 | }
82 | else if (drv)
83 | *drv = '\0';
84 | for (end = path; *end && *end != ':';)
85 | end++;
86 | for (p = end; p > path && *--p != '\\' && *p != '/';)
87 | if (*p == '.') {
88 | end = p;
89 | break;
90 | }
91 | if (ext)
92 | for (s = end; (*ext = *s++);)
93 | ext++;
94 | for (p = end; p > path;)
95 | if (*--p == '\\' || *p == '/') {
96 | p++;
97 | break;
98 | }
99 | if (name) {
100 | for (s = p; s < end;)
101 | *name++ = *s++;
102 | *name = '\0';
103 | }
104 | if (dir) {
105 | for (s = path; s < p;)
106 | *dir++ = *s++;
107 | *dir = '\0';
108 | }
109 | }
110 |
111 | typedef struct
112 | {
113 | int inFrameSize;
114 | int inWindowSize;
115 | int inSampleRate;
116 | float *inWindowing;
117 | stb_fft_real_plan *inPlan;
118 | int outFrameSize;
119 | int outWindowSize;
120 | int outSampleRate;
121 | float *outWindowing;
122 | stb_fft_real_plan *outPlan;
123 | float *inFifo;
124 | float *synthesisMem;
125 | cmplx *samples;
126 | int pos;
127 | } FFT_Resampler_Handle;
128 |
129 | void FFT_Resampler_Free(FFT_Resampler_Handle *handle)
130 | {
131 | if (handle) {
132 | if (handle->inFifo) {
133 | free(handle->inFifo);
134 | handle->inFifo = NULL;
135 | }
136 |
137 | if (handle->inPlan) {
138 | free(handle->inPlan);
139 | handle->inPlan = NULL;
140 | }
141 |
142 | if (handle->outPlan) {
143 | free(handle->outPlan);
144 | handle->outPlan = NULL;
145 | }
146 |
147 | if (handle->samples) {
148 | free(handle->samples);
149 | handle->samples = NULL;
150 | }
151 |
152 | if (handle->synthesisMem) {
153 | free(handle->synthesisMem);
154 | handle->synthesisMem = NULL;
155 | }
156 |
157 | if (handle->inWindowing) {
158 | free(handle->inWindowing);
159 | handle->inWindowing = NULL;
160 | }
161 |
162 | if (handle->outWindowing) {
163 | free(handle->outWindowing);
164 | handle->outWindowing = NULL;
165 | }
166 | }
167 | }
168 |
169 | void FFT_Resampler_reset(FFT_Resampler_Handle *handle)
170 | {
171 | if (handle)
172 | handle->pos = 0;
173 | }
174 |
175 | int FFT_Resampler_Init(FFT_Resampler_Handle *handle, size_t inSampleRate, size_t outSampleRate, size_t nFFT)
176 | {
177 | if (handle) {
178 | handle->pos = 0;
179 | if (outSampleRate < inSampleRate) {
180 | nFFT = nFFT * inSampleRate * 128 / outSampleRate;
181 | }
182 | else {
183 | nFFT = nFFT * outSampleRate * 128 / inSampleRate;
184 | }
185 | nFFT += (nFFT % 2);
186 | handle->inFrameSize = nFFT;
187 | handle->inWindowSize = nFFT * 2;
188 | handle->inSampleRate = inSampleRate;
189 | handle->inWindowing = (float *) calloc(handle->inFrameSize, sizeof(float));
190 | handle->inPlan = stb_fft_real_plan_dft_1d(handle->inWindowSize);
191 | handle->outSampleRate = outSampleRate;
192 | handle->outFrameSize = handle->inFrameSize * outSampleRate / inSampleRate;
193 | handle->outWindowSize = handle->outFrameSize * 2;
194 | handle->outWindowing = (float *) calloc(handle->outFrameSize, sizeof(float));
195 | handle->outPlan = stb_fft_real_plan_dft_1d(handle->outWindowSize);
196 | handle->inFifo = (float *) calloc(max(handle->inWindowSize, handle->outWindowSize), sizeof(float));
197 | handle->samples = (cmplx *) calloc(max(handle->inWindowSize, handle->outWindowSize), sizeof(cmplx));
198 | handle->synthesisMem = (float *) calloc(handle->outFrameSize, sizeof(float));
199 | if ((handle->inFifo == NULL) || (handle->inPlan == NULL) || (handle->outPlan == NULL)
200 | || (handle->samples == NULL)
201 | || (handle->synthesisMem == NULL) || (handle->inWindowing == NULL) || (handle->outWindowing == NULL)
202 | ) {
203 | FFT_Resampler_Free(handle);
204 | return 0;
205 | }
206 | float norm = 1.0f / handle->inWindowSize;
207 | for (size_t i = 0; i < handle->inFrameSize; i++) {
208 | double t = sin(.5 * M_PI * (i + .5) / handle->inFrameSize);
209 | handle->inWindowing[i] = (float) sin(.5 * M_PI * t * t) * norm;
210 | }
211 | for (size_t i = 0; i < handle->outFrameSize; i++) {
212 | double t = sin(.5 * M_PI * (i + .5) / handle->outFrameSize);
213 | handle->outWindowing[i] = (float) sin(.5 * M_PI * t * t);
214 | }
215 | return 1;
216 | }
217 | return 0;
218 | }
219 |
220 | int FFT_Resampler_Proc(FFT_Resampler_Handle *handle, const float *input, float *output)
221 | {
222 | if ((input == NULL) || (handle == NULL) || (output == NULL)) {
223 | return -1;
224 | }
225 | float *inFifo = handle->inFifo;
226 | float *synthesis_mem = handle->synthesisMem;
227 | for (size_t i = 0; i < handle->inFrameSize; i++) {
228 | inFifo[i] *= handle->inWindowing[i];
229 | inFifo[handle->inWindowSize - 1 - i] = input[handle->inFrameSize - 1 - i] * handle->inWindowing[i];
230 | }
231 | stb_fft_r2c_exec(handle->inPlan, inFifo, handle->samples);
232 | if (handle->outWindowSize < handle->inWindowSize) {
233 | int half_output = (handle->outWindowSize / 2);
234 | int diff_size = handle->inWindowSize - handle->outWindowSize;
235 | memset(handle->samples + half_output, 0, diff_size * sizeof(cmplx));
236 | }
237 | else if (handle->outWindowSize > handle->inWindowSize) {
238 | int half_input = handle->inWindowSize / 2;
239 | int diff_size = handle->outWindowSize - handle->inWindowSize;
240 | memmove(handle->samples + half_input + diff_size, handle->samples + half_input,
241 | half_input * sizeof(cmplx));
242 | memset(handle->samples + half_input, 0, diff_size * sizeof(cmplx));
243 | }
244 | stb_fft_c2r_exec(handle->outPlan, handle->samples, inFifo);
245 | for (size_t i = 0; i < handle->outFrameSize; i++) {
246 | output[i] = inFifo[i] * handle->outWindowing[i] + synthesis_mem[i];
247 | inFifo[handle->outWindowSize - 1 - i] *= handle->outWindowing[i];
248 | }
249 | memcpy(synthesis_mem, inFifo + handle->outFrameSize, handle->outFrameSize * sizeof(float));
250 | memcpy(inFifo, input, handle->inFrameSize * sizeof(float));
251 | if (handle->pos == 0) {
252 | handle->pos++;
253 | return 0;
254 | }
255 | handle->pos++;
256 | return 1;
257 | }
258 |
259 | void printUsage()
260 | {
261 | printf("usage:\n");
262 | printf("./FFTResampler input.wav 48000\n");
263 | printf("./FFTResampler input.mp3 16000\n");
264 | printf("or\n");
265 | printf("./FFTResampler input.wav output.wav 8000\n");
266 | printf("./FFTResampler input.mp3 output.wav 44100\n");
267 | printf("press any key to exit.\n");
268 | getchar();
269 | }
270 |
271 | void FFT_Resampler(char *in_file, char *out_file, uint32_t targetSampleRate)
272 | {
273 | if (targetSampleRate == 0) {
274 | printUsage();
275 | return;
276 | }
277 | uint32_t sampleRate = 0;
278 | uint64_t sampleCount = 0;
279 | uint32_t channels = 0;
280 | float *input = wavRead_f32(in_file, &sampleRate, &sampleCount, &channels);
281 | if (input) {
282 | size_t nFFT = 2;
283 | FFT_Resampler_Handle *handle = (FFT_Resampler_Handle *) malloc(sizeof(FFT_Resampler_Handle));
284 | if (handle) {
285 | double startTime = now();
286 | if (FFT_Resampler_Init(handle, sampleRate, targetSampleRate, nFFT) == 1) {
287 | uint64_t frames = (sampleCount / handle->inFrameSize);
288 | int remainingSample = (sampleCount % handle->inFrameSize);
289 | int outRemainingSize = remainingSample * targetSampleRate / sampleRate;
290 | uint64_t targetSampleCount = frames * handle->outFrameSize + outRemainingSize;
291 | float *output = (float *) calloc(targetSampleCount, sizeof(float));
292 | if (output) {
293 | FFT_Resampler_reset(handle);
294 | float *inBuffer = input;
295 | float *outBuffer = output;
296 | for (int n = 0; n < frames; ++n) {
297 | if (FFT_Resampler_Proc(handle, inBuffer, outBuffer) == 1)
298 | outBuffer += handle->outFrameSize;
299 | inBuffer += handle->inFrameSize;
300 | }
301 | if (remainingSample == 0) {
302 | inBuffer -= handle->inFrameSize;
303 | FFT_Resampler_Proc(handle, inBuffer, outBuffer);
304 | memcpy(outBuffer, handle->synthesisMem, sizeof(float) * handle->outFrameSize);
305 | }
306 | else {
307 | float *buffer = (float *) calloc(handle->inFrameSize, sizeof(float));
308 | if (buffer) {
309 | memcpy(buffer, inBuffer, sizeof(float) * remainingSample);
310 | if (FFT_Resampler_Proc(handle, buffer, outBuffer) == 1)
311 | outBuffer += handle->outFrameSize;
312 | free(buffer);
313 |
314 | memcpy(outBuffer, handle->synthesisMem, sizeof(float) * outRemainingSize);
315 | }
316 | }
317 | }
318 | double time_interval = calcElapsed(startTime, now());
319 | printf("time interval: %f ms\n ", (time_interval * 1000));
320 | wavWrite_f32(out_file, output, targetSampleRate, (uint32_t) targetSampleCount, channels);
321 | free(output);
322 | }
323 | FFT_Resampler_Free(handle);
324 | free(handle);
325 | }
326 | free(input);
327 | }
328 | }
329 |
330 | int main(int argc, char *argv[])
331 | {
332 | printf("Audio Processing\n");
333 | printf("blog:http://cpuimage.cnblogs.com/\n");
334 | printf("Audio FFT Resampler\n");
335 | if (argc < 3) {
336 | printUsage();
337 | return -1;
338 | }
339 | char *in_file = argv[1];
340 | if (argc > 3) {
341 | char *out_file = argv[2];
342 | uint32_t targetSampleRate = (uint32_t) atoi(argv[3]);
343 | FFT_Resampler(in_file, out_file, targetSampleRate);
344 | }
345 | else {
346 | int32_t targetSampleRate = (uint32_t) atoi(argv[2]);
347 | char drive[3];
348 | char dir[256];
349 | char fname[256];
350 | char ext[256];
351 | char out_file[1024];
352 | splitpath(in_file, drive, dir, fname, ext);
353 | sprintf(out_file, "%s%s%s_out.wav", drive, dir, fname);
354 | FFT_Resampler(in_file, out_file, targetSampleRate);
355 | }
356 |
357 | return 0;
358 | }
359 |
360 | #ifdef __cplusplus
361 | }
362 | #endif
363 |
--------------------------------------------------------------------------------
/stb_fft.h:
--------------------------------------------------------------------------------
1 | // fast fourier transform library (suitable for power of 2 and non-power of 2) Public domain. See "unlicense" statement at the end of this file.
2 | // stb_fft - v0.11 - 2018-12-28
3 | //
4 | // ZhiHan Gao - 200759103@qq.com
5 | // USAGE
6 | //
7 | // This is a single-file library. To use it, do something like the following in one .c file.
8 | // #define STB_FFT_IMPLEMENTAION
9 | // #include "stb_fft.h"
10 | //
11 | //
12 | // You can then #include this file in other parts of the program as you would with any other header file.
13 | //
14 | // The default real type is float.
15 | // To define a macro named USE_DOUBLE_TYPE to change it to double.
16 | // You can read the following function: STB_FFT,STB_IFFT,STB_FFT_R2C,STB_IFFT_C2R for easily usage
17 | //
18 | //
19 |
20 | #ifndef _stb_fft_h_
21 | #define _stb_fft_h_
22 | #ifdef __cplusplus
23 | extern "C" {
24 | #endif
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #ifdef USE_DOUBLE_TYPE
33 | #define stb_real_t double
34 | #else
35 | #define stb_real_t float
36 | #endif
37 |
38 | typedef struct {
39 | stb_real_t real;
40 | stb_real_t imag;
41 | } cmplx;
42 |
43 | typedef struct {
44 | int count;
45 | int* radix;
46 | int* remainder;
47 | int* offsets;
48 | } stb_fft_stages;
49 |
50 | typedef struct {
51 | int N;
52 | cmplx* twiddles;
53 | cmplx* twiddles_ordered;
54 | stb_fft_stages stages;
55 | } stb_fft_plan;
56 |
57 | typedef struct {
58 | stb_fft_plan* half_plan;
59 | cmplx* buffer;
60 | cmplx* twiddles;
61 | } stb_fft_real_plan;
62 |
63 | stb_fft_plan* stb_fft_plan_dft_1d(int N);
64 |
65 | stb_fft_real_plan* stb_fft_real_plan_dft_1d(int N);
66 |
67 | void stb_fft_r2c_exec(stb_fft_real_plan* plan, const stb_real_t* in, cmplx* out);
68 |
69 | void stb_fft_c2r_exec(stb_fft_real_plan* plan, const cmplx* in, stb_real_t* out);
70 |
71 | void stb_fft_exec(const stb_fft_plan* plan, cmplx* in, cmplx* out);
72 |
73 | void stb_ifft_exec(const stb_fft_plan* plan, cmplx* in, cmplx* out);
74 |
75 | // for easily usage
76 | void STB_FFT(cmplx* input, cmplx* output, int n);
77 |
78 | void STB_IFFT(cmplx* input, cmplx* output, int n);
79 |
80 | void STB_FFT_R2C(stb_real_t* input, cmplx* output, int n);
81 |
82 | void STB_IFFT_C2R(cmplx* input, stb_real_t* output, int n);
83 |
84 | #ifdef __cplusplus
85 | }
86 | #endif
87 | #endif
88 |
89 | #ifdef STB_FFT_IMPLEMENTAION
90 |
91 | #ifndef STB_KP5
92 | #define STB_KP5 ((stb_real_t)0.5)
93 | #endif
94 |
95 | #ifndef STB_KP25
96 | #define STB_KP25 ((stb_real_t)0.25)
97 | #endif
98 |
99 | #ifndef STB_KP951056516
100 | #define STB_KP951056516 ((stb_real_t)0.951056516295153572116439333379382143405698634)
101 | #endif
102 |
103 | #ifndef STB_KP587785252
104 | #define STB_KP587785252 ((stb_real_t)0.587785252292473129168705954639072768597652438)
105 | #endif
106 |
107 | #ifndef STB_KP559016994
108 | #define STB_KP559016994 ((stb_real_t)0.559016994374947424102293417182819058860154590)
109 | #endif
110 |
111 | #ifndef STB_KP866025403
112 | #define STB_KP866025403 ((stb_real_t)0.866025403784438646763723170752936183471402627)
113 | #endif
114 |
115 | #ifndef STB_KP900968867
116 | #define STB_KP900968867 ((stb_real_t)0.900968867902419126236102319507445051165919162)
117 | #endif
118 |
119 | #ifndef STB_KP222520933
120 | #define STB_KP222520933 ((stb_real_t)0.222520933956314404288902564496794759466355569)
121 | #endif
122 |
123 | #ifndef STB_KP623489801
124 | #define STB_KP623489801 ((stb_real_t)0.623489801858733530525004884004239810632274731)
125 | #endif
126 |
127 | #ifndef STB_KP781831482
128 | #define STB_KP781831482 ((stb_real_t)0.781831482468029808708444526674057750232334519)
129 | #endif
130 |
131 | #ifndef STB_KP974927912
132 | #define STB_KP974927912 ((stb_real_t)0.974927912181823607018131682993931217232785801)
133 | #endif
134 |
135 | #ifndef STB_KP433883739
136 | #define STB_KP433883739 ((stb_real_t)0.433883739117558120475768332848358754609990728)
137 | #endif
138 |
139 | #ifndef STB_KP707106781
140 | #define STB_KP707106781 ((stb_real_t)0.707106781186547524400844362104849039284835938)
141 | #endif
142 |
143 | #ifndef STB_TWOPI
144 | #define STB_TWOPI ((stb_real_t)6.283185307179586476925286766559005768394338798750211641949889)
145 | #endif
146 |
147 | #ifndef STB_PI
148 | #define STB_PI ((stb_real_t)3.141592653589793238462643383279502884197169399375105820974944)
149 | #endif
150 |
151 | void stbSinCos(double x, stb_real_t* pSin, stb_real_t* pCos)
152 | {
153 | *pSin = (stb_real_t)sin(x);
154 | *pCos = (stb_real_t)cos(x);
155 | }
156 |
157 | void stb_make_twiddles(int n, int count, cmplx* twiddles)
158 | {
159 | double w_pi = STB_TWOPI / n;
160 | double t = 0;
161 | for (int i = 0; i < count; ++i) {
162 | stbSinCos(t, &twiddles[i].imag, &twiddles[i].real);
163 | t += w_pi;
164 | }
165 | };
166 |
167 | int stb_make_twiddles_sequential(int n, cmplx* twiddles, stb_fft_stages* stages)
168 | {
169 | int size = 0;
170 | {
171 | int offset = 0;
172 | for (int s = 0; s < stages->count; s++) {
173 | int r = stages->radix[s];
174 | int count = stages->remainder[s];
175 | int amount = (r <= 8) ? (r - 1) * (count - 1) : 0;
176 | stages->offsets[s] = amount;
177 | offset += amount;
178 | }
179 | size = offset;
180 | for (int s = 0; s < stages->count; s++) {
181 | int count = stages->offsets[s];
182 | offset -= count;
183 | stages->offsets[s] = offset;
184 | }
185 | }
186 | if (twiddles) {
187 | int w = 1;
188 | for (int s = 0; s < stages->count; s++) {
189 | double w_pi = STB_TWOPI * w / n;
190 | const int r = stages->radix[s];
191 | const int count = stages->remainder[s];
192 | int offset = stages->offsets[s];
193 | if (r <= 8) {
194 | for (int i = 1; i < count; i++) {
195 | for (int j = 1; j < r; j++) {
196 | stbSinCos(w_pi * i * j, &twiddles[offset].imag, &twiddles[offset].real);
197 | offset++;
198 | }
199 | }
200 | }
201 | w *= r;
202 | }
203 | }
204 | return size;
205 | };
206 |
207 | typedef struct {
208 | int calc_twiddles;
209 | int stage_count;
210 | int twiddles_size;
211 | } stb_stage_info;
212 |
213 | stb_stage_info stb_calculate_stages(int n, stb_fft_plan* plan)
214 | {
215 | int calc_twiddles = 0;
216 | int stage = 0;
217 | int twiddles_size = 0;
218 | while (n > 1) {
219 | int i = 8;
220 | for (; i > 1; i--) {
221 | if (!(n % i)) {
222 | twiddles_size += ((i - 1) * (n - 1));
223 | break;
224 | }
225 | }
226 | if (i == 1) {
227 | calc_twiddles = 1;
228 | i = 7;
229 | for (; i <= n; i++) {
230 | if (!(n % i)) {
231 | break;
232 | }
233 | }
234 | }
235 | n /= i;
236 | if (plan) {
237 | plan->stages.radix[stage] = i;
238 | plan->stages.remainder[stage] = n;
239 | }
240 | stage++;
241 | }
242 | stb_stage_info result = {
243 | calc_twiddles, stage, twiddles_size
244 | };
245 | return result;
246 | }
247 |
248 | int stb_make_fft_plan(int N, stb_fft_plan* plan)
249 | {
250 | if (N == 0)
251 | return 0;
252 | stb_stage_info info = stb_calculate_stages(N, NULL);
253 | const int size_plan = sizeof(stb_fft_plan);
254 | const int size_radix = info.stage_count * sizeof(int);
255 | const int size_remainder = info.stage_count * sizeof(int);
256 | const int size_offsets = info.stage_count * sizeof(int);
257 | const int twiddles_ordered_size = info.twiddles_size * sizeof(cmplx);
258 | const int twiddles_size = N * sizeof(cmplx) * info.calc_twiddles;
259 | const int total_size = size_plan
260 | + twiddles_size
261 | + size_radix + size_remainder + size_offsets + twiddles_ordered_size;
262 | if (plan) {
263 | uint8_t* data = (uint8_t*)(plan);
264 | uint8_t* data_twiddles = data + size_plan;
265 | uint8_t* data_radix = data_twiddles + twiddles_size;
266 | uint8_t* data_remainder = data_radix + size_radix;
267 | uint8_t* data_offsets = data_remainder + size_offsets;
268 | uint8_t* data_twiddles_ordered = data_offsets + size_remainder;
269 | plan->twiddles = (info.calc_twiddles) ? (cmplx*)(data_twiddles) : NULL;
270 | plan->stages.radix = (int*)(data_radix);
271 | plan->stages.remainder = (int*)(data_remainder);
272 | plan->stages.offsets = (int*)(data_offsets);
273 | plan->stages.count = info.stage_count;
274 | plan->twiddles_ordered = (cmplx*)(data_twiddles_ordered);
275 | plan->N = N;
276 | if (plan->twiddles) {
277 | stb_make_twiddles(N, N, plan->twiddles);
278 | }
279 | stb_calculate_stages(N, plan);
280 | stb_make_twiddles_sequential(N, plan->twiddles_ordered, &plan->stages);
281 | }
282 | return total_size;
283 | }
284 |
285 | stb_fft_plan* stb_fft_plan_dft_1d(int N)
286 | {
287 | if (N == 0)
288 | return 0;
289 | stb_stage_info info = stb_calculate_stages(N, NULL);
290 | const int size_plan = sizeof(stb_fft_plan);
291 | const int size_radix = info.stage_count * sizeof(int);
292 | const int size_remainder = info.stage_count * sizeof(int);
293 | const int size_offsets = info.stage_count * sizeof(int);
294 | const int twiddles_ordered_size = info.twiddles_size * sizeof(cmplx);
295 | const int twiddles_size = N * sizeof(cmplx) * info.calc_twiddles;
296 | const int total_size = size_plan
297 | + twiddles_size
298 | + size_radix + size_remainder + size_offsets + twiddles_ordered_size;
299 | stb_fft_plan* plan = (stb_fft_plan*)calloc(total_size, 1);
300 | if (plan) {
301 | uint8_t* data = (uint8_t*)(plan);
302 | uint8_t* data_twiddles = data + size_plan;
303 | uint8_t* data_radix = data_twiddles + twiddles_size;
304 | uint8_t* data_remainder = data_radix + size_radix;
305 | uint8_t* data_offsets = data_remainder + size_offsets;
306 | uint8_t* data_twiddles_ordered = data_offsets + size_remainder;
307 | plan->twiddles = (info.calc_twiddles) ? (cmplx*)(data_twiddles) : NULL;
308 | plan->stages.radix = (int*)(data_radix);
309 | plan->stages.remainder = (int*)(data_remainder);
310 | plan->stages.offsets = (int*)(data_offsets);
311 | plan->stages.count = info.stage_count;
312 | plan->twiddles_ordered = (cmplx*)(data_twiddles_ordered);
313 | plan->N = N;
314 | if (plan->twiddles) {
315 | stb_make_twiddles(N, N, plan->twiddles);
316 | }
317 | stb_calculate_stages(N, plan);
318 | stb_make_twiddles_sequential(N, plan->twiddles_ordered, &plan->stages);
319 | }
320 | return plan;
321 | }
322 |
323 | stb_fft_real_plan* stb_fft_real_plan_dft_1d(int N)
324 | {
325 | if (N == 0)
326 | return 0;
327 | if (N & 1) {
328 | fprintf(stderr, "Real FFT must be even.\n");
329 | return 0;
330 | }
331 | N >>= 1;
332 | int c_plan_size = stb_make_fft_plan(N, NULL);
333 | int mem_needed = sizeof(stb_fft_real_plan) + c_plan_size + sizeof(cmplx) * (N * 3 / 2);
334 | stb_fft_real_plan* plan = (stb_fft_real_plan*)calloc(mem_needed, 1);
335 | if (plan) {
336 | plan->half_plan = (stb_fft_plan*)(plan + 1);
337 | plan->buffer = (cmplx*)(((char*)plan->half_plan) + c_plan_size);
338 | plan->twiddles = plan->buffer + N;
339 | stb_make_fft_plan(N, plan->half_plan);
340 | for (int i = 0; i < N / 2; ++i) {
341 | stbSinCos(-STB_PI * ((double)(i + 1) / N + 0.5), &plan->twiddles[i].imag, &plan->twiddles[i].real);
342 | }
343 | }
344 | return plan;
345 | }
346 |
347 | void stb_general_dit(cmplx* twiddles, cmplx* out, int count,
348 | int cur_sign, int radix, int N, int reverse)
349 | {
350 | cmplx* scratch = (cmplx*)calloc(radix, sizeof(cmplx));
351 | if (scratch == 0)
352 | return;
353 | if (reverse) {
354 | for (int butterfly = 0; butterfly < count; ++butterfly) {
355 | int idx = butterfly;
356 | for (int r = 0; r < radix; ++r) {
357 | scratch[r] = out[idx];
358 | idx += count;
359 | }
360 | idx = butterfly;
361 | for (int r = 0; r < radix; ++r) {
362 | int tw_idx = 0;
363 | out[idx] = *scratch;
364 | for (int cr = 1; cr < radix; ++cr) {
365 | tw_idx += cur_sign * idx;
366 | if (tw_idx >= N)
367 | tw_idx -= N;
368 | out[idx].real += twiddles[tw_idx].real * scratch[cr].real
369 | - twiddles[tw_idx].imag * scratch[cr].imag;
370 | out[idx].imag += twiddles[tw_idx].real * scratch[cr].imag
371 | + scratch[cr].real * twiddles[tw_idx].imag;
372 | }
373 | idx += count;
374 | }
375 | }
376 | } else {
377 | for (int butterfly = 0; butterfly < count; ++butterfly) {
378 | int idx = butterfly;
379 | for (int r = 0; r < radix; ++r) {
380 | scratch[r] = out[idx];
381 | idx += count;
382 | }
383 | idx = butterfly;
384 | for (int r = 0; r < radix; ++r) {
385 | int tw_idx = 0;
386 | out[idx] = *scratch;
387 | for (int cr = 1; cr < radix; ++cr) {
388 | tw_idx += cur_sign * idx;
389 | if (tw_idx >= N)
390 | tw_idx -= N;
391 | out[idx].real += twiddles[tw_idx].real * scratch[cr].real
392 | + twiddles[tw_idx].imag * scratch[cr].imag;
393 | out[idx].imag += twiddles[tw_idx].real * scratch[cr].imag
394 | - scratch[cr].real * twiddles[tw_idx].imag;
395 | }
396 | idx += count;
397 | }
398 | }
399 | }
400 | free(scratch);
401 | }
402 |
403 | void stb_radix_2_dit(const cmplx* tw, cmplx* out, int count)
404 | {
405 | int m;
406 | cmplx* output;
407 | stb_real_t T1 = out[0].real;
408 | stb_real_t T2 = out[count].real;
409 | out[count].real = out[0].real - T2;
410 | out[0].real = T1 + T2;
411 | stb_real_t T3 = out[0].imag;
412 | stb_real_t T4 = out[count].imag;
413 | out[count].imag = T3 - T4;
414 | out[0].imag = T3 + T4;
415 | output = out + 1;
416 | m = 1;
417 | while (m < count) {
418 | stb_real_t T1_0 = output[0].real;
419 | stb_real_t T8 = output[0].imag;
420 | stb_real_t T3_0 = output[count].real;
421 | stb_real_t T5 = output[count].imag;
422 | stb_real_t T4_0 = tw[0].imag;
423 | stb_real_t T6 = T4_0 * T5 + tw[0].real * T3_0;
424 | stb_real_t T7 = tw[0].real * T5 - T4_0 * T3_0;
425 | output[count].real = output[0].real - T6;
426 | output[count].imag = T8 - T7;
427 | output[0].real = T1_0 + T6;
428 | output[0].imag = T7 + T8;
429 | ++m;
430 | ++output;
431 | ++tw;
432 | }
433 | }
434 |
435 | void stb_radix_3_dit(const cmplx* tw, cmplx* out, int count)
436 | {
437 | int m;
438 | cmplx* output;
439 | stb_real_t T1 = out[0].real;
440 | stb_real_t T10 = out[0].imag;
441 | stb_real_t T2 = out[count].real;
442 | stb_real_t T3 = out[2 * count].real;
443 | stb_real_t T9 = (T3 - T2) * STB_KP866025403;
444 | stb_real_t T6 = out[count].imag;
445 | stb_real_t T7 = out[2 * count].imag;
446 | stb_real_t T8 = (T6 - T7) * STB_KP866025403;
447 | out[0].real = out[0].real + T2 + T3;
448 | out[0].imag = T10 + T6 + T7;
449 | stb_real_t T5 = T1 - STB_KP5 * (T2 + T3);
450 | out[2 * count].real = T5 - T8;
451 | out[count].real = T5 + T8;
452 | stb_real_t T12 = T10 - STB_KP5 * (T6 + T7);
453 | out[count].imag = T9 + T12;
454 | out[2 * count].imag = T12 - T9;
455 | output = out + 1;
456 | m = 1;
457 | while (m < count) {
458 | stb_real_t T1_0 = output[0].real;
459 | stb_real_t T18 = output[0].imag;
460 | stb_real_t T3_0 = output[count].real;
461 | stb_real_t T5_0 = output[count].imag;
462 | stb_real_t T4_0 = tw[0].imag;
463 | stb_real_t T6_0 = T4_0 * T5_0 + tw[0].real * T3_0;
464 | stb_real_t T14 = tw[0].real * T5_0 - T4_0 * T3_0;
465 | stb_real_t T8_0 = output[2 * count].real;
466 | stb_real_t T10_0 = output[2 * count].imag;
467 | stb_real_t T7_0 = tw[1].real;
468 | stb_real_t T9_0 = tw[1].imag;
469 | stb_real_t T11_0 = T9_0 * T10_0 + T7_0 * T8_0;
470 | stb_real_t T15 = T7_0 * T10_0 - T9_0 * T8_0;
471 | stb_real_t T12_0 = T6_0 + T11_0;
472 | stb_real_t T17 = T14 + T15;
473 | output[0].real = output[0].real + T12_0;
474 | output[0].imag = T17 + T18;
475 | stb_real_t T16 = (T14 - T15) * STB_KP866025403;
476 | output[2 * count].real = T1_0 - STB_KP5 * T12_0 - T16;
477 | output[count].real = T1_0 - STB_KP5 * T12_0 + T16;
478 | stb_real_t T20 = T18 - STB_KP5 * T17;
479 | output[count].imag = (T11_0 - T6_0) * STB_KP866025403 + T20;
480 | output[2 * count].imag = T20 - (T11_0 - T6_0) * STB_KP866025403;
481 | ++m;
482 | ++output;
483 | tw += 2;
484 | }
485 | }
486 |
487 | void stb_radix_4_dit(const cmplx* tw, cmplx* out, int count)
488 | {
489 | int m;
490 | cmplx* output;
491 | stb_real_t T2 = out[2 * count].real;
492 | stb_real_t T3 = out[0].real + T2;
493 | stb_real_t T11 = out[0].real - T2;
494 | stb_real_t T7 = out[0].imag;
495 | stb_real_t T8 = out[2 * count].imag;
496 | stb_real_t T4 = out[count].real;
497 | stb_real_t T5 = out[3 * count].real;
498 | stb_real_t T12 = out[count].imag;
499 | stb_real_t T13 = out[3 * count].imag;
500 | out[2 * count].real = T3 - (T4 + T5);
501 | out[2 * count].imag = T7 + T8 - (T12 + T13);
502 | out[0].real = T3 + T4 + T5;
503 | out[0].imag = T7 + T8 + T12 + T13;
504 | out[count].imag = T7 - T8 - (T4 - T5);
505 | out[count].real = T11 + T12 - T13;
506 | out[3 * count].imag = T4 - T5 + T7 - T8;
507 | out[3 * count].real = T11 - (T12 - T13);
508 | output = out + 1;
509 | m = 1;
510 | while (m < count) {
511 | stb_real_t T1_0 = output[0].real;
512 | stb_real_t T25 = output[0].imag;
513 | stb_real_t T3_0 = output[2 * count].real;
514 | stb_real_t T5_0 = output[2 * count].imag;
515 | stb_real_t T2_0 = tw[1].real;
516 | stb_real_t T4_0 = tw[1].imag;
517 | stb_real_t T6_0 = T4_0 * T5_0 + T2_0 * T3_0;
518 | stb_real_t T24 = T2_0 * T5_0 - T4_0 * T3_0;
519 | stb_real_t T9_0 = output[count].real;
520 | stb_real_t T11_0 = output[count].imag;
521 | stb_real_t T10_0 = tw[0].imag;
522 | stb_real_t T12_0 = T10_0 * T11_0 + tw[0].real * T9_0;
523 | stb_real_t T20 = tw[0].real * T11_0 - T10_0 * T9_0;
524 | stb_real_t T14_0 = output[3 * count].real;
525 | stb_real_t T16_0 = output[3 * count].imag;
526 | stb_real_t T13_0 = tw[2].real;
527 | stb_real_t T15_0 = tw[2].imag;
528 | stb_real_t T17 = T15_0 * T16_0 + T13_0 * T14_0;
529 | stb_real_t T21 = T13_0 * T16_0 - T15_0 * T14_0;
530 | stb_real_t T18 = T12_0 + T17;
531 | output[2 * count].real = output[0].real + T6_0 - T18;
532 | output[0].real = T1_0 + T6_0 + T18;
533 | output[0].imag = T20 + T21 + T24 + T25;
534 | output[2 * count].imag = T24 + T25 - (T20 + T21);
535 | output[3 * count].real = T1_0 - T6_0 - (T20 - T21);
536 | output[count].real = T1_0 - T6_0 + T20 - T21;
537 | output[count].imag = T25 - T24 - (T12_0 - T17);
538 | output[3 * count].imag = T12_0 - T17 + T25 - T24;
539 | ++m;
540 | ++output;
541 | tw += 3;
542 | }
543 | }
544 |
545 | void stb_radix_5_dit(const cmplx* tw, cmplx* out, int count)
546 | {
547 | int m;
548 | cmplx* output;
549 | stb_real_t T1 = out[0].real;
550 | stb_real_t T24 = out[0].imag;
551 | stb_real_t T2 = out[count].real;
552 | stb_real_t T3 = out[4 * count].real;
553 | stb_real_t T5 = out[2 * count].real;
554 | stb_real_t T6 = out[3 * count].real;
555 | stb_real_t T8 = T2 + T3 + T5 + T6;
556 | stb_real_t T9 = (T2 + T3 - (T5 + T6)) * STB_KP559016994;
557 | stb_real_t T12 = out[count].imag;
558 | stb_real_t T13 = out[4 * count].imag;
559 | stb_real_t T15 = out[2 * count].imag;
560 | stb_real_t T16 = out[3 * count].imag;
561 | stb_real_t T25 = T12 + T13 + T15 + T16;
562 | stb_real_t T23 = (T12 + T13 - (T15 + T16)) * STB_KP559016994;
563 | out[0].real = out[0].real + T8;
564 | out[0].imag = T24 + T25;
565 | stb_real_t T18 = STB_KP587785252 * (T15 - T16) + STB_KP951056516 * (T12 - T13);
566 | stb_real_t T20 = STB_KP951056516 * (T15 - T16) - STB_KP587785252 * (T12 - T13);
567 | stb_real_t T11 = T9 + T1 - STB_KP25 * T8;
568 | stb_real_t T19 = T1 - STB_KP25 * T8 - T9;
569 | out[4 * count].real = T11 - T18;
570 | out[3 * count].real = T19 + T20;
571 | out[count].real = T11 + T18;
572 | out[2 * count].real = T19 - T20;
573 | stb_real_t T30 = STB_KP587785252 * (T5 - T6) + STB_KP951056516 * (T2 - T3);
574 | stb_real_t T31 = STB_KP951056516 * (T5 - T6) - STB_KP587785252 * (T2 - T3);
575 | stb_real_t T27 = T23 + T24 - STB_KP25 * T25;
576 | stb_real_t T32 = T24 - STB_KP25 * T25 - T23;
577 | out[count].imag = T27 - T30;
578 | out[3 * count].imag = T32 - T31;
579 | out[4 * count].imag = T30 + T27;
580 | out[2 * count].imag = T31 + T32;
581 | output = out + 1;
582 | m = 1;
583 | while (m < count) {
584 | stb_real_t T1_0 = output[0].real;
585 | stb_real_t T40 = output[0].imag;
586 | stb_real_t T3_0 = output[count].real;
587 | stb_real_t T5_0 = output[count].imag;
588 | stb_real_t T4_0 = tw[0].imag;
589 | stb_real_t T19_0 = output[3 * count].real;
590 | stb_real_t T21_0 = output[3 * count].imag;
591 | stb_real_t T18_0 = tw[2].real;
592 | stb_real_t T20_0 = tw[2].imag;
593 | stb_real_t T22_0 = T20_0 * T21_0 + T18_0 * T19_0;
594 | stb_real_t T32_0 = T18_0 * T21_0 - T20_0 * T19_0;
595 | stb_real_t T8_0 = output[4 * count].real;
596 | stb_real_t T10_0 = output[4 * count].imag;
597 | stb_real_t T7_0 = tw[3].real;
598 | stb_real_t T9_0 = tw[3].imag;
599 | stb_real_t T11_0 = T9_0 * T10_0 + T7_0 * T8_0;
600 | stb_real_t T29_0 = T7_0 * T10_0 - T9_0 * T8_0;
601 | stb_real_t T14_0 = output[2 * count].real;
602 | stb_real_t T16_0 = output[2 * count].imag;
603 | stb_real_t T13_0 = tw[1].real;
604 | stb_real_t T15_0 = tw[1].imag;
605 | stb_real_t T30_0 = tw[0].real * T5_0 - T4_0 * T3_0 - T29_0;
606 | stb_real_t T33 = T13_0 * T16_0 - T15_0 * T14_0 - T32_0;
607 | stb_real_t T45 = T15_0 * T16_0 + T13_0 * T14_0 - T22_0;
608 | stb_real_t T44 = T4_0 * T5_0 + tw[0].real * T3_0 - T11_0;
609 | stb_real_t T37 = tw[0].real * T5_0 - T4_0 * T3_0 + T29_0;
610 | stb_real_t T38 = T13_0 * T16_0 - T15_0 * T14_0 + T32_0;
611 | stb_real_t T39 = T37 + T38;
612 | stb_real_t T12_0 = T4_0 * T5_0 + tw[0].real * T3_0 + T11_0;
613 | stb_real_t T23_0 = T15_0 * T16_0 + T13_0 * T14_0 + T22_0;
614 | stb_real_t T24_0 = T12_0 + T23_0;
615 | output[0].real = output[0].real + T24_0;
616 | output[0].imag = T39 + T40;
617 | stb_real_t T34 = STB_KP587785252 * T33 + STB_KP951056516 * T30_0;
618 | stb_real_t T36 = STB_KP951056516 * T33 - STB_KP587785252 * T30_0;
619 | stb_real_t T27_0 = (T12_0 - T23_0) * STB_KP559016994 + T1_0 - STB_KP25 * T24_0;
620 | stb_real_t T35 = T1_0 - STB_KP25 * T24_0 - (T12_0 - T23_0) * STB_KP559016994;
621 | output[4 * count].real = T27_0 - T34;
622 | output[3 * count].real = T35 + T36;
623 | output[count].real = T27_0 + T34;
624 | output[2 * count].real = T35 - T36;
625 | stb_real_t T46 = STB_KP587785252 * T45 + STB_KP951056516 * T44;
626 | stb_real_t T47 = STB_KP951056516 * T45 - STB_KP587785252 * T44;
627 | stb_real_t T43 = (T37 - T38) * STB_KP559016994 + T40 - STB_KP25 * T39;
628 | stb_real_t T48 = T40 - STB_KP25 * T39 - (T37 - T38) * STB_KP559016994;
629 | output[count].imag = T43 - T46;
630 | output[3 * count].imag = T48 - T47;
631 | output[4 * count].imag = T46 + T43;
632 | output[2 * count].imag = T47 + T48;
633 | ++m;
634 | ++output;
635 | tw += 4;
636 | }
637 | }
638 |
639 | void stb_radix_6_dit(const cmplx* tw, cmplx* out, int count)
640 | {
641 | int m;
642 | cmplx* output;
643 | stb_real_t T2 = out[3 * count].real;
644 | stb_real_t T3 = out[0].real - T2;
645 | stb_real_t T11 = out[0].real + T2;
646 | stb_real_t T24 = out[0].imag;
647 | stb_real_t T25 = out[3 * count].imag;
648 | stb_real_t T4 = out[2 * count].real;
649 | stb_real_t T5 = out[5 * count].real;
650 | stb_real_t T7 = out[4 * count].real;
651 | stb_real_t T8 = out[count].real;
652 | stb_real_t T10 = T4 - T5 + T7 - T8;
653 | stb_real_t T14 = T4 + T5 + T7 + T8;
654 | stb_real_t T16 = out[2 * count].imag;
655 | stb_real_t T17 = out[5 * count].imag;
656 | stb_real_t T19 = out[4 * count].imag;
657 | stb_real_t T20 = out[count].imag;
658 | stb_real_t T27 = T16 - T17 + T19 - T20;
659 | stb_real_t T34 = T16 + T17 + T19 + T20;
660 | out[3 * count].real = T3 + T10;
661 | out[3 * count].imag = T24 - T25 + T27;
662 | out[0].real = T11 + T14;
663 | out[0].imag = T24 + T25 + T34;
664 | stb_real_t T22 = (T16 - T17 - (T19 - T20)) * STB_KP866025403;
665 | out[5 * count].real = T3 - STB_KP5 * T10 - T22;
666 | out[count].real = T3 - STB_KP5 * T10 + T22;
667 | stb_real_t T23 = (T7 - T8 - (T4 - T5)) * STB_KP866025403;
668 | stb_real_t T28 = T24 - T25 - STB_KP5 * T27;
669 | out[count].imag = T23 + T28;
670 | out[5 * count].imag = T28 - T23;
671 | stb_real_t T32 = (T16 + T17 - (T19 + T20)) * STB_KP866025403;
672 | out[2 * count].real = T11 - STB_KP5 * T14 - T32;
673 | out[4 * count].real = T11 - STB_KP5 * T14 + T32;
674 | stb_real_t T35 = T24 + T25 - STB_KP5 * T34;
675 | stb_real_t T36 = (T7 + T8 - (T4 + T5)) * STB_KP866025403;
676 | out[2 * count].imag = T35 - T36;
677 | out[4 * count].imag = T36 + T35;
678 | output = out + 1;
679 | m = 1;
680 | while (m < count) {
681 | stb_real_t T49 = output[0].imag;
682 | stb_real_t T3_0 = output[3 * count].real;
683 | stb_real_t T5_0 = output[3 * count].imag;
684 | stb_real_t T2_0 = tw[2].real;
685 | stb_real_t T4_0 = tw[2].imag;
686 | stb_real_t T6_0 = T4_0 * T5_0 + T2_0 * T3_0;
687 | stb_real_t T54 = T49 - (T2_0 * T5_0 - T4_0 * T3_0);
688 | stb_real_t T31_0 = output[0].real + T6_0;
689 | stb_real_t T50 = T2_0 * T5_0 - T4_0 * T3_0 + T49;
690 | stb_real_t T20_0 = output[4 * count].real;
691 | stb_real_t T22_0 = output[4 * count].imag;
692 | stb_real_t T19_0 = tw[3].real;
693 | stb_real_t T21_0 = tw[3].imag;
694 | stb_real_t T25_0 = output[count].real;
695 | stb_real_t T27_0 = output[count].imag;
696 | stb_real_t T26_0 = tw[0].imag;
697 | stb_real_t T28_0 = T26_0 * T27_0 + tw[0].real * T25_0;
698 | stb_real_t T40 = tw[0].real * T27_0 - T26_0 * T25_0;
699 | stb_real_t T29_0 = T21_0 * T22_0 + T19_0 * T20_0 - T28_0;
700 | stb_real_t T45 = T19_0 * T22_0 - T21_0 * T20_0 + T40;
701 | stb_real_t T33_0 = T21_0 * T22_0 + T19_0 * T20_0 + T28_0;
702 | stb_real_t T41 = T19_0 * T22_0 - T21_0 * T20_0 - T40;
703 | stb_real_t T9_0 = output[2 * count].real;
704 | stb_real_t T11_0 = output[2 * count].imag;
705 | stb_real_t T8_0 = tw[1].real;
706 | stb_real_t T10_0 = tw[1].imag;
707 | stb_real_t T14_0 = output[5 * count].real;
708 | stb_real_t T16_0 = output[5 * count].imag;
709 | stb_real_t T13_0 = tw[4].real;
710 | stb_real_t T15_0 = tw[4].imag;
711 | stb_real_t T17_0 = T15_0 * T16_0 + T13_0 * T14_0;
712 | stb_real_t T37 = T13_0 * T16_0 - T15_0 * T14_0;
713 | stb_real_t T44 = T8_0 * T11_0 - T10_0 * T9_0 + T37;
714 | stb_real_t T32_0 = T10_0 * T11_0 + T8_0 * T9_0 + T17_0;
715 | stb_real_t T42 = (T8_0 * T11_0 - T10_0 * T9_0 - T37 - T41) * STB_KP866025403;
716 | stb_real_t T30_0 = T10_0 * T11_0 + T8_0 * T9_0 - T17_0 + T29_0;
717 | stb_real_t T35_0 = output[0].real - T6_0 - STB_KP5 * T30_0;
718 | output[3 * count].real = output[0].real - T6_0 + T30_0;
719 | output[count].real = T35_0 + T42;
720 | output[5 * count].real = T35_0 - T42;
721 | stb_real_t T53 = (T29_0 - (T10_0 * T11_0 + T8_0 * T9_0 - T17_0)) * STB_KP866025403;
722 | stb_real_t T55 = T8_0 * T11_0 - T10_0 * T9_0 - T37 + T41;
723 | stb_real_t T56 = T54 - STB_KP5 * T55;
724 | output[count].imag = T53 + T56;
725 | output[3 * count].imag = T55 + T54;
726 | output[5 * count].imag = T56 - T53;
727 | stb_real_t T46 = (T44 - T45) * STB_KP866025403;
728 | stb_real_t T43 = T31_0 - STB_KP5 * (T32_0 + T33_0);
729 | output[0].real = T31_0 + T32_0 + T33_0;
730 | output[4 * count].real = T43 + T46;
731 | output[2 * count].real = T43 - T46;
732 | stb_real_t T52 = (T33_0 - T32_0) * STB_KP866025403;
733 | stb_real_t T51 = T50 - STB_KP5 * (T44 + T45);
734 | output[0].imag = T44 + T45 + T50;
735 | output[4 * count].imag = T52 + T51;
736 | output[2 * count].imag = T51 - T52;
737 | ++m;
738 | ++output;
739 | tw += 5;
740 | }
741 | }
742 |
743 | void stb_radix_7_dit(const cmplx* tw, cmplx* out, int count)
744 | {
745 | int m;
746 | cmplx* output;
747 | stb_real_t T1 = out[0].real;
748 | stb_real_t T30 = out[0].imag;
749 | stb_real_t T2 = out[count].real;
750 | stb_real_t T3 = out[6 * count].real;
751 | stb_real_t T12 = out[count].imag;
752 | stb_real_t T13 = out[6 * count].imag;
753 | stb_real_t T5 = out[2 * count].real;
754 | stb_real_t T6 = out[5 * count].real;
755 | stb_real_t T18 = out[2 * count].imag;
756 | stb_real_t T19 = out[5 * count].imag;
757 | stb_real_t T8 = out[3 * count].real;
758 | stb_real_t T9 = out[4 * count].real;
759 | stb_real_t T15 = out[3 * count].imag;
760 | stb_real_t T16 = out[4 * count].imag;
761 | out[0].real = out[0].real + T2 + T3 + T5 + T6 + T8 + T9;
762 | out[0].imag = T30 + T12 + T13 + T18 + T19 + T15 + T16;
763 | stb_real_t T21 = STB_KP974927912 * (T12 - T13) - STB_KP781831482 * (T15 - T16) - STB_KP433883739 * (T18 - T19);
764 | out[5 * count].real = STB_KP623489801 * (T8 + T9)
765 | + T1
766 | - (STB_KP222520933 * (T2 + T3)
767 | + STB_KP900968867 * (T5 + T6))
768 | - T21;
769 | out[2 * count].real = STB_KP623489801 * (T8 + T9)
770 | + T1
771 | - (STB_KP222520933 * (T2 + T3)
772 | + STB_KP900968867 * (T5 + T6))
773 | + T21;
774 | stb_real_t T38 = STB_KP623489801 * (T15 + T16) + T30 - (STB_KP222520933 * (T12 + T13) + STB_KP900968867 * (T18 + T19));
775 | out[2 * count].imag = STB_KP974927912 * (T3 - T2)
776 | - STB_KP781831482 * (T9 - T8)
777 | - STB_KP433883739 * (T6 - T5)
778 | + T38;
779 | out[5 * count].imag = T38
780 | - (STB_KP974927912 * (T3 - T2)
781 | - STB_KP781831482 * (T9 - T8)
782 | - STB_KP433883739 * (T6 - T5));
783 | stb_real_t T23 = STB_KP433883739 * (T15 - T16) + STB_KP781831482 * (T12 - T13) + STB_KP974927912 * (T18 - T19);
784 | out[6 * count].real = STB_KP623489801 * (T2 + T3)
785 | + T1
786 | - (STB_KP222520933 * (T5 + T6)
787 | + STB_KP900968867 * (T8 + T9))
788 | - T23;
789 | out[count].real = STB_KP623489801 * (T2 + T3)
790 | + T1
791 | - (STB_KP222520933 * (T5 + T6)
792 | + STB_KP900968867 * (T8 + T9))
793 | + T23;
794 | stb_real_t T36 = STB_KP623489801 * (T12 + T13) + T30 - (STB_KP222520933 * (T18 + T19) + STB_KP900968867 * (T15 + T16));
795 | out[count].imag = STB_KP433883739 * (T9 - T8)
796 | + STB_KP781831482 * (T3 - T2)
797 | + STB_KP974927912 * (T6 - T5)
798 | + T36;
799 | out[6 * count].imag = T36
800 | - (STB_KP433883739 * (T9 - T8)
801 | + STB_KP781831482 * (T3 - T2)
802 | + STB_KP974927912 * (T6 - T5));
803 | stb_real_t T25 = STB_KP974927912 * (T15 - T16) + STB_KP433883739 * (T12 - T13) - STB_KP781831482 * (T18 - T19);
804 | stb_real_t T24 = STB_KP623489801 * (T5 + T6) + T1 - (STB_KP900968867 * (T2 + T3) + STB_KP222520933 * (T8 + T9));
805 | out[4 * count].real = T24 - T25;
806 | out[3 * count].real = T24 + T25;
807 | stb_real_t T29 = STB_KP974927912 * (T9 - T8) + STB_KP433883739 * (T3 - T2) - STB_KP781831482 * (T6 - T5);
808 | stb_real_t T34 = STB_KP623489801 * (T18 + T19) + T30 - (STB_KP900968867 * (T12 + T13) + STB_KP222520933 * (T15 + T16));
809 | out[3 * count].imag = T29 + T34;
810 | out[4 * count].imag = T34 - T29;
811 | output = out + 1;
812 | m = 1;
813 | while (m < count) {
814 | stb_real_t T1_0 = output[0].real;
815 | stb_real_t T53 = output[0].imag;
816 | stb_real_t T3_0 = output[count].real;
817 | stb_real_t T5_0 = output[count].imag;
818 | stb_real_t T4_0 = tw[0].imag;
819 | stb_real_t T8_0 = output[6 * count].real;
820 | stb_real_t T10_0 = output[6 * count].imag;
821 | stb_real_t T7_0 = tw[5].real;
822 | stb_real_t T9_0 = tw[5].imag;
823 | stb_real_t T37_0 = T7_0 * T10_0 - T9_0 * T8_0;
824 | stb_real_t T12_0 = T4_0 * T5_0 + tw[0].real * T3_0 + T9_0 * T10_0 + T7_0 * T8_0;
825 | stb_real_t T54 = T9_0 * T10_0 + T7_0 * T8_0 - (T4_0 * T5_0 + tw[0].real * T3_0);
826 | stb_real_t T38_0 = tw[0].real * T5_0 - T4_0 * T3_0 - T37_0;
827 | stb_real_t T50 = tw[0].real * T5_0 - T4_0 * T3_0 + T37_0;
828 | stb_real_t T14_0 = output[2 * count].real;
829 | stb_real_t T16_0 = output[2 * count].imag;
830 | stb_real_t T13_0 = tw[1].real;
831 | stb_real_t T15_0 = tw[1].imag;
832 | stb_real_t T19_0 = output[5 * count].real;
833 | stb_real_t T21_0 = output[5 * count].imag;
834 | stb_real_t T18_0 = tw[4].real;
835 | stb_real_t T20_0 = tw[4].imag;
836 | stb_real_t T43 = T18_0 * T21_0 - T20_0 * T19_0;
837 | stb_real_t T23_0 = T15_0 * T16_0 + T13_0 * T14_0 + T20_0 * T21_0 + T18_0 * T19_0;
838 | stb_real_t T55 = T20_0 * T21_0 + T18_0 * T19_0 - (T15_0 * T16_0 + T13_0 * T14_0);
839 | stb_real_t T44 = T13_0 * T16_0 - T15_0 * T14_0 - T43;
840 | stb_real_t T51 = T13_0 * T16_0 - T15_0 * T14_0 + T43;
841 | stb_real_t T25_0 = output[3 * count].real;
842 | stb_real_t T27_0 = output[3 * count].imag;
843 | stb_real_t T24_0 = tw[2].real;
844 | stb_real_t T26_0 = tw[2].imag;
845 | stb_real_t T30_0 = output[4 * count].real;
846 | stb_real_t T32_0 = output[4 * count].imag;
847 | stb_real_t T29_0 = tw[3].real;
848 | stb_real_t T31_0 = tw[3].imag;
849 | stb_real_t T40 = T29_0 * T32_0 - T31_0 * T30_0;
850 | stb_real_t T34_0 = T26_0 * T27_0 + T24_0 * T25_0 + T31_0 * T32_0 + T29_0 * T30_0;
851 | stb_real_t T56 = T31_0 * T32_0 + T29_0 * T30_0 - (T26_0 * T27_0 + T24_0 * T25_0);
852 | stb_real_t T41 = T24_0 * T27_0 - T26_0 * T25_0 - T40;
853 | stb_real_t T52 = T24_0 * T27_0 - T26_0 * T25_0 + T40;
854 | output[0].real = output[0].real + T12_0 + T23_0 + T34_0;
855 | output[0].imag = T50 + T51 + T52 + T53;
856 | stb_real_t T45 = STB_KP974927912 * T38_0 - STB_KP781831482 * T41 - STB_KP433883739 * T44;
857 | output[5 * count].real = STB_KP623489801 * T34_0
858 | + T1_0
859 | - (STB_KP222520933 * T12_0
860 | + STB_KP900968867 * T23_0)
861 | - T45;
862 | output[2 * count].real = STB_KP623489801 * T34_0
863 | + T1_0
864 | - (STB_KP222520933 * T12_0
865 | + STB_KP900968867 * T23_0)
866 | + T45;
867 | stb_real_t T60 = STB_KP623489801 * T52 + T53 - (STB_KP222520933 * T50 + STB_KP900968867 * T51);
868 | output[2 * count].imag = STB_KP974927912 * T54 - STB_KP781831482 * T56 - STB_KP433883739 * T55 + T60;
869 | output[5 * count].imag = T60 - (STB_KP974927912 * T54 - STB_KP781831482 * T56 - STB_KP433883739 * T55);
870 | stb_real_t T47 = STB_KP433883739 * T41 + STB_KP781831482 * T38_0 + STB_KP974927912 * T44;
871 | output[6 * count].real = STB_KP623489801 * T12_0
872 | + T1_0
873 | - (STB_KP222520933 * T23_0
874 | + STB_KP900968867 * T34_0)
875 | - T47;
876 | output[count].real = STB_KP623489801 * T12_0
877 | + T1_0
878 | - (STB_KP222520933 * T23_0
879 | + STB_KP900968867 * T34_0)
880 | + T47;
881 | stb_real_t T58 = STB_KP623489801 * T50 + T53 - (STB_KP222520933 * T51 + STB_KP900968867 * T52);
882 | output[count].imag = STB_KP433883739 * T56 + STB_KP781831482 * T54 + STB_KP974927912 * T55 + T58;
883 | output[6 * count].imag = T58 - (STB_KP433883739 * T56 + STB_KP781831482 * T54 + STB_KP974927912 * T55);
884 | stb_real_t T49 = STB_KP974927912 * T41 + STB_KP433883739 * T38_0 - STB_KP781831482 * T44;
885 | output[4 * count].real = STB_KP623489801 * T23_0
886 | + T1_0
887 | - (STB_KP900968867 * T12_0
888 | + STB_KP222520933 * T34_0)
889 | - T49;
890 | output[3 * count].real = STB_KP623489801 * T23_0
891 | + T1_0
892 | - (STB_KP900968867 * T12_0
893 | + STB_KP222520933 * T34_0)
894 | + T49;
895 | stb_real_t T62 = STB_KP623489801 * T51 + T53 - (STB_KP900968867 * T50 + STB_KP222520933 * T52);
896 | output[3 * count].imag = STB_KP974927912 * T56 + STB_KP433883739 * T54 - STB_KP781831482 * T55 + T62;
897 | output[4 * count].imag = T62
898 | - (STB_KP974927912 * T56
899 | + STB_KP433883739 * T54
900 | - STB_KP781831482 * T55);
901 | ++m;
902 | ++output;
903 | tw += 6;
904 | }
905 | }
906 |
907 | void stb_radix_8_dit(const cmplx* tw, cmplx* out, int count)
908 | {
909 | int m;
910 | cmplx* output;
911 | stb_real_t T2 = out[4 * count].real;
912 | stb_real_t T3 = out[0].real + T2;
913 | stb_real_t T23 = out[0].real - T2;
914 | stb_real_t T16 = out[0].imag;
915 | stb_real_t T17 = out[4 * count].imag;
916 | stb_real_t T4 = out[2 * count].real;
917 | stb_real_t T5 = out[6 * count].real;
918 | stb_real_t T19 = out[2 * count].imag;
919 | stb_real_t T20 = out[6 * count].imag;
920 | stb_real_t T11 = out[7 * count].real;
921 | stb_real_t T12 = out[3 * count].real;
922 | stb_real_t T32 = out[7 * count].imag;
923 | stb_real_t T33 = out[3 * count].imag;
924 | stb_real_t T35 = T11 - T12 - (T32 - T33);
925 | stb_real_t T43 = T11 - T12 + T32 - T33;
926 | stb_real_t T8 = out[count].real;
927 | stb_real_t T9 = out[5 * count].real;
928 | stb_real_t T27 = out[count].imag;
929 | stb_real_t T28 = out[5 * count].imag;
930 | stb_real_t T30 = T8 - T9 + T27 - T28;
931 | stb_real_t T42 = T27 - T28 - (T8 - T9);
932 | stb_real_t T7 = T3 + T4 + T5;
933 | stb_real_t T14 = T8 + T9 + T11 + T12;
934 | out[4 * count].real = T7 - T14;
935 | out[0].real = T7 + T14;
936 | out[4 * count].imag = T16 + T17 + T19 + T20 - (T27 + T28 + T32 + T33);
937 | out[0].imag = T16 + T17 + T19 + T20 + T27 + T28 + T32 + T33;
938 | stb_real_t T15 = T11 + T12 - (T8 + T9);
939 | stb_real_t T22 = T16 + T17 - (T19 + T20);
940 | out[2 * count].imag = T15 + T22;
941 | out[6 * count].imag = T22 - T15;
942 | stb_real_t T47 = T3 - (T4 + T5);
943 | stb_real_t T50 = T27 + T28 - (T32 + T33);
944 | out[6 * count].real = T47 - T50;
945 | out[2 * count].real = T47 + T50;
946 | stb_real_t T36 = (T30 + T35) * STB_KP707106781;
947 | out[5 * count].real = T23 + T19 - T20 - T36;
948 | out[count].real = T23 + T19 - T20 + T36;
949 | stb_real_t T46 = (T42 + T43) * STB_KP707106781;
950 | out[5 * count].imag = T16 - T17 - (T4 - T5) - T46;
951 | out[count].imag = T16 - T17 - (T4 - T5) + T46;
952 | stb_real_t T39 = T4 - T5 + T16 - T17;
953 | stb_real_t T40 = (T35 - T30) * STB_KP707106781;
954 | out[7 * count].imag = T39 - T40;
955 | out[3 * count].imag = T39 + T40;
956 | stb_real_t T41 = T23 - (T19 - T20);
957 | stb_real_t T44 = (T42 - T43) * STB_KP707106781;
958 | out[7 * count].real = T41 - T44;
959 | out[3 * count].real = T41 + T44;
960 | output = out + 1;
961 | m = 1;
962 | while (m < count) {
963 | stb_real_t T70 = output[0].imag;
964 | stb_real_t T3_0 = output[4 * count].real;
965 | stb_real_t T5_0 = output[4 * count].imag;
966 | stb_real_t T2_0 = tw[3].real;
967 | stb_real_t T4_0 = tw[3].imag;
968 | stb_real_t T6_0 = T4_0 * T5_0 + T2_0 * T3_0;
969 | stb_real_t T7_0 = output[0].real + T6_0;
970 | stb_real_t T76 = T70 - (T2_0 * T5_0 - T4_0 * T3_0);
971 | stb_real_t T43_0 = output[0].real - T6_0;
972 | stb_real_t T71 = T2_0 * T5_0 - T4_0 * T3_0 + T70;
973 | stb_real_t T32_0 = output[7 * count].real;
974 | stb_real_t T34_0 = output[7 * count].imag;
975 | stb_real_t T31_0 = tw[6].real;
976 | stb_real_t T33_0 = tw[6].imag;
977 | stb_real_t T37_0 = output[3 * count].real;
978 | stb_real_t T39_0 = output[3 * count].imag;
979 | stb_real_t T36_0 = tw[2].real;
980 | stb_real_t T38_0 = tw[2].imag;
981 | stb_real_t T40_0 = T38_0 * T39_0 + T36_0 * T37_0;
982 | stb_real_t T55 = T36_0 * T39_0 - T38_0 * T37_0;
983 | stb_real_t T41_0 = T33_0 * T34_0 + T31_0 * T32_0 + T40_0;
984 | stb_real_t T65 = T31_0 * T34_0 - T33_0 * T32_0 + T55;
985 | stb_real_t T53 = T33_0 * T34_0 + T31_0 * T32_0 - T40_0;
986 | stb_real_t T56 = T31_0 * T34_0 - T33_0 * T32_0 - T55;
987 | stb_real_t T9_0 = output[2 * count].real;
988 | stb_real_t T11_0 = output[2 * count].imag;
989 | stb_real_t T8_0 = tw[1].real;
990 | stb_real_t T10_0 = tw[1].imag;
991 | stb_real_t T14_0 = output[6 * count].real;
992 | stb_real_t T16_0 = output[6 * count].imag;
993 | stb_real_t T13_0 = tw[5].real;
994 | stb_real_t T15_0 = tw[5].imag;
995 | stb_real_t T17_0 = T15_0 * T16_0 + T13_0 * T14_0;
996 | stb_real_t T45_0 = T13_0 * T16_0 - T15_0 * T14_0;
997 | stb_real_t T18_0 = T10_0 * T11_0 + T8_0 * T9_0 + T17_0;
998 | stb_real_t T77 = T10_0 * T11_0 + T8_0 * T9_0 - T17_0;
999 | stb_real_t T46_0 = T8_0 * T11_0 - T10_0 * T9_0 - T45_0;
1000 | stb_real_t T68 = T8_0 * T11_0 - T10_0 * T9_0 + T45_0;
1001 | stb_real_t T21_0 = output[count].real;
1002 | stb_real_t T23_0 = output[count].imag;
1003 | stb_real_t T22_0 = tw[0].imag;
1004 | stb_real_t T26_0 = output[5 * count].real;
1005 | stb_real_t T28_0 = output[5 * count].imag;
1006 | stb_real_t T25_0 = tw[4].real;
1007 | stb_real_t T27_0 = tw[4].imag;
1008 | stb_real_t T29_0 = T27_0 * T28_0 + T25_0 * T26_0;
1009 | stb_real_t T50_0 = T25_0 * T28_0 - T27_0 * T26_0;
1010 | stb_real_t T30_0 = T22_0 * T23_0 + tw[0].real * T21_0 + T29_0;
1011 | stb_real_t T64 = tw[0].real * T23_0 - T22_0 * T21_0 + T50_0;
1012 | stb_real_t T48_0 = T22_0 * T23_0 + tw[0].real * T21_0 - T29_0;
1013 | stb_real_t T51_0 = tw[0].real * T23_0 - T22_0 * T21_0 - T50_0;
1014 | stb_real_t T19_0 = T7_0 + T18_0;
1015 | stb_real_t T42_0 = T30_0 + T41_0;
1016 | output[4 * count].real = T19_0 - T42_0;
1017 | output[0].real = T19_0 + T42_0;
1018 | output[0].imag = T64 + T65 + T68 + T71;
1019 | output[4 * count].imag = T68 + T71 - (T64 + T65);
1020 | output[6 * count].real = T7_0 - T18_0 - (T64 - T65);
1021 | output[2 * count].real = T7_0 - T18_0 + T64 - T65;
1022 | output[2 * count].imag = T41_0 - T30_0 + T71 - T68;
1023 | output[6 * count].imag = T71 - T68 - (T41_0 - T30_0);
1024 | stb_real_t T62 = (T51_0 - T48_0 - (T53 + T56)) * STB_KP707106781;
1025 | stb_real_t T75 = (T51_0 - T48_0 + T53 + T56) * STB_KP707106781;
1026 | output[7 * count].real = T43_0 - T46_0 - T62;
1027 | output[5 * count].imag = T76 - T77 - T75;
1028 | output[3 * count].real = T43_0 - T46_0 + T62;
1029 | output[count].imag = T75 + T76 - T77;
1030 | stb_real_t T58 = (T48_0 + T51_0 + T53 - T56) * STB_KP707106781;
1031 | stb_real_t T79 = (T53 - T56 - (T48_0 + T51_0)) * STB_KP707106781;
1032 | output[5 * count].real = T43_0 + T46_0 - T58;
1033 | output[7 * count].imag = T77 + T76 - T79;
1034 | output[count].real = T43_0 + T46_0 + T58;
1035 | output[3 * count].imag = T79 + T77 + T76;
1036 | ++m;
1037 | ++output;
1038 | tw += 7;
1039 | }
1040 | }
1041 |
1042 | void stb_radix_2_idit(const cmplx* tw, cmplx* out, int count)
1043 | {
1044 | int m;
1045 | cmplx* output;
1046 | stb_real_t T1 = out[0].real;
1047 | stb_real_t T2 = out[count].real;
1048 | out[count].real = out[0].real - T2;
1049 | out[0].real = T1 + T2;
1050 | stb_real_t T3 = out[0].imag;
1051 | stb_real_t T4 = out[count].imag;
1052 | out[count].imag = T3 - T4;
1053 | out[0].imag = T3 + T4;
1054 | output = out + 1;
1055 | m = 1;
1056 | while (m < count) {
1057 | stb_real_t T1_0 = output[0].real;
1058 | stb_real_t T8 = output[0].imag;
1059 | stb_real_t T3_0 = output[count].real;
1060 | stb_real_t T5 = output[count].imag;
1061 | stb_real_t T4_0 = tw[0].imag;
1062 | stb_real_t T6 = tw[0].real * T3_0 - T4_0 * T5;
1063 | stb_real_t T7 = tw[0].real * T5 + T4_0 * T3_0;
1064 | output[count].real = output[0].real - T6;
1065 | output[count].imag = T8 - T7;
1066 | output[0].real = T1_0 + T6;
1067 | output[0].imag = T7 + T8;
1068 | ++m;
1069 | ++output;
1070 | ++tw;
1071 | }
1072 | }
1073 |
1074 | void stb_radix_3_idit(const cmplx* tw, cmplx* out, int count)
1075 | {
1076 | int m;
1077 | cmplx* output;
1078 | stb_real_t T1 = out[0].real;
1079 | stb_real_t T6 = out[0].imag;
1080 | stb_real_t T2 = out[count].real;
1081 | stb_real_t T3 = out[2 * count].real;
1082 | stb_real_t T5 = (T2 - T3) * STB_KP866025403;
1083 | stb_real_t T7 = out[count].imag;
1084 | stb_real_t T8 = out[2 * count].imag;
1085 | stb_real_t T12 = (T8 - T7) * STB_KP866025403;
1086 | out[0].real = out[0].real + T2 + T3;
1087 | out[0].imag = T6 + T7 + T8;
1088 | stb_real_t T10 = T6 - STB_KP5 * (T7 + T8);
1089 | out[count].imag = T5 + T10;
1090 | out[2 * count].imag = T10 - T5;
1091 | stb_real_t T11 = T1 - STB_KP5 * (T2 + T3);
1092 | out[2 * count].real = T11 - T12;
1093 | out[count].real = T11 + T12;
1094 | output = out + 1;
1095 | m = 1;
1096 | while (m < count) {
1097 | stb_real_t T1_0 = output[0].real;
1098 | stb_real_t T18 = output[0].imag;
1099 | stb_real_t T3_0 = output[count].real;
1100 | stb_real_t T5_0 = output[count].imag;
1101 | stb_real_t T4_0 = tw[0].imag;
1102 | stb_real_t T6_0 = tw[0].real * T3_0 - T4_0 * T5_0;
1103 | stb_real_t T15 = tw[0].real * T5_0 + T4_0 * T3_0;
1104 | stb_real_t T8_0 = output[2 * count].real;
1105 | stb_real_t T10_0 = output[2 * count].imag;
1106 | stb_real_t T7_0 = tw[1].real;
1107 | stb_real_t T9_0 = tw[1].imag;
1108 | stb_real_t T11_0 = T7_0 * T8_0 - T9_0 * T10_0;
1109 | stb_real_t T14 = T7_0 * T10_0 + T9_0 * T8_0;
1110 | stb_real_t T12_0 = T6_0 + T11_0;
1111 | stb_real_t T17 = T15 + T14;
1112 | output[0].real = output[0].real + T12_0;
1113 | output[0].imag = T17 + T18;
1114 | stb_real_t T16 = (T14 - T15) * STB_KP866025403;
1115 | output[2 * count].real = T1_0 - STB_KP5 * T12_0 - T16;
1116 | output[count].real = T1_0 - STB_KP5 * T12_0 + T16;
1117 | stb_real_t T20 = T18 - STB_KP5 * T17;
1118 | output[count].imag = (T6_0 - T11_0) * STB_KP866025403 + T20;
1119 | output[2 * count].imag = T20 - (T6_0 - T11_0) * STB_KP866025403;
1120 | ++m;
1121 | ++output;
1122 | tw += 2;
1123 | }
1124 | }
1125 |
1126 | void stb_radix_4_idit(const cmplx* tw, cmplx* out, int count)
1127 | {
1128 | int m;
1129 | cmplx* output;
1130 | stb_real_t T2 = out[2 * count].real;
1131 | stb_real_t T3 = out[0].real + T2;
1132 | stb_real_t T11 = out[0].real - T2;
1133 | stb_real_t T8 = out[0].imag;
1134 | stb_real_t T9 = out[2 * count].imag;
1135 | stb_real_t T4 = out[count].real;
1136 | stb_real_t T5 = out[3 * count].real;
1137 | stb_real_t T12 = out[count].imag;
1138 | stb_real_t T13 = out[3 * count].imag;
1139 | out[2 * count].real = T3 - (T4 + T5);
1140 | out[2 * count].imag = T8 + T9 - (T12 + T13);
1141 | out[0].real = T3 + T4 + T5;
1142 | out[0].imag = T8 + T9 + T12 + T13;
1143 | out[count].imag = T4 - T5 + T8 - T9;
1144 | out[count].real = T11 - (T12 - T13);
1145 | out[3 * count].imag = T8 - T9 - (T4 - T5);
1146 | out[3 * count].real = T11 + T12 - T13;
1147 | output = out + 1;
1148 | m = 1;
1149 | while (m < count) {
1150 | stb_real_t T1_0 = output[0].real;
1151 | stb_real_t T25 = output[0].imag;
1152 | stb_real_t T3_0 = output[2 * count].real;
1153 | stb_real_t T5_0 = output[2 * count].imag;
1154 | stb_real_t T2_0 = tw[1].real;
1155 | stb_real_t T4_0 = tw[1].imag;
1156 | stb_real_t T6_0 = T2_0 * T3_0 - T4_0 * T5_0;
1157 | stb_real_t T24 = T2_0 * T5_0 + T4_0 * T3_0;
1158 | stb_real_t T9_0 = output[count].real;
1159 | stb_real_t T11_0 = output[count].imag;
1160 | stb_real_t T10_0 = tw[0].imag;
1161 | stb_real_t T12_0 = tw[0].real * T9_0 - T10_0 * T11_0;
1162 | stb_real_t T20 = tw[0].real * T11_0 + T10_0 * T9_0;
1163 | stb_real_t T14_0 = output[3 * count].real;
1164 | stb_real_t T16_0 = output[3 * count].imag;
1165 | stb_real_t T13_0 = tw[2].real;
1166 | stb_real_t T15_0 = tw[2].imag;
1167 | stb_real_t T17 = T13_0 * T14_0 - T15_0 * T16_0;
1168 | stb_real_t T21 = T13_0 * T16_0 + T15_0 * T14_0;
1169 | stb_real_t T18 = T12_0 + T17;
1170 | output[2 * count].real = output[0].real + T6_0 - T18;
1171 | output[0].real = T1_0 + T6_0 + T18;
1172 | output[0].imag = T20 + T21 + T24 + T25;
1173 | output[2 * count].imag = T24 + T25 - (T20 + T21);
1174 | output[count].real = T1_0 - T6_0 - (T20 - T21);
1175 | output[3 * count].real = T1_0 - T6_0 + T20 - T21;
1176 | output[count].imag = T12_0 - T17 + T25 - T24;
1177 | output[3 * count].imag = T25 - T24 - (T12_0 - T17);
1178 | ++m;
1179 | ++output;
1180 | tw += 3;
1181 | }
1182 | }
1183 |
1184 | void stb_radix_5_idit(const cmplx* tw, cmplx* out, int count)
1185 | {
1186 | int m;
1187 | cmplx* output;
1188 | stb_real_t T1 = out[0].real;
1189 | stb_real_t T27 = out[0].imag;
1190 | stb_real_t T2 = out[count].real;
1191 | stb_real_t T3 = out[4 * count].real;
1192 | stb_real_t T5 = out[2 * count].real;
1193 | stb_real_t T6 = out[3 * count].real;
1194 | stb_real_t T8 = T2 + T3 + T5 + T6;
1195 | stb_real_t T10 = (T2 + T3 - (T5 + T6)) * STB_KP559016994;
1196 | stb_real_t T12 = out[count].imag;
1197 | stb_real_t T13 = out[4 * count].imag;
1198 | stb_real_t T15 = out[2 * count].imag;
1199 | stb_real_t T16 = out[3 * count].imag;
1200 | stb_real_t T28 = T12 + T13 + T15 + T16;
1201 | stb_real_t T26 = (T12 + T13 - (T15 + T16)) * STB_KP559016994;
1202 | out[0].real = out[0].real + T8;
1203 | out[0].imag = T27 + T28;
1204 | stb_real_t T18 = STB_KP587785252 * (T12 - T13) - STB_KP951056516 * (T15 - T16);
1205 | stb_real_t T20 = STB_KP587785252 * (T15 - T16) + STB_KP951056516 * (T12 - T13);
1206 | stb_real_t T19 = T10 + T1 - STB_KP25 * T8;
1207 | out[2 * count].real = T1 - STB_KP25 * T8 - T10 - T18;
1208 | out[4 * count].real = T19 + T20;
1209 | out[3 * count].real = T1 - STB_KP25 * T8 - T10 + T18;
1210 | out[count].real = T19 - T20;
1211 | stb_real_t T31 = STB_KP587785252 * (T2 - T3) - STB_KP951056516 * (T5 - T6);
1212 | stb_real_t T30 = T26 + T27 - STB_KP25 * T28;
1213 | stb_real_t T32 = T27 - STB_KP25 * T28 - T26;
1214 | out[count].imag = STB_KP587785252 * (T5 - T6) + STB_KP951056516 * (T2 - T3) + T30;
1215 | out[3 * count].imag = T32 - T31;
1216 | out[4 * count].imag = T30 - (STB_KP587785252 * (T5 - T6) + STB_KP951056516 * (T2 - T3));
1217 | out[2 * count].imag = T31 + T32;
1218 | output = out + 1;
1219 | m = 1;
1220 | while (m < count) {
1221 | stb_real_t T1_0 = output[0].real;
1222 | stb_real_t T40 = output[0].imag;
1223 | stb_real_t T3_0 = output[count].real;
1224 | stb_real_t T5_0 = output[count].imag;
1225 | stb_real_t T4_0 = tw[0].imag;
1226 | stb_real_t T19_0 = output[3 * count].real;
1227 | stb_real_t T21_0 = output[3 * count].imag;
1228 | stb_real_t T18_0 = tw[2].real;
1229 | stb_real_t T20_0 = tw[2].imag;
1230 | stb_real_t T22_0 = T18_0 * T19_0 - T20_0 * T21_0;
1231 | stb_real_t T32_0 = T18_0 * T21_0 + T20_0 * T19_0;
1232 | stb_real_t T8_0 = output[4 * count].real;
1233 | stb_real_t T10_0 = output[4 * count].imag;
1234 | stb_real_t T7_0 = tw[3].real;
1235 | stb_real_t T9_0 = tw[3].imag;
1236 | stb_real_t T11_0 = T7_0 * T8_0 - T9_0 * T10_0;
1237 | stb_real_t T29_0 = T7_0 * T10_0 + T9_0 * T8_0;
1238 | stb_real_t T14_0 = output[2 * count].real;
1239 | stb_real_t T16_0 = output[2 * count].imag;
1240 | stb_real_t T13_0 = tw[1].real;
1241 | stb_real_t T15_0 = tw[1].imag;
1242 | stb_real_t T30_0 = tw[0].real * T5_0 + T4_0 * T3_0 - T29_0;
1243 | stb_real_t T33 = T13_0 * T16_0 + T15_0 * T14_0 - T32_0;
1244 | stb_real_t T42 = T13_0 * T14_0 - T15_0 * T16_0 - T22_0;
1245 | stb_real_t T41 = tw[0].real * T3_0 - T4_0 * T5_0 - T11_0;
1246 | stb_real_t T37 = tw[0].real * T5_0 + T4_0 * T3_0 + T29_0;
1247 | stb_real_t T38 = T13_0 * T16_0 + T15_0 * T14_0 + T32_0;
1248 | stb_real_t T39 = T37 + T38;
1249 | stb_real_t T12_0 = tw[0].real * T3_0 - T4_0 * T5_0 + T11_0;
1250 | stb_real_t T23_0 = T13_0 * T14_0 - T15_0 * T16_0 + T22_0;
1251 | stb_real_t T24_0 = T12_0 + T23_0;
1252 | output[0].real = output[0].real + T24_0;
1253 | output[0].imag = T39 + T40;
1254 | stb_real_t T34 = STB_KP587785252 * T30_0 - STB_KP951056516 * T33;
1255 | stb_real_t T36 = STB_KP587785252 * T33 + STB_KP951056516 * T30_0;
1256 | stb_real_t T27_0 = T1_0 - STB_KP25 * T24_0 - (T12_0 - T23_0) * STB_KP559016994;
1257 | stb_real_t T35 = (T12_0 - T23_0) * STB_KP559016994 + T1_0 - STB_KP25 * T24_0;
1258 | output[2 * count].real = T27_0 - T34;
1259 | output[4 * count].real = T35 + T36;
1260 | output[3 * count].real = T27_0 + T34;
1261 | output[count].real = T35 - T36;
1262 | stb_real_t T47 = STB_KP587785252 * T41 - STB_KP951056516 * T42;
1263 | stb_real_t T46 = (T37 - T38) * STB_KP559016994 + T40 - STB_KP25 * T39;
1264 | stb_real_t T48 = T40 - STB_KP25 * T39 - (T37 - T38) * STB_KP559016994;
1265 | output[count].imag = STB_KP587785252 * T42 + STB_KP951056516 * T41 + T46;
1266 | output[3 * count].imag = T48 - T47;
1267 | output[4 * count].imag = T46 - (STB_KP587785252 * T42 + STB_KP951056516 * T41);
1268 | output[2 * count].imag = T47 + T48;
1269 | ++m;
1270 | ++output;
1271 | tw += 4;
1272 | }
1273 | }
1274 |
1275 | void stb_radix_6_idit(const cmplx* tw, cmplx* out, int count)
1276 | {
1277 | int m;
1278 | cmplx* output;
1279 | stb_real_t T2 = out[3 * count].real;
1280 | stb_real_t T3 = out[0].real - T2;
1281 | stb_real_t T11 = out[0].real + T2;
1282 | stb_real_t T24 = out[0].imag;
1283 | stb_real_t T25 = out[3 * count].imag;
1284 | stb_real_t T4 = out[2 * count].real;
1285 | stb_real_t T5 = out[5 * count].real;
1286 | stb_real_t T7 = out[4 * count].real;
1287 | stb_real_t T8 = out[count].real;
1288 | stb_real_t T10 = T4 - T5 + T7 - T8;
1289 | stb_real_t T14 = T4 + T5 + T7 + T8;
1290 | stb_real_t T16 = out[4 * count].imag;
1291 | stb_real_t T17 = out[count].imag;
1292 | stb_real_t T19 = out[2 * count].imag;
1293 | stb_real_t T20 = out[5 * count].imag;
1294 | stb_real_t T27 = T19 - T20 + T16 - T17;
1295 | stb_real_t T32 = T19 + T20 + T16 + T17;
1296 | out[3 * count].real = T3 + T10;
1297 | out[3 * count].imag = T24 - T25 + T27;
1298 | out[0].real = T11 + T14;
1299 | out[0].imag = T24 + T25 + T32;
1300 | stb_real_t T22 = (T16 - T17 - (T19 - T20)) * STB_KP866025403;
1301 | out[5 * count].real = T3 - STB_KP5 * T10 - T22;
1302 | out[count].real = T3 - STB_KP5 * T10 + T22;
1303 | stb_real_t T23 = (T4 - T5 - (T7 - T8)) * STB_KP866025403;
1304 | stb_real_t T28 = T24 - T25 - STB_KP5 * T27;
1305 | out[count].imag = T23 + T28;
1306 | out[5 * count].imag = T28 - T23;
1307 | stb_real_t T33 = T24 + T25 - STB_KP5 * T32;
1308 | stb_real_t T34 = (T4 + T5 - (T7 + T8)) * STB_KP866025403;
1309 | out[2 * count].imag = T33 - T34;
1310 | out[4 * count].imag = T34 + T33;
1311 | stb_real_t T36 = (T16 + T17 - (T19 + T20)) * STB_KP866025403;
1312 | out[2 * count].real = T11 - STB_KP5 * T14 - T36;
1313 | out[4 * count].real = T11 - STB_KP5 * T14 + T36;
1314 | output = out + 1;
1315 | m = 1;
1316 | while (m < count) {
1317 | stb_real_t T49 = output[0].imag;
1318 | stb_real_t T3_0 = output[3 * count].real;
1319 | stb_real_t T5_0 = output[3 * count].imag;
1320 | stb_real_t T2_0 = tw[2].real;
1321 | stb_real_t T4_0 = tw[2].imag;
1322 | stb_real_t T6_0 = T2_0 * T3_0 - T4_0 * T5_0;
1323 | stb_real_t T54 = T49 - (T2_0 * T5_0 + T4_0 * T3_0);
1324 | stb_real_t T31_0 = output[0].real + T6_0;
1325 | stb_real_t T50 = T2_0 * T5_0 + T4_0 * T3_0 + T49;
1326 | stb_real_t T20_0 = output[4 * count].real;
1327 | stb_real_t T22_0 = output[4 * count].imag;
1328 | stb_real_t T19_0 = tw[3].real;
1329 | stb_real_t T21_0 = tw[3].imag;
1330 | stb_real_t T25_0 = output[count].real;
1331 | stb_real_t T27_0 = output[count].imag;
1332 | stb_real_t T26_0 = tw[0].imag;
1333 | stb_real_t T28_0 = tw[0].real * T25_0 - T26_0 * T27_0;
1334 | stb_real_t T37 = tw[0].real * T27_0 + T26_0 * T25_0;
1335 | stb_real_t T29_0 = T19_0 * T20_0 - T21_0 * T22_0 - T28_0;
1336 | stb_real_t T44 = T19_0 * T22_0 + T21_0 * T20_0 + T37;
1337 | stb_real_t T33_0 = T19_0 * T20_0 - T21_0 * T22_0 + T28_0;
1338 | stb_real_t T9_0 = output[2 * count].real;
1339 | stb_real_t T11_0 = output[2 * count].imag;
1340 | stb_real_t T8_0 = tw[1].real;
1341 | stb_real_t T10_0 = tw[1].imag;
1342 | stb_real_t T14_0 = output[5 * count].real;
1343 | stb_real_t T16_0 = output[5 * count].imag;
1344 | stb_real_t T13_0 = tw[4].real;
1345 | stb_real_t T15_0 = tw[4].imag;
1346 | stb_real_t T17_0 = T13_0 * T14_0 - T15_0 * T16_0;
1347 | stb_real_t T40 = T13_0 * T16_0 + T15_0 * T14_0;
1348 | stb_real_t T45 = T8_0 * T11_0 + T10_0 * T9_0 + T40;
1349 | stb_real_t T32_0 = T8_0 * T9_0 - T10_0 * T11_0 + T17_0;
1350 | stb_real_t T41 = T8_0 * T11_0 + T10_0 * T9_0 - T40;
1351 | stb_real_t T42 = (T19_0 * T22_0 + T21_0 * T20_0 - T37 - T41) * STB_KP866025403;
1352 | stb_real_t T30_0 = T8_0 * T9_0 - T10_0 * T11_0 - T17_0 + T29_0;
1353 | stb_real_t T35_0 = output[0].real - T6_0 - STB_KP5 * T30_0;
1354 | output[3 * count].real = output[0].real - T6_0 + T30_0;
1355 | output[count].real = T35_0 + T42;
1356 | output[5 * count].real = T35_0 - T42;
1357 | stb_real_t T53 = (T8_0 * T9_0 - T10_0 * T11_0 - T17_0 - T29_0) * STB_KP866025403;
1358 | stb_real_t T55 = T41 + T19_0 * T22_0 + T21_0 * T20_0 - T37;
1359 | stb_real_t T56 = T54 - STB_KP5 * T55;
1360 | output[count].imag = T53 + T56;
1361 | output[3 * count].imag = T55 + T54;
1362 | output[5 * count].imag = T56 - T53;
1363 | stb_real_t T46 = (T44 - T45) * STB_KP866025403;
1364 | stb_real_t T43 = T31_0 - STB_KP5 * (T32_0 + T33_0);
1365 | output[0].real = T31_0 + T32_0 + T33_0;
1366 | output[4 * count].real = T43 + T46;
1367 | output[2 * count].real = T43 - T46;
1368 | stb_real_t T52 = (T32_0 - T33_0) * STB_KP866025403;
1369 | stb_real_t T51 = T50 - STB_KP5 * (T45 + T44);
1370 | output[0].imag = T45 + T44 + T50;
1371 | output[4 * count].imag = T52 + T51;
1372 | output[2 * count].imag = T51 - T52;
1373 | ++m;
1374 | ++output;
1375 | tw += 5;
1376 | }
1377 | }
1378 |
1379 | void stb_radix_7_idit(const cmplx* tw, cmplx* out, int count)
1380 | {
1381 | int m;
1382 | cmplx* output;
1383 | stb_real_t T1 = out[0].real;
1384 | stb_real_t T15 = out[0].imag;
1385 | stb_real_t T2 = out[count].real;
1386 | stb_real_t T3 = out[6 * count].real;
1387 | stb_real_t T22 = out[count].imag;
1388 | stb_real_t T23 = out[6 * count].imag;
1389 | stb_real_t T5 = out[2 * count].real;
1390 | stb_real_t T6 = out[5 * count].real;
1391 | stb_real_t T16 = out[2 * count].imag;
1392 | stb_real_t T17 = out[5 * count].imag;
1393 | stb_real_t T8 = out[3 * count].real;
1394 | stb_real_t T9 = out[4 * count].real;
1395 | stb_real_t T19 = out[3 * count].imag;
1396 | stb_real_t T20 = out[4 * count].imag;
1397 | out[0].real = out[0].real + T2 + T3 + T5 + T6 + T8 + T9;
1398 | out[0].imag = T15 + T22 + T23 + T16 + T17 + T19 + T20;
1399 | stb_real_t T25 = STB_KP623489801 * (T16 + T17) + T15 - (STB_KP900968867 * (T22 + T23) + STB_KP222520933 * (T19 + T20));
1400 | out[3 * count].imag = STB_KP974927912 * (T8 - T9)
1401 | + STB_KP433883739 * (T2 - T3)
1402 | - STB_KP781831482 * (T5 - T6)
1403 | + T25;
1404 | out[4 * count].imag = T25
1405 | - (STB_KP974927912 * (T8 - T9)
1406 | + STB_KP433883739 * (T2 - T3)
1407 | - STB_KP781831482 * (T5 - T6));
1408 | stb_real_t T38 = STB_KP974927912 * (T20 - T19) + STB_KP433883739 * (T23 - T22) - STB_KP781831482 * (T17 - T16);
1409 | out[4 * count].real = STB_KP623489801 * (T5 + T6)
1410 | + T1
1411 | - (STB_KP900968867 * (T2 + T3)
1412 | + STB_KP222520933 * (T8 + T9))
1413 | - T38;
1414 | out[3 * count].real = STB_KP623489801 * (T5 + T6)
1415 | + T1
1416 | - (STB_KP900968867 * (T2 + T3)
1417 | + STB_KP222520933 * (T8 + T9))
1418 | + T38;
1419 | stb_real_t T27 = STB_KP623489801 * (T22 + T23) + T15 - (STB_KP222520933 * (T16 + T17) + STB_KP900968867 * (T19 + T20));
1420 | out[count].imag = STB_KP433883739 * (T8 - T9)
1421 | + STB_KP781831482 * (T2 - T3)
1422 | + STB_KP974927912 * (T5 - T6)
1423 | + T27;
1424 | out[6 * count].imag = T27
1425 | - (STB_KP433883739 * (T8 - T9)
1426 | + STB_KP781831482 * (T2 - T3)
1427 | + STB_KP974927912 * (T5 - T6));
1428 | stb_real_t T36 = STB_KP433883739 * (T20 - T19) + STB_KP781831482 * (T23 - T22) + STB_KP974927912 * (T17 - T16);
1429 | out[6 * count].real = STB_KP623489801 * (T2 + T3)
1430 | + T1
1431 | - (STB_KP222520933 * (T5 + T6)
1432 | + STB_KP900968867 * (T8 + T9))
1433 | - T36;
1434 | out[count].real = STB_KP623489801 * (T2 + T3)
1435 | + T1
1436 | - (STB_KP222520933 * (T5 + T6)
1437 | + STB_KP900968867 * (T8 + T9))
1438 | + T36;
1439 | stb_real_t T28 = STB_KP974927912 * (T2 - T3) - STB_KP781831482 * (T8 - T9) - STB_KP433883739 * (T5 - T6);
1440 | stb_real_t T29 = STB_KP623489801 * (T19 + T20) + T15 - (STB_KP222520933 * (T22 + T23) + STB_KP900968867 * (T16 + T17));
1441 | out[2 * count].imag = T28 + T29;
1442 | out[5 * count].imag = T29 - T28;
1443 | stb_real_t T34 = STB_KP974927912 * (T23 - T22) - STB_KP781831482 * (T20 - T19) - STB_KP433883739 * (T17 - T16);
1444 | stb_real_t T30 = STB_KP623489801 * (T8 + T9) + T1 - (STB_KP222520933 * (T2 + T3) + STB_KP900968867 * (T5 + T6));
1445 | out[5 * count].real = T30 - T34;
1446 | out[2 * count].real = T30 + T34;
1447 | output = out + 1;
1448 | m = 1;
1449 | while (m < count) {
1450 | stb_real_t T1_0 = output[0].real;
1451 | stb_real_t T53 = output[0].imag;
1452 | stb_real_t T3_0 = output[count].real;
1453 | stb_real_t T5_0 = output[count].imag;
1454 | stb_real_t T4_0 = tw[0].imag;
1455 | stb_real_t T8_0 = output[6 * count].real;
1456 | stb_real_t T10_0 = output[6 * count].imag;
1457 | stb_real_t T7_0 = tw[5].real;
1458 | stb_real_t T9_0 = tw[5].imag;
1459 | stb_real_t T11_0 = T7_0 * T8_0 - T9_0 * T10_0;
1460 | stb_real_t T12_0 = tw[0].real * T3_0 - T4_0 * T5_0 + T11_0;
1461 | stb_real_t T54 = tw[0].real * T3_0 - T4_0 * T5_0 - T11_0;
1462 | stb_real_t T38_0 = T7_0 * T10_0 + T9_0 * T8_0 - (tw[0].real * T5_0 + T4_0 * T3_0);
1463 | stb_real_t T50 = tw[0].real * T5_0 + T4_0 * T3_0 + T7_0 * T10_0 + T9_0 * T8_0;
1464 | stb_real_t T14_0 = output[2 * count].real;
1465 | stb_real_t T16_0 = output[2 * count].imag;
1466 | stb_real_t T13_0 = tw[1].real;
1467 | stb_real_t T15_0 = tw[1].imag;
1468 | stb_real_t T19_0 = output[5 * count].real;
1469 | stb_real_t T21_0 = output[5 * count].imag;
1470 | stb_real_t T18_0 = tw[4].real;
1471 | stb_real_t T20_0 = tw[4].imag;
1472 | stb_real_t T22_0 = T18_0 * T19_0 - T20_0 * T21_0;
1473 | stb_real_t T23_0 = T13_0 * T14_0 - T15_0 * T16_0 + T22_0;
1474 | stb_real_t T55 = T13_0 * T14_0 - T15_0 * T16_0 - T22_0;
1475 | stb_real_t T44 = T18_0 * T21_0 + T20_0 * T19_0 - (T13_0 * T16_0 + T15_0 * T14_0);
1476 | stb_real_t T51 = T13_0 * T16_0 + T15_0 * T14_0 + T18_0 * T21_0 + T20_0 * T19_0;
1477 | stb_real_t T25_0 = output[3 * count].real;
1478 | stb_real_t T27_0 = output[3 * count].imag;
1479 | stb_real_t T24_0 = tw[2].real;
1480 | stb_real_t T26_0 = tw[2].imag;
1481 | stb_real_t T30_0 = output[4 * count].real;
1482 | stb_real_t T32_0 = output[4 * count].imag;
1483 | stb_real_t T29_0 = tw[3].real;
1484 | stb_real_t T31_0 = tw[3].imag;
1485 | stb_real_t T33_0 = T29_0 * T30_0 - T31_0 * T32_0;
1486 | stb_real_t T34_0 = T24_0 * T25_0 - T26_0 * T27_0 + T33_0;
1487 | stb_real_t T56 = T24_0 * T25_0 - T26_0 * T27_0 - T33_0;
1488 | stb_real_t T41 = T29_0 * T32_0 + T31_0 * T30_0 - (T24_0 * T27_0 + T26_0 * T25_0);
1489 | stb_real_t T52 = T24_0 * T27_0 + T26_0 * T25_0 + T29_0 * T32_0 + T31_0 * T30_0;
1490 | output[0].real = output[0].real + T12_0 + T23_0 + T34_0;
1491 | output[0].imag = T50 + T51 + T52 + T53;
1492 | stb_real_t T45 = STB_KP974927912 * T38_0 - STB_KP781831482 * T41 - STB_KP433883739 * T44;
1493 | output[5 * count].real = STB_KP623489801 * T34_0
1494 | + T1_0
1495 | - (STB_KP222520933 * T12_0
1496 | + STB_KP900968867 * T23_0)
1497 | - T45;
1498 | output[2 * count].real = STB_KP623489801 * T34_0
1499 | + T1_0
1500 | - (STB_KP222520933 * T12_0
1501 | + STB_KP900968867 * T23_0)
1502 | + T45;
1503 | stb_real_t T60 = STB_KP623489801 * T52 + T53 - (STB_KP222520933 * T50 + STB_KP900968867 * T51);
1504 | output[2 * count].imag = STB_KP974927912 * T54 - STB_KP781831482 * T56 - STB_KP433883739 * T55 + T60;
1505 | output[5 * count].imag = T60 - (STB_KP974927912 * T54 - STB_KP781831482 * T56 - STB_KP433883739 * T55);
1506 | stb_real_t T47 = STB_KP433883739 * T41 + STB_KP781831482 * T38_0 + STB_KP974927912 * T44;
1507 | output[6 * count].real = STB_KP623489801 * T12_0
1508 | + T1_0
1509 | - (STB_KP222520933 * T23_0
1510 | + STB_KP900968867 * T34_0)
1511 | - T47;
1512 | output[count].real = STB_KP623489801 * T12_0
1513 | + T1_0
1514 | - (STB_KP222520933 * T23_0
1515 | + STB_KP900968867 * T34_0)
1516 | + T47;
1517 | stb_real_t T58 = STB_KP623489801 * T50 + T53 - (STB_KP222520933 * T51 + STB_KP900968867 * T52);
1518 | output[count].imag = STB_KP433883739 * T56 + STB_KP781831482 * T54 + STB_KP974927912 * T55 + T58;
1519 | output[6 * count].imag = T58 - (STB_KP433883739 * T56 + STB_KP781831482 * T54 + STB_KP974927912 * T55);
1520 | stb_real_t T49 = STB_KP974927912 * T41 + STB_KP433883739 * T38_0 - STB_KP781831482 * T44;
1521 | output[4 * count].real = STB_KP623489801 * T23_0
1522 | + T1_0
1523 | - (STB_KP900968867 * T12_0
1524 | + STB_KP222520933 * T34_0)
1525 | - T49;
1526 | output[3 * count].real = STB_KP623489801 * T23_0
1527 | + T1_0
1528 | - (STB_KP900968867 * T12_0
1529 | + STB_KP222520933 * T34_0)
1530 | + T49;
1531 | stb_real_t T62 = STB_KP623489801 * T51 + T53 - (STB_KP900968867 * T50 + STB_KP222520933 * T52);
1532 | output[3 * count].imag = STB_KP974927912 * T56 + STB_KP433883739 * T54 - STB_KP781831482 * T55 + T62;
1533 | output[4 * count].imag = T62
1534 | - (STB_KP974927912 * T56
1535 | + STB_KP433883739 * T54
1536 | - STB_KP781831482 * T55);
1537 | ++m;
1538 | ++output;
1539 | tw += 6;
1540 | }
1541 | }
1542 |
1543 | void stb_radix_8_idit(const cmplx* tw, cmplx* out, int count)
1544 | {
1545 | int m;
1546 | cmplx* output;
1547 | stb_real_t T2 = out[4 * count].real;
1548 | stb_real_t T3 = out[0].real + T2;
1549 | stb_real_t T37 = out[0].real - T2;
1550 | stb_real_t T16 = out[0].imag;
1551 | stb_real_t T17 = out[4 * count].imag;
1552 | stb_real_t T4 = out[2 * count].real;
1553 | stb_real_t T5 = out[6 * count].real;
1554 | stb_real_t T19 = out[2 * count].imag;
1555 | stb_real_t T20 = out[6 * count].imag;
1556 | stb_real_t T11 = out[7 * count].real;
1557 | stb_real_t T12 = out[3 * count].real;
1558 | stb_real_t T32 = out[7 * count].imag;
1559 | stb_real_t T33 = out[3 * count].imag;
1560 | stb_real_t T35 = T11 - T12 + T32 - T33;
1561 | stb_real_t T43 = T32 - T33 - (T11 - T12);
1562 | stb_real_t T8 = out[count].real;
1563 | stb_real_t T9 = out[5 * count].real;
1564 | stb_real_t T27 = out[count].imag;
1565 | stb_real_t T28 = out[5 * count].imag;
1566 | stb_real_t T30 = T8 - T9 - (T27 - T28);
1567 | stb_real_t T42 = T8 - T9 + T27 - T28;
1568 | stb_real_t T7 = T3 + T4 + T5;
1569 | stb_real_t T14 = T8 + T9 + T11 + T12;
1570 | out[4 * count].real = T7 - T14;
1571 | out[0].real = T7 + T14;
1572 | out[4 * count].imag = T16 + T17 + T19 + T20 - (T27 + T28 + T32 + T33);
1573 | out[0].imag = T16 + T17 + T19 + T20 + T27 + T28 + T32 + T33;
1574 | stb_real_t T15 = T8 + T9 - (T11 + T12);
1575 | stb_real_t T22 = T16 + T17 - (T19 + T20);
1576 | out[2 * count].imag = T15 + T22;
1577 | out[6 * count].imag = T22 - T15;
1578 | stb_real_t T51 = T3 - (T4 + T5);
1579 | stb_real_t T52 = T32 + T33 - (T27 + T28);
1580 | out[6 * count].real = T51 - T52;
1581 | out[2 * count].real = T51 + T52;
1582 | stb_real_t T36 = (T30 - T35) * STB_KP707106781;
1583 | out[7 * count].imag = T16 - T17 - (T4 - T5) - T36;
1584 | out[3 * count].imag = T16 - T17 - (T4 - T5) + T36;
1585 | stb_real_t T46 = (T43 - T42) * STB_KP707106781;
1586 | out[7 * count].real = T37 + T19 - T20 - T46;
1587 | out[3 * count].real = T37 + T19 - T20 + T46;
1588 | stb_real_t T39 = T37 - (T19 - T20);
1589 | stb_real_t T40 = (T30 + T35) * STB_KP707106781;
1590 | out[5 * count].real = T39 - T40;
1591 | out[count].real = T39 + T40;
1592 | stb_real_t T41 = T4 - T5 + T16 - T17;
1593 | stb_real_t T44 = (T42 + T43) * STB_KP707106781;
1594 | out[5 * count].imag = T41 - T44;
1595 | out[count].imag = T41 + T44;
1596 | output = out + 1;
1597 | m = 1;
1598 | while (m < count) {
1599 | stb_real_t T70 = output[0].imag;
1600 | stb_real_t T3_0 = output[4 * count].real;
1601 | stb_real_t T5_0 = output[4 * count].imag;
1602 | stb_real_t T2_0 = tw[3].real;
1603 | stb_real_t T4_0 = tw[3].imag;
1604 | stb_real_t T6_0 = T2_0 * T3_0 - T4_0 * T5_0;
1605 | stb_real_t T7_0 = output[0].real + T6_0;
1606 | stb_real_t T77 = T70 - (T2_0 * T5_0 + T4_0 * T3_0);
1607 | stb_real_t T43_0 = output[0].real - T6_0;
1608 | stb_real_t T71 = T2_0 * T5_0 + T4_0 * T3_0 + T70;
1609 | stb_real_t T32_0 = output[7 * count].real;
1610 | stb_real_t T34_0 = output[7 * count].imag;
1611 | stb_real_t T31_0 = tw[6].real;
1612 | stb_real_t T33_0 = tw[6].imag;
1613 | stb_real_t T37_0 = output[3 * count].real;
1614 | stb_real_t T39_0 = output[3 * count].imag;
1615 | stb_real_t T36_0 = tw[2].real;
1616 | stb_real_t T38_0 = tw[2].imag;
1617 | stb_real_t T40_0 = T36_0 * T37_0 - T38_0 * T39_0;
1618 | stb_real_t T55 = T36_0 * T39_0 + T38_0 * T37_0;
1619 | stb_real_t T41_0 = T31_0 * T32_0 - T33_0 * T34_0 + T40_0;
1620 | stb_real_t T64 = T31_0 * T34_0 + T33_0 * T32_0 + T55;
1621 | stb_real_t T53 = T31_0 * T32_0 - T33_0 * T34_0 - T40_0;
1622 | stb_real_t T56 = T31_0 * T34_0 + T33_0 * T32_0 - T55;
1623 | stb_real_t T9_0 = output[2 * count].real;
1624 | stb_real_t T11_0 = output[2 * count].imag;
1625 | stb_real_t T8_0 = tw[1].real;
1626 | stb_real_t T10_0 = tw[1].imag;
1627 | stb_real_t T14_0 = output[6 * count].real;
1628 | stb_real_t T16_0 = output[6 * count].imag;
1629 | stb_real_t T13_0 = tw[5].real;
1630 | stb_real_t T15_0 = tw[5].imag;
1631 | stb_real_t T17_0 = T13_0 * T14_0 - T15_0 * T16_0;
1632 | stb_real_t T45_0 = T13_0 * T16_0 + T15_0 * T14_0;
1633 | stb_real_t T18_0 = T8_0 * T9_0 - T10_0 * T11_0 + T17_0;
1634 | stb_real_t T76 = T8_0 * T9_0 - T10_0 * T11_0 - T17_0;
1635 | stb_real_t T46_0 = T8_0 * T11_0 + T10_0 * T9_0 - T45_0;
1636 | stb_real_t T68 = T8_0 * T11_0 + T10_0 * T9_0 + T45_0;
1637 | stb_real_t T21_0 = output[count].real;
1638 | stb_real_t T23_0 = output[count].imag;
1639 | stb_real_t T22_0 = tw[0].imag;
1640 | stb_real_t T26_0 = output[5 * count].real;
1641 | stb_real_t T28_0 = output[5 * count].imag;
1642 | stb_real_t T25_0 = tw[4].real;
1643 | stb_real_t T27_0 = tw[4].imag;
1644 | stb_real_t T29_0 = T25_0 * T26_0 - T27_0 * T28_0;
1645 | stb_real_t T50_0 = T25_0 * T28_0 + T27_0 * T26_0;
1646 | stb_real_t T30_0 = tw[0].real * T21_0 - T22_0 * T23_0 + T29_0;
1647 | stb_real_t T65 = tw[0].real * T23_0 + T22_0 * T21_0 + T50_0;
1648 | stb_real_t T48_0 = tw[0].real * T21_0 - T22_0 * T23_0 - T29_0;
1649 | stb_real_t T51_0 = tw[0].real * T23_0 + T22_0 * T21_0 - T50_0;
1650 | stb_real_t T19_0 = T7_0 + T18_0;
1651 | stb_real_t T42_0 = T30_0 + T41_0;
1652 | output[4 * count].real = T19_0 - T42_0;
1653 | output[0].real = T19_0 + T42_0;
1654 | output[0].imag = T65 + T64 + T68 + T71;
1655 | output[4 * count].imag = T68 + T71 - (T65 + T64);
1656 | output[6 * count].real = T7_0 - T18_0 - (T64 - T65);
1657 | output[2 * count].real = T7_0 - T18_0 + T64 - T65;
1658 | output[2 * count].imag = T30_0 - T41_0 + T71 - T68;
1659 | output[6 * count].imag = T71 - T68 - (T30_0 - T41_0);
1660 | stb_real_t T62 = (T56 - T53 - (T48_0 + T51_0)) * STB_KP707106781;
1661 | stb_real_t T75 = (T48_0 + T51_0 + T56 - T53) * STB_KP707106781;
1662 | output[7 * count].real = T43_0 + T46_0 - T62;
1663 | output[5 * count].imag = T76 + T77 - T75;
1664 | output[3 * count].real = T43_0 + T46_0 + T62;
1665 | output[count].imag = T75 + T76 + T77;
1666 | stb_real_t T58 = (T48_0 - T51_0 + T53 + T56) * STB_KP707106781;
1667 | stb_real_t T79 = (T48_0 - T51_0 - (T53 + T56)) * STB_KP707106781;
1668 | output[5 * count].real = T43_0 - T46_0 - T58;
1669 | output[7 * count].imag = T77 - T76 - T79;
1670 | output[count].real = T43_0 - T46_0 + T58;
1671 | output[3 * count].imag = T79 + T77 - T76;
1672 | ++m;
1673 | ++output;
1674 | tw += 7;
1675 | }
1676 | }
1677 |
1678 | void stb_recursive_mixed_radix_dit(const stb_fft_plan* plan, int stage, cmplx* in, cmplx* out, int sign)
1679 | {
1680 | const int radix = plan->stages.radix[stage];
1681 | const int count = plan->stages.remainder[stage];
1682 | cmplx* twiddles = plan->twiddles;
1683 | const int tw_offset = plan->stages.offsets[stage];
1684 | cmplx* tw_sequential = &plan->twiddles_ordered[tw_offset];
1685 | if (count == 1) {
1686 | for (int i = 0; i < radix; i++) {
1687 | out[i] = in[i * sign];
1688 | }
1689 | } else {
1690 | const int cur_sign = sign * radix;
1691 | for (int i = 0; i < radix; ++i) {
1692 | stb_recursive_mixed_radix_dit(plan, stage + 1, &in[sign * i], &out[count * i], cur_sign);
1693 | }
1694 | }
1695 | switch (radix) {
1696 | case 2:
1697 | stb_radix_2_dit(tw_sequential, out, count);
1698 | break;
1699 | case 3:
1700 | stb_radix_3_dit(tw_sequential, out, count);
1701 | break;
1702 | case 4:
1703 | stb_radix_4_dit(tw_sequential, out, count);
1704 | break;
1705 | case 5:
1706 | stb_radix_5_dit(tw_sequential, out, count);
1707 | break;
1708 | case 6:
1709 | stb_radix_6_dit(tw_sequential, out, count);
1710 | break;
1711 | case 7:
1712 | stb_radix_7_dit(tw_sequential, out, count);
1713 | break;
1714 | case 8:
1715 | stb_radix_8_dit(tw_sequential, out, count);
1716 | break;
1717 | default:
1718 | stb_general_dit(twiddles, out, count, sign, radix, plan->N, 0);
1719 | break;
1720 | }
1721 | }
1722 |
1723 | void stb_recursive_mixed_radix_idit(const stb_fft_plan* plan, int stage, cmplx* in, cmplx* out, int sign)
1724 | {
1725 | const int radix = plan->stages.radix[stage];
1726 | const int count = plan->stages.remainder[stage];
1727 | cmplx* twiddles = plan->twiddles;
1728 | const int tw_offset = plan->stages.offsets[stage];
1729 | cmplx* tw_sequential = &plan->twiddles_ordered[tw_offset];
1730 | if (count == 1) {
1731 | for (int i = 0; i < radix; i++) {
1732 | out[i] = in[i * sign];
1733 | }
1734 | } else {
1735 | const int cur_sign = sign * radix;
1736 | for (int i = 0; i < radix; ++i) {
1737 | stb_recursive_mixed_radix_idit(plan, stage + 1, &in[sign * i], &out[count * i],
1738 | cur_sign);
1739 | }
1740 | }
1741 | switch (radix) {
1742 | case 2:
1743 | stb_radix_2_idit(tw_sequential, out, count);
1744 | break;
1745 | case 3:
1746 | stb_radix_3_idit(tw_sequential, out, count);
1747 | break;
1748 | case 4:
1749 | stb_radix_4_idit(tw_sequential, out, count);
1750 | break;
1751 | case 5:
1752 | stb_radix_5_idit(tw_sequential, out, count);
1753 | break;
1754 | case 6:
1755 | stb_radix_6_idit(tw_sequential, out, count);
1756 | break;
1757 | case 7:
1758 | stb_radix_7_idit(tw_sequential, out, count);
1759 | break;
1760 | case 8:
1761 | stb_radix_8_idit(tw_sequential, out, count);
1762 | break;
1763 | default:
1764 | stb_general_dit(twiddles, out, count, sign, radix, plan->N, 1);
1765 | break;
1766 | }
1767 | }
1768 |
1769 | void stb_fft_exec(const stb_fft_plan* plan, cmplx* in, cmplx* out)
1770 | {
1771 | if (in == out) {
1772 | cmplx* buf = (cmplx*)calloc(plan->N, sizeof(cmplx));
1773 | if (buf == NULL)
1774 | return;
1775 | stb_recursive_mixed_radix_dit(plan, 0, in, buf, 1);
1776 | memcpy(out, buf, sizeof(cmplx) * plan->N);
1777 | free(buf);
1778 | } else {
1779 | stb_recursive_mixed_radix_dit(plan, 0, in, out, 1);
1780 | }
1781 | }
1782 |
1783 | void stb_ifft_exec(const stb_fft_plan* plan, cmplx* in, cmplx* out)
1784 | {
1785 | if (in == out) {
1786 | cmplx* buf = (cmplx*)calloc(plan->N, sizeof(cmplx));
1787 | if (buf == NULL)
1788 | return;
1789 | stb_recursive_mixed_radix_idit(plan, 0, in, buf, 1);
1790 | memcpy(out, buf, sizeof(cmplx) * plan->N);
1791 | free(buf);
1792 | } else {
1793 | stb_recursive_mixed_radix_idit(plan, 0, in, out, 1);
1794 | }
1795 | }
1796 |
1797 | void stb_fft_r2c_exec(stb_fft_real_plan* plan, const stb_real_t* input, cmplx* output)
1798 | {
1799 | int n = plan->half_plan->N;
1800 | stb_fft_exec(plan->half_plan, (cmplx*)input, plan->buffer);
1801 | cmplx tdc = plan->buffer[0];
1802 | output[0].real = tdc.imag + tdc.real;
1803 | output[n].real = tdc.real - tdc.imag;
1804 | output[0].imag = 0.0;
1805 | output[n].imag = output[0].imag;
1806 | for (int c = 1; c <= n / 2; ++c) {
1807 | cmplx t = plan->buffer[n - c];
1808 | t.imag = -t.imag;
1809 | stb_real_t r = (plan->twiddles[c - 1].real * (plan->buffer[c].real - t.real)) - (plan->twiddles[c - 1].imag * (plan->buffer[c].imag - t.imag));
1810 | stb_real_t i = (plan->twiddles[c - 1].real * (plan->buffer[c].imag - t.imag)) + ((plan->buffer[c].real - t.real) * plan->twiddles[c - 1].imag);
1811 | output[c].real = (r + (t.real + plan->buffer[c].real)) * STB_KP5;
1812 | output[c].imag = (i + (t.imag + plan->buffer[c].imag)) * STB_KP5;
1813 | output[n - c].real = ((t.real + plan->buffer[c].real) - r) * STB_KP5;
1814 | output[n - c].imag = (i - (t.imag + plan->buffer[c].imag)) * STB_KP5;
1815 | }
1816 | }
1817 |
1818 | void stb_fft_c2r_exec(stb_fft_real_plan* plan, const cmplx* input, stb_real_t* output)
1819 | {
1820 | int n = plan->half_plan->N;
1821 | plan->buffer[0].real = input[n].real + input[0].real;
1822 | plan->buffer[0].imag = input[0].real - input[n].real;
1823 | for (int c = 1; c <= n / 2; ++c) {
1824 | cmplx t = input[n - c];
1825 | t.imag = -t.imag;
1826 | stb_real_t r = (plan->twiddles[c - 1].real * (input[c].real - t.real)) + (plan->twiddles[c - 1].imag * (input[c].imag - t.imag));
1827 | stb_real_t i = (plan->twiddles[c - 1].real * (input[c].imag - t.imag)) - ((input[c].real - t.real) * plan->twiddles[c - 1].imag);
1828 | plan->buffer[c].real = (r + t.real + input[c].real);
1829 | plan->buffer[c].imag = (i + t.imag + input[c].imag);
1830 | plan->buffer[n - c].real = (t.real + input[c].real - r);
1831 | plan->buffer[n - c].imag = (i - t.imag - input[c].imag);
1832 | }
1833 | stb_ifft_exec(plan->half_plan, plan->buffer, (cmplx*)output);
1834 | }
1835 |
1836 | void STB_FFT(cmplx* input, cmplx* output, int n)
1837 | {
1838 | if (n < 2) {
1839 | output[0] = input[0];
1840 | return;
1841 | }
1842 | stb_fft_plan* plan = stb_fft_plan_dft_1d(n);
1843 | if (plan != NULL) {
1844 | stb_fft_exec(plan, input, output);
1845 | free(plan);
1846 | }
1847 | }
1848 |
1849 | void STB_IFFT(cmplx* input, cmplx* output, int n)
1850 | {
1851 | if (n < 2) {
1852 | output[0] = input[0];
1853 | return;
1854 | }
1855 | stb_fft_plan* plan = stb_fft_plan_dft_1d(n);
1856 | if (plan != NULL) {
1857 | stb_ifft_exec(plan, input, output);
1858 | free(plan);
1859 | }
1860 | }
1861 |
1862 | void STB_FFT_R2C(stb_real_t* input, cmplx* output, int n)
1863 | {
1864 | if (n < 2) {
1865 | output[0].real = input[0];
1866 | return;
1867 | }
1868 | stb_fft_real_plan* stb_fft_plan = stb_fft_real_plan_dft_1d(n);
1869 | if (stb_fft_plan != NULL) {
1870 | stb_fft_r2c_exec(stb_fft_plan, input, output);
1871 | free(stb_fft_plan);
1872 | }
1873 | }
1874 |
1875 | void STB_IFFT_C2R(cmplx* input, stb_real_t* output, int n)
1876 | {
1877 | if (n < 2) {
1878 | output[0] = input[0].real;
1879 | return;
1880 | }
1881 | stb_fft_real_plan* stb_fft_plan = stb_fft_real_plan_dft_1d(n);
1882 | if (stb_fft_plan != NULL) {
1883 | stb_fft_c2r_exec(stb_fft_plan, input, output);
1884 | free(stb_fft_plan);
1885 | }
1886 | }
1887 |
1888 | #endif
1889 |
1890 | // REVISION HISTORY
1891 | // v0.11 - 2018-12-28
1892 | // - Initial versioned release.
1893 |
1894 | /*
1895 | This is free and unencumbered software released into the public domain.
1896 | Anyone is free to copy, modify, publish, use, compile, sell, or
1897 | distribute this software, either in source code form or as a compiled
1898 | binary, for any purpose, commercial or non-commercial, and by any
1899 | means.
1900 | In jurisdictions that recognize copyright laws, the author or authors
1901 | of this software dedicate any and all copyright interest in the
1902 | software to the public domain. We make this dedication for the benefit
1903 | of the public at large and to the detriment of our heirs and
1904 | successors. We intend this dedication to be an overt act of
1905 | relinquishment in perpetuity of all present and future rights to this
1906 | software under copyright law.
1907 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1908 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1909 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1910 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
1911 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1912 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1913 | OTHER DEALINGS IN THE SOFTWARE.
1914 | For more information, please refer to
1915 | */
--------------------------------------------------------------------------------
/timing.h:
--------------------------------------------------------------------------------
1 |
2 | #include
3 |
4 | #if defined(__APPLE__)
5 | # include
6 | #elif defined(_WIN32)
7 | # define WIN32_LEAN_AND_MEAN
8 |
9 | # include
10 |
11 | #else // __linux
12 |
13 | # include
14 |
15 | # ifndef CLOCK_MONOTONIC //_RAW
16 | # define CLOCK_MONOTONIC CLOCK_REALTIME
17 | # endif
18 | #endif
19 |
20 | static
21 | uint64_t nanotimer() {
22 | static int ever = 0;
23 | #if defined(__APPLE__)
24 | static mach_timebase_info_data_t frequency;
25 | if (!ever) {
26 | if (mach_timebase_info(&frequency) != KERN_SUCCESS) {
27 | return 0;
28 | }
29 | ever = 1;
30 | }
31 | return (mach_absolute_time() * frequency.numer / frequency.denom);
32 | #elif defined(_WIN32)
33 | static LARGE_INTEGER frequency;
34 | if (!ever) {
35 | QueryPerformanceFrequency(&frequency);
36 | ever = 1;
37 | }
38 | LARGE_INTEGER t;
39 | QueryPerformanceCounter(&t);
40 | return (t.QuadPart * (uint64_t) 1e9) / frequency.QuadPart;
41 | #else // __linux
42 | struct timespec t;
43 | if (!ever) {
44 | if (clock_gettime(CLOCK_MONOTONIC, &t) != 0) {
45 | return 0;
46 | }
47 | ever = 1;
48 | }
49 | clock_gettime(CLOCK_MONOTONIC, &t);
50 | return (t.tv_sec * (uint64_t) 1e9) + t.tv_nsec;
51 | #endif
52 | }
53 |
54 |
55 | static double now() {
56 | static uint64_t epoch = 0;
57 | if (!epoch) {
58 | epoch = nanotimer();
59 | }
60 | return (nanotimer() - epoch) / 1e9;
61 | };
62 |
63 | static double calcElapsed(double start, double end) {
64 | double took = -start;
65 | return took + end;
66 | }
--------------------------------------------------------------------------------