diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2010-06-03 08:55:36 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2010-06-03 08:55:36 +0000 |
commit | e0af34cb5f42cb4c6c76cac14677de1f896c5b06 (patch) | |
tree | f80883366b56373c7bc6f3aa843dbafd31b36cc9 | |
parent | 6feac4a315574b9cc037a328018e6ba9398a77d5 (diff) | |
download | rockbox-e0af34cb5f42cb4c6c76cac14677de1f896c5b06.tar.gz rockbox-e0af34cb5f42cb4c6c76cac14677de1f896c5b06.zip |
More FFT fun: No point in computing and combining the 2nd FFT if it's just being made null. Use the regular complex FFT (called by fftr anyway) and save ram and computation for a given number of bins.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26507 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/plugins/fft/fft.c | 66 |
1 files changed, 28 insertions, 38 deletions
diff --git a/apps/plugins/fft/fft.c b/apps/plugins/fft/fft.c index dc118ec0c1..28e775a9c1 100644 --- a/apps/plugins/fft/fft.c +++ b/apps/plugins/fft/fft.c | |||
@@ -247,18 +247,14 @@ GREY_INFO_STRUCT | |||
247 | #include "_kiss_fft_guts.h" /* sizeof(struct kiss_fft_state) */ | 247 | #include "_kiss_fft_guts.h" /* sizeof(struct kiss_fft_state) */ |
248 | #include "const.h" | 248 | #include "const.h" |
249 | 249 | ||
250 | #if (LCD_WIDTH < LCD_HEIGHT) | 250 | #define LCD_SIZE MAX(LCD_WIDTH, LCD_HEIGHT) |
251 | #define LCD_SIZE LCD_HEIGHT | ||
252 | #else | ||
253 | #define LCD_SIZE LCD_WIDTH | ||
254 | #endif | ||
255 | 251 | ||
256 | #if (LCD_SIZE < 512) | 252 | #if (LCD_SIZE <= 511) |
257 | #define FFT_SIZE 2048 /* 512*4 */ | 253 | #define FFT_SIZE 1024 /* 512*2 */ |
258 | #elif (LCD_SIZE < 1024) | 254 | #elif (LCD_SIZE <= 1023) |
259 | #define FFT_SIZE 4096 /* 1024*4 */ | 255 | #define FFT_SIZE 2048 /* 1024*2 */ |
260 | #else | 256 | #else |
261 | #define FFT_SIZE 8192 /* 2048*4 */ | 257 | #define FFT_SIZE 4096 /* 2048*2 */ |
262 | #endif | 258 | #endif |
263 | 259 | ||
264 | #ifdef HAVE_LCD_COLOR | 260 | #ifdef HAVE_LCD_COLOR |
@@ -272,14 +268,9 @@ GREY_INFO_STRUCT | |||
272 | #endif | 268 | #endif |
273 | 269 | ||
274 | #define ARRAYLEN_IN (FFT_SIZE) | 270 | #define ARRAYLEN_IN (FFT_SIZE) |
275 | #define ARRAYLEN_OUT (FFT_SIZE/2) | 271 | #define ARRAYLEN_OUT (FFT_SIZE) |
276 | #define ARRAYLEN_PLOT ((FFT_SIZE/4)-1) /* -1 to ignore DC bin */ | 272 | #define ARRAYLEN_PLOT (FFT_SIZE/2-1) /* FFT is symmetric, ignore DC */ |
277 | #define BUFSIZE_FFT (sizeof(struct kiss_fft_state)+sizeof(kiss_fft_cpx)*(FFT_SIZE-1)) | 273 | #define BUFSIZE_FFT (sizeof(struct kiss_fft_state)+sizeof(kiss_fft_cpx)*(FFT_SIZE-1)) |
278 | #define BUFSIZE_FFTR (BUFSIZE_FFT+sizeof(struct kiss_fftr_state)+sizeof(kiss_fft_cpx)*(FFT_SIZE*3/2)) | ||
279 | #define BUFSIZE BUFSIZE_FFTR | ||
280 | #define FFT_ALLOC kiss_fftr_alloc | ||
281 | #define FFT_FFT kiss_fftr | ||
282 | #define FFT_CFG kiss_fftr_cfg | ||
283 | 274 | ||
284 | #define __COEFF(type,size) type##_##size | 275 | #define __COEFF(type,size) type##_##size |
285 | #define _COEFF(x, y) __COEFF(x,y) /* force the preprocessor to evaluate FFT_SIZE) */ | 276 | #define _COEFF(x, y) __COEFF(x,y) /* force the preprocessor to evaluate FFT_SIZE) */ |
@@ -294,28 +285,28 @@ GREY_INFO_STRUCT | |||
294 | (CACHEALIGN_UP((len)*sizeof(type) + (sizeof(type)-1)) / sizeof(type)) | 285 | (CACHEALIGN_UP((len)*sizeof(type) + (sizeof(type)-1)) / sizeof(type)) |
295 | /* Shared */ | 286 | /* Shared */ |
296 | /* COP + CPU PCM */ | 287 | /* COP + CPU PCM */ |
297 | static kiss_fft_scalar input[CACHEALIGN_UP_SIZE(kiss_fft_scalar, ARRAYLEN_IN)] | 288 | static kiss_fft_cpx input[CACHEALIGN_UP_SIZE(kiss_fft_scalar, ARRAYLEN_IN)] |
298 | CACHEALIGN_AT_LEAST_ATTR(4); | 289 | CACHEALIGN_AT_LEAST_ATTR(4); |
299 | /* CPU+COP */ | 290 | /* CPU+COP */ |
300 | #if NUM_CORES > 1 | 291 | #if NUM_CORES > 1 |
301 | /* Output queue indexes */ | 292 | /* Output queue indexes */ |
302 | static volatile int output_head SHAREDBSS_ATTR = 0; | 293 | static volatile int output_head SHAREDBSS_ATTR = 0; |
303 | static volatile int output_tail SHAREDBSS_ATTR = 0; | 294 | static volatile int output_tail SHAREDBSS_ATTR = 0; |
304 | /* The result is nfft/2+1 complex frequency bins from DC to Nyquist. */ | 295 | /* The result is nfft/2 complex frequency bins from DC to Nyquist. */ |
305 | static kiss_fft_cpx output[2][CACHEALIGN_UP_SIZE(kiss_fft_cpx, ARRAYLEN_OUT+1)] | 296 | static kiss_fft_cpx output[2][CACHEALIGN_UP_SIZE(kiss_fft_cpx, ARRAYLEN_OUT)] |
306 | SHAREDBSS_ATTR; | 297 | SHAREDBSS_ATTR; |
307 | #else | 298 | #else |
308 | /* Only one output buffer */ | 299 | /* Only one output buffer */ |
309 | #define output_head 0 | 300 | #define output_head 0 |
310 | #define output_tail 0 | 301 | #define output_tail 0 |
311 | /* The result is nfft/2+1 complex frequency bins from DC to Nyquist. */ | 302 | /* The result is nfft/2 complex frequency bins from DC to Nyquist. */ |
312 | static kiss_fft_cpx output[1][ARRAYLEN_OUT+1]; | 303 | static kiss_fft_cpx output[1][ARRAYLEN_OUT]; |
313 | #endif | 304 | #endif |
314 | 305 | ||
315 | /* Unshared */ | 306 | /* Unshared */ |
316 | /* COP */ | 307 | /* COP */ |
317 | static FFT_CFG fft_state SHAREDBSS_ATTR; | 308 | static kiss_fft_cfg fft_state SHAREDBSS_ATTR; |
318 | static char buffer[CACHEALIGN_UP_SIZE(char, BUFSIZE)] | 309 | static char fft_buffer[CACHEALIGN_UP_SIZE(char, BUFSIZE_FFT)] |
319 | CACHEALIGN_AT_LEAST_ATTR(4); | 310 | CACHEALIGN_AT_LEAST_ATTR(4); |
320 | /* CPU */ | 311 | /* CPU */ |
321 | static int32_t plot_history[ARRAYLEN_PLOT]; | 312 | static int32_t plot_history[ARRAYLEN_PLOT]; |
@@ -399,10 +390,10 @@ static struct { | |||
399 | 390 | ||
400 | /************************* Math functions *************************/ | 391 | /************************* Math functions *************************/ |
401 | 392 | ||
402 | /* Based on playing back a 0dB sweep tone */ | 393 | /* Based on feeding-in a 0db sinewave at FS/4 */ |
403 | #define QLOG_MAX 0x000865EF | 394 | #define QLOG_MAX 0x0009154B |
404 | /* fudge it a little or it's not very visbile */ | 395 | /* fudge it a little or it's not very visbile */ |
405 | #define QLIN_MAX (0x00001157 >> 1) | 396 | #define QLIN_MAX (0x00002266 >> 1) |
406 | 397 | ||
407 | /* Apply window function to input */ | 398 | /* Apply window function to input */ |
408 | static void apply_window_func(enum fft_window_func mode) | 399 | static void apply_window_func(enum fft_window_func mode) |
@@ -414,14 +405,14 @@ static void apply_window_func(enum fft_window_func mode) | |||
414 | case FFT_WF_HAMMING: | 405 | case FFT_WF_HAMMING: |
415 | for(i = 0; i < ARRAYLEN_IN; ++i) | 406 | for(i = 0; i < ARRAYLEN_IN; ++i) |
416 | { | 407 | { |
417 | input[i] = (input[i] * HAMMING_COEFF[i] + 16384) >> 15; | 408 | input[i].r = (input[i].r * HAMMING_COEFF[i] + 16384) >> 15; |
418 | } | 409 | } |
419 | break; | 410 | break; |
420 | 411 | ||
421 | case FFT_WF_HANN: | 412 | case FFT_WF_HANN: |
422 | for(i = 0; i < ARRAYLEN_IN; ++i) | 413 | for(i = 0; i < ARRAYLEN_IN; ++i) |
423 | { | 414 | { |
424 | input[i] = (input[i] * HANN_COEFF[i] + 16384) >> 15; | 415 | input[i].r = (input[i].r * HANN_COEFF[i] + 16384) >> 15; |
425 | } | 416 | } |
426 | break; | 417 | break; |
427 | } | 418 | } |
@@ -1135,8 +1126,8 @@ static void draw_spectrogram_horizontal(void) | |||
1135 | /** functions use in single/multi configuration **/ | 1126 | /** functions use in single/multi configuration **/ |
1136 | static inline bool fft_init_fft_lib(void) | 1127 | static inline bool fft_init_fft_lib(void) |
1137 | { | 1128 | { |
1138 | size_t size = sizeof(buffer); | 1129 | size_t size = sizeof(fft_buffer); |
1139 | fft_state = FFT_ALLOC(FFT_SIZE, 0, buffer, &size); | 1130 | fft_state = kiss_fft_alloc(FFT_SIZE, 0, fft_buffer, &size); |
1140 | 1131 | ||
1141 | if(fft_state == NULL) | 1132 | if(fft_state == NULL) |
1142 | { | 1133 | { |
@@ -1159,12 +1150,12 @@ static inline bool fft_get_fft(void) | |||
1159 | * do a proper spectrum analysis.*/ | 1150 | * do a proper spectrum analysis.*/ |
1160 | 1151 | ||
1161 | /* there are cases when we don't have enough data to fill the buffer */ | 1152 | /* there are cases when we don't have enough data to fill the buffer */ |
1162 | if(count != ARRAYLEN_IN/2) | 1153 | if(count != ARRAYLEN_IN) |
1163 | { | 1154 | { |
1164 | if(count < ARRAYLEN_IN/2) | 1155 | if(count < ARRAYLEN_IN) |
1165 | return false; | 1156 | return false; |
1166 | 1157 | ||
1167 | count = ARRAYLEN_IN/2; /* too much - limit */ | 1158 | count = ARRAYLEN_IN; /* too much - limit */ |
1168 | } | 1159 | } |
1169 | 1160 | ||
1170 | int fft_idx = 0; /* offset in 'input' */ | 1161 | int fft_idx = 0; /* offset in 'input' */ |
@@ -1173,15 +1164,14 @@ static inline bool fft_get_fft(void) | |||
1173 | { | 1164 | { |
1174 | kiss_fft_scalar left = *value++; | 1165 | kiss_fft_scalar left = *value++; |
1175 | kiss_fft_scalar right = *value++; | 1166 | kiss_fft_scalar right = *value++; |
1176 | input[fft_idx++] = (left + right) >> 1; /* to mono */ | 1167 | input[fft_idx].r = (left + right) >> 1; /* to mono */ |
1177 | input[fft_idx++] = 0; | 1168 | } while (fft_idx++, --count > 0); |
1178 | } while (--count > 0); | ||
1179 | 1169 | ||
1180 | apply_window_func(graph_settings.window_func); | 1170 | apply_window_func(graph_settings.window_func); |
1181 | 1171 | ||
1182 | rb->yield(); | 1172 | rb->yield(); |
1183 | 1173 | ||
1184 | FFT_FFT(fft_state, input, output[output_tail]); | 1174 | kiss_fft(fft_state, input, output[output_tail]); |
1185 | 1175 | ||
1186 | rb->yield(); | 1176 | rb->yield(); |
1187 | 1177 | ||