summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-06-03 08:55:36 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-06-03 08:55:36 +0000
commite0af34cb5f42cb4c6c76cac14677de1f896c5b06 (patch)
treef80883366b56373c7bc6f3aa843dbafd31b36cc9
parent6feac4a315574b9cc037a328018e6ba9398a77d5 (diff)
downloadrockbox-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.c66
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 */
297static kiss_fft_scalar input[CACHEALIGN_UP_SIZE(kiss_fft_scalar, ARRAYLEN_IN)] 288static 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 */
302static volatile int output_head SHAREDBSS_ATTR = 0; 293static volatile int output_head SHAREDBSS_ATTR = 0;
303static volatile int output_tail SHAREDBSS_ATTR = 0; 294static 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. */
305static kiss_fft_cpx output[2][CACHEALIGN_UP_SIZE(kiss_fft_cpx, ARRAYLEN_OUT+1)] 296static 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. */
312static kiss_fft_cpx output[1][ARRAYLEN_OUT+1]; 303static kiss_fft_cpx output[1][ARRAYLEN_OUT];
313#endif 304#endif
314 305
315/* Unshared */ 306/* Unshared */
316/* COP */ 307/* COP */
317static FFT_CFG fft_state SHAREDBSS_ATTR; 308static kiss_fft_cfg fft_state SHAREDBSS_ATTR;
318static char buffer[CACHEALIGN_UP_SIZE(char, BUFSIZE)] 309static 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 */
321static int32_t plot_history[ARRAYLEN_PLOT]; 312static 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 */
408static void apply_window_func(enum fft_window_func mode) 399static 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 **/
1136static inline bool fft_init_fft_lib(void) 1127static 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