diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugin.c | 2 | ||||
-rw-r--r-- | apps/plugin.h | 2 | ||||
-rw-r--r-- | apps/plugins/pitch_detector.c | 394 |
3 files changed, 170 insertions, 228 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index 53a05bf527..5101ceeb20 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -721,6 +721,8 @@ static const struct plugin_api rockbox_api = { | |||
721 | 721 | ||
722 | /* new stuff at the end, sort into place next time | 722 | /* new stuff at the end, sort into place next time |
723 | the API gets incompatible */ | 723 | the API gets incompatible */ |
724 | |||
725 | lcd_putsf, | ||
724 | }; | 726 | }; |
725 | 727 | ||
726 | int plugin_load(const char* plugin, const void* parameter) | 728 | int plugin_load(const char* plugin, const void* parameter) |
diff --git a/apps/plugin.h b/apps/plugin.h index 17c36fa8b1..2bcd93e3ad 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -894,6 +894,8 @@ struct plugin_api { | |||
894 | 894 | ||
895 | /* new stuff at the end, sort into place next time | 895 | /* new stuff at the end, sort into place next time |
896 | the API gets incompatible */ | 896 | the API gets incompatible */ |
897 | |||
898 | void (*lcd_putsf)(int x, int y, const unsigned char *fmt, ...); | ||
897 | }; | 899 | }; |
898 | 900 | ||
899 | /* plugin header */ | 901 | /* plugin header */ |
diff --git a/apps/plugins/pitch_detector.c b/apps/plugins/pitch_detector.c index 36e7059c1f..92ba6e53ac 100644 --- a/apps/plugins/pitch_detector.c +++ b/apps/plugins/pitch_detector.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2008 Lechner Michael / smoking gnu | 10 | * Copyright (C) 2008 Lechner Michael / smoking gnu |
11 | * | 11 | * |
@@ -19,15 +19,15 @@ | |||
19 | * | 19 | * |
20 | * INTRODUCTION: | 20 | * INTRODUCTION: |
21 | * OK, this is an attempt to write an instrument tuner for rockbox. | 21 | * OK, this is an attempt to write an instrument tuner for rockbox. |
22 | * It uses a Schmitt trigger algorithm, which I copied from | 22 | * It uses a Schmitt trigger algorithm, which I copied from |
23 | * tuneit [ (c) 2004 Mario Lang <mlang@delysid.org> ], for detecting the | 23 | * tuneit [ (c) 2004 Mario Lang <mlang@delysid.org> ], for detecting the |
24 | * fundamental freqency of a sound. A FFT algorithm would be more accurate | 24 | * fundamental freqency of a sound. A FFT algorithm would be more accurate |
25 | * but also much slower. | 25 | * but also much slower. |
26 | * | 26 | * |
27 | * TODO: | 27 | * TODO: |
28 | * - Adapt the Yin FFT algorithm, which would reduce complexity from O(n^2) | 28 | * - Adapt the Yin FFT algorithm, which would reduce complexity from O(n^2) |
29 | * to O(nlogn), theoretically reducing latency by a factor of ~10. -David | 29 | * to O(nlogn), theoretically reducing latency by a factor of ~10. -David |
30 | * | 30 | * |
31 | * MAJOR CHANGES: | 31 | * MAJOR CHANGES: |
32 | * 08.03.2008 Started coding | 32 | * 08.03.2008 Started coding |
33 | * 21.03.2008 Pitch detection works more or less | 33 | * 21.03.2008 Pitch detection works more or less |
@@ -42,7 +42,7 @@ | |||
42 | * Aubio sound processing library (aubio.org). -David | 42 | * Aubio sound processing library (aubio.org). -David |
43 | * 08.31.2009 Lots of changes: | 43 | * 08.31.2009 Lots of changes: |
44 | * Added a menu to tweak settings | 44 | * Added a menu to tweak settings |
45 | * Converted everything to fixed point (greatly improving | 45 | * Converted everything to fixed point (greatly improving |
46 | * latency) | 46 | * latency) |
47 | * Improved the display | 47 | * Improved the display |
48 | * Improved efficiency with judicious use of cpu_boost, the | 48 | * Improved efficiency with judicious use of cpu_boost, the |
@@ -51,17 +51,17 @@ | |||
51 | * Fixed a problem that caused an octave-off error | 51 | * Fixed a problem that caused an octave-off error |
52 | * -David | 52 | * -David |
53 | * 05.14.2010 Multibuffer continuous recording with two buffers | 53 | * 05.14.2010 Multibuffer continuous recording with two buffers |
54 | * | 54 | * |
55 | * | 55 | * |
56 | * CURRENT LIMITATIONS: | 56 | * CURRENT LIMITATIONS: |
57 | * - No gapless recording. Strictly speaking true gappless isn't possible, | 57 | * - No gapless recording. Strictly speaking true gappless isn't possible, |
58 | * since the algorithm takes longer to calculate than the length of the | 58 | * since the algorithm takes longer to calculate than the length of the |
59 | * sample, but latency could be improved a bit with proper use of the DMA | 59 | * sample, but latency could be improved a bit with proper use of the DMA |
60 | * recording functions. | 60 | * recording functions. |
61 | * - Due to how the Yin algorithm works, latency is higher for lower | 61 | * - Due to how the Yin algorithm works, latency is higher for lower |
62 | * frequencies. | 62 | * frequencies. |
63 | */ | 63 | */ |
64 | 64 | ||
65 | #include "plugin.h" | 65 | #include "plugin.h" |
66 | #include "lib/pluginlib_actions.h" | 66 | #include "lib/pluginlib_actions.h" |
67 | #include "lib/picture.h" | 67 | #include "lib/picture.h" |
@@ -140,7 +140,7 @@ typedef struct _fixed fixed; | |||
140 | /* there'll be one sample per second, or a latency of one second. */ | 140 | /* there'll be one sample per second, or a latency of one second. */ |
141 | /* Furthermore, the lowest detectable frequency will be about twice */ | 141 | /* Furthermore, the lowest detectable frequency will be about twice */ |
142 | /* the number of reads per second */ | 142 | /* the number of reads per second */ |
143 | /* If we ever switch to Yin FFT algorithm then this needs to be | 143 | /* If we ever switch to Yin FFT algorithm then this needs to be |
144 | a power of 2 */ | 144 | a power of 2 */ |
145 | #define BUFFER_SIZE 4096 | 145 | #define BUFFER_SIZE 4096 |
146 | #define SAMPLE_SIZE 4096 | 146 | #define SAMPLE_SIZE 4096 |
@@ -150,7 +150,7 @@ typedef struct _fixed fixed; | |||
150 | #define LCD_FACTOR (fp_div(int2fixed(LCD_WIDTH), int2fixed(100))) | 150 | #define LCD_FACTOR (fp_div(int2fixed(LCD_WIDTH), int2fixed(100))) |
151 | /* The threshold for the YIN algorithm */ | 151 | /* The threshold for the YIN algorithm */ |
152 | #define DEFAULT_YIN_THRESHOLD 5 /* 0.10 */ | 152 | #define DEFAULT_YIN_THRESHOLD 5 /* 0.10 */ |
153 | const fixed yin_threshold_table[] IDATA_ATTR = | 153 | static const fixed yin_threshold_table[] IDATA_ATTR = |
154 | { | 154 | { |
155 | float2fixed(0.01), | 155 | float2fixed(0.01), |
156 | float2fixed(0.02), | 156 | float2fixed(0.02), |
@@ -173,14 +173,12 @@ const fixed yin_threshold_table[] IDATA_ATTR = | |||
173 | * the note. The frequency is scaled in a way that the main | 173 | * the note. The frequency is scaled in a way that the main |
174 | * algorithm can assume the frequency of A to be 440 Hz. | 174 | * algorithm can assume the frequency of A to be 440 Hz. |
175 | */ | 175 | */ |
176 | struct freq_A_entry | 176 | static const struct |
177 | { | 177 | { |
178 | const int frequency; /* Frequency in Hz */ | 178 | const int frequency; /* Frequency in Hz */ |
179 | const fixed ratio; /* 440/frequency */ | 179 | const fixed ratio; /* 440/frequency */ |
180 | const fixed logratio; /* log2(factor) */ | 180 | const fixed logratio; /* log2(factor) */ |
181 | }; | 181 | } freq_A[] = |
182 | |||
183 | const struct freq_A_entry freq_A[] = | ||
184 | { | 182 | { |
185 | {435, float2fixed(1.011363636), float2fixed( 0.016301812)}, | 183 | {435, float2fixed(1.011363636), float2fixed( 0.016301812)}, |
186 | {436, float2fixed(1.009090909), float2fixed( 0.013056153)}, | 184 | {436, float2fixed(1.009090909), float2fixed( 0.013056153)}, |
@@ -214,8 +212,8 @@ const struct freq_A_entry freq_A[] = | |||
214 | #define DISPLAY_HZ_PRECISION 100 | 212 | #define DISPLAY_HZ_PRECISION 100 |
215 | 213 | ||
216 | /* Where to put the various GUI elements */ | 214 | /* Where to put the various GUI elements */ |
217 | int note_y; | 215 | static int note_y; |
218 | int bar_grad_y; | 216 | static int bar_grad_y; |
219 | #define LCD_RES_MIN (LCD_HEIGHT < LCD_WIDTH ? LCD_HEIGHT : LCD_WIDTH) | 217 | #define LCD_RES_MIN (LCD_HEIGHT < LCD_WIDTH ? LCD_HEIGHT : LCD_WIDTH) |
220 | #define BAR_PADDING (LCD_RES_MIN / 32) | 218 | #define BAR_PADDING (LCD_RES_MIN / 32) |
221 | #define BAR_Y (LCD_HEIGHT * 3 / 4) | 219 | #define BAR_Y (LCD_HEIGHT * 3 / 4) |
@@ -225,7 +223,7 @@ int bar_grad_y; | |||
225 | #define HZ_Y 0 | 223 | #define HZ_Y 0 |
226 | #define GRADUATION 10 /* Subdivisions of the whole 100-cent scale */ | 224 | #define GRADUATION 10 /* Subdivisions of the whole 100-cent scale */ |
227 | 225 | ||
228 | /* Bitmaps for drawing the note names. These need to have height | 226 | /* Bitmaps for drawing the note names. These need to have height |
229 | <= (bar_grad_y - note_y), or 15/32 * LCD_HEIGHT | 227 | <= (bar_grad_y - note_y), or 15/32 * LCD_HEIGHT |
230 | */ | 228 | */ |
231 | #define NUM_NOTE_IMAGES 9 | 229 | #define NUM_NOTE_IMAGES 9 |
@@ -238,7 +236,8 @@ int bar_grad_y; | |||
238 | #define NOTE_INDEX_G 6 | 236 | #define NOTE_INDEX_G 6 |
239 | #define NOTE_INDEX_SHARP 7 | 237 | #define NOTE_INDEX_SHARP 7 |
240 | #define NOTE_INDEX_FLAT 8 | 238 | #define NOTE_INDEX_FLAT 8 |
241 | const struct picture note_bitmaps = | 239 | |
240 | static const struct picture note_bitmaps = | ||
242 | { | 241 | { |
243 | pitch_notes, | 242 | pitch_notes, |
244 | BMPWIDTH_pitch_notes, | 243 | BMPWIDTH_pitch_notes, |
@@ -261,16 +260,13 @@ static int16_t iram_audio_data[BUFFER_SIZE] IBSS_ATTR; | |||
261 | #endif | 260 | #endif |
262 | #endif | 261 | #endif |
263 | 262 | ||
264 | /* Description of a note of scale */ | 263 | /* Notes within one (reference) scale */ |
265 | struct note_entry | 264 | static const struct |
266 | { | 265 | { |
267 | const char *name; /* Name of the note, e.g. "A#" */ | 266 | const char *name; /* Name of the note, e.g. "A#" */ |
268 | const fixed freq; /* Note frequency, Hz */ | 267 | const fixed freq; /* Note frequency, Hz */ |
269 | const fixed logfreq; /* log2(frequency) */ | 268 | const fixed logfreq; /* log2(frequency) */ |
270 | }; | 269 | } notes[] = |
271 | |||
272 | /* Notes within one (reference) scale */ | ||
273 | static const struct note_entry notes[] = | ||
274 | { | 270 | { |
275 | {"A" , float2fixed(440.0000000f), float2fixed(8.781359714f)}, | 271 | {"A" , float2fixed(440.0000000f), float2fixed(8.781359714f)}, |
276 | {"A#", float2fixed(466.1637615f), float2fixed(8.864693047f)}, | 272 | {"A#", float2fixed(466.1637615f), float2fixed(8.864693047f)}, |
@@ -295,7 +291,7 @@ static int bar_x_0; | |||
295 | static int lbl_x_minus_50, lbl_x_minus_20, lbl_x_0, lbl_x_20, lbl_x_50; | 291 | static int lbl_x_minus_50, lbl_x_minus_20, lbl_x_0, lbl_x_20, lbl_x_50; |
296 | 292 | ||
297 | /* Settings for the plugin */ | 293 | /* Settings for the plugin */ |
298 | struct tuner_settings | 294 | static struct tuner_settings |
299 | { | 295 | { |
300 | unsigned volume_threshold; | 296 | unsigned volume_threshold; |
301 | unsigned record_gain; | 297 | unsigned record_gain; |
@@ -305,7 +301,7 @@ struct tuner_settings | |||
305 | int freq_A; /* Index of the frequency of A */ | 301 | int freq_A; /* Index of the frequency of A */ |
306 | bool use_sharps; | 302 | bool use_sharps; |
307 | bool display_hz; | 303 | bool display_hz; |
308 | } tuner_settings; | 304 | } settings; |
309 | 305 | ||
310 | /*=================================================================*/ | 306 | /*=================================================================*/ |
311 | /* Settings loading and saving(adapted from the clock plugin) */ | 307 | /* Settings loading and saving(adapted from the clock plugin) */ |
@@ -313,98 +309,68 @@ struct tuner_settings | |||
313 | 309 | ||
314 | #define SETTINGS_FILENAME PLUGIN_APPS_DIR "/.pitch_settings" | 310 | #define SETTINGS_FILENAME PLUGIN_APPS_DIR "/.pitch_settings" |
315 | 311 | ||
316 | enum message | 312 | /* The settings as they exist on the hard disk, so that |
317 | { | ||
318 | MESSAGE_LOADING, | ||
319 | MESSAGE_LOADED, | ||
320 | MESSAGE_ERRLOAD, | ||
321 | MESSAGE_SAVING, | ||
322 | MESSAGE_SAVED, | ||
323 | MESSAGE_ERRSAVE | ||
324 | }; | ||
325 | |||
326 | enum settings_file_status | ||
327 | { | ||
328 | LOADED, ERRLOAD, | ||
329 | SAVED, ERRSAVE | ||
330 | }; | ||
331 | |||
332 | /* The settings as they exist on the hard disk, so that | ||
333 | * we can know at saving time if changes have been made */ | 313 | * we can know at saving time if changes have been made */ |
334 | struct tuner_settings hdd_tuner_settings; | 314 | static struct tuner_settings hdd_settings; |
335 | 315 | ||
336 | /*---------------------------------------------------------------------*/ | 316 | /*---------------------------------------------------------------------*/ |
337 | 317 | ||
338 | bool settings_needs_saving(struct tuner_settings* settings) | 318 | static bool settings_needs_saving(void) |
339 | { | 319 | { |
340 | return(rb->memcmp(settings, &hdd_tuner_settings, sizeof(*settings))); | 320 | return(rb->memcmp(&settings, &hdd_settings, sizeof(settings))); |
341 | } | 321 | } |
342 | 322 | ||
343 | /*---------------------------------------------------------------------*/ | 323 | /*---------------------------------------------------------------------*/ |
344 | 324 | ||
345 | void tuner_settings_reset(struct tuner_settings* settings) | 325 | static void tuner_settings_reset(void) |
346 | { | 326 | { |
347 | settings->volume_threshold = VOLUME_THRESHOLD; | 327 | settings = (struct tuner_settings) { |
348 | settings->record_gain = rb->global_settings->rec_mic_gain; | 328 | .volume_threshold = VOLUME_THRESHOLD, |
349 | settings->sample_size = BUFFER_SIZE; | 329 | .record_gain = rb->global_settings->rec_mic_gain, |
350 | settings->lowest_freq = period2freq(BUFFER_SIZE / 4); | 330 | .sample_size = BUFFER_SIZE, |
351 | settings->yin_threshold = DEFAULT_YIN_THRESHOLD; | 331 | .lowest_freq = period2freq(BUFFER_SIZE / 4), |
352 | settings->freq_A = DEFAULT_FREQ_A; | 332 | .yin_threshold = DEFAULT_YIN_THRESHOLD, |
353 | settings->use_sharps = true; | 333 | .freq_A = DEFAULT_FREQ_A, |
354 | settings->display_hz = false; | 334 | .use_sharps = true, |
335 | .display_hz = false, | ||
336 | }; | ||
355 | } | 337 | } |
356 | 338 | ||
357 | /*---------------------------------------------------------------------*/ | 339 | /*---------------------------------------------------------------------*/ |
358 | 340 | ||
359 | enum settings_file_status tuner_settings_load(struct tuner_settings* settings, | 341 | static void load_settings(void) |
360 | char* filename) | ||
361 | { | 342 | { |
362 | int fd = rb->open(filename, O_RDONLY); | 343 | int fd = rb->open(SETTINGS_FILENAME, O_RDONLY); |
363 | if(fd >= 0){ /* does file exist? */ | 344 | if(fd < 0){ /* file doesn't exist */ |
364 | /* basic consistency check */ | 345 | /* Initializes the settings with default values at least */ |
365 | if(rb->filesize(fd) == sizeof(*settings)){ | 346 | tuner_settings_reset(); |
366 | rb->read(fd, settings, sizeof(*settings)); | 347 | return; |
367 | rb->close(fd); | ||
368 | rb->memcpy(&hdd_tuner_settings, settings, sizeof(*settings)); | ||
369 | return(LOADED); | ||
370 | } | ||
371 | } | 348 | } |
372 | /* Initializes the settings with default values at least */ | ||
373 | tuner_settings_reset(settings); | ||
374 | return(ERRLOAD); | ||
375 | } | ||
376 | |||
377 | /*---------------------------------------------------------------------*/ | ||
378 | 349 | ||
379 | enum settings_file_status tuner_settings_save(struct tuner_settings* settings, | 350 | /* basic consistency check */ |
380 | char* filename) | 351 | if(rb->filesize(fd) == sizeof(settings)){ |
381 | { | 352 | rb->read(fd, &settings, sizeof(settings)); |
382 | int fd = rb->creat(filename, 0666); | 353 | rb->memcpy(&hdd_settings, &settings, sizeof(settings)); |
383 | if(fd >= 0){ /* does file exist? */ | 354 | } |
384 | rb->write (fd, settings, sizeof(*settings)); | 355 | else{ |
385 | rb->close(fd); | 356 | tuner_settings_reset(); |
386 | return(SAVED); | ||
387 | } | 357 | } |
388 | return(ERRSAVE); | ||
389 | } | ||
390 | |||
391 | /*---------------------------------------------------------------------*/ | ||
392 | |||
393 | void load_settings(void) | ||
394 | { | ||
395 | tuner_settings_load(&tuner_settings, SETTINGS_FILENAME); | ||
396 | 358 | ||
397 | rb->storage_sleep(); | 359 | rb->close(fd); |
398 | } | 360 | } |
399 | 361 | ||
400 | /*---------------------------------------------------------------------*/ | 362 | /*---------------------------------------------------------------------*/ |
401 | 363 | ||
402 | void save_settings(void) | 364 | static void save_settings(void) |
403 | { | 365 | { |
404 | if(!settings_needs_saving(&tuner_settings)) | 366 | if(!settings_needs_saving()) |
405 | return; | 367 | return; |
406 | 368 | ||
407 | tuner_settings_save(&tuner_settings, SETTINGS_FILENAME); | 369 | int fd = rb->creat(SETTINGS_FILENAME, 0666); |
370 | if(fd >= 0){ /* does file exist? */ | ||
371 | rb->write (fd, &settings, sizeof(settings)); | ||
372 | rb->close(fd); | ||
373 | } | ||
408 | } | 374 | } |
409 | 375 | ||
410 | /*=================================================================*/ | 376 | /*=================================================================*/ |
@@ -423,7 +389,7 @@ const struct button_mapping* plugin_contexts[]={ | |||
423 | /* Option strings */ | 389 | /* Option strings */ |
424 | 390 | ||
425 | /* This has to match yin_threshold_table */ | 391 | /* This has to match yin_threshold_table */ |
426 | static const struct opt_items yin_threshold_text[] = | 392 | static const struct opt_items yin_threshold_text[] = |
427 | { | 393 | { |
428 | { "0.01", -1 }, | 394 | { "0.01", -1 }, |
429 | { "0.02", -1 }, | 395 | { "0.02", -1 }, |
@@ -441,27 +407,27 @@ static const struct opt_items yin_threshold_text[] = | |||
441 | { "0.50", -1 }, | 407 | { "0.50", -1 }, |
442 | }; | 408 | }; |
443 | 409 | ||
444 | static const struct opt_items accidental_text[] = | 410 | static const struct opt_items accidental_text[] = |
445 | { | 411 | { |
446 | { "Flat", -1 }, | 412 | { "Flat", -1 }, |
447 | { "Sharp", -1 }, | 413 | { "Sharp", -1 }, |
448 | }; | 414 | }; |
449 | 415 | ||
450 | void set_min_freq(int new_freq) | 416 | static void set_min_freq(int new_freq) |
451 | { | 417 | { |
452 | tuner_settings.sample_size = freq2period(new_freq) * 4; | 418 | settings.sample_size = freq2period(new_freq) * 4; |
453 | 419 | ||
454 | /* clamp the sample size between min and max */ | 420 | /* clamp the sample size between min and max */ |
455 | if(tuner_settings.sample_size <= SAMPLE_SIZE_MIN) | 421 | if(settings.sample_size <= SAMPLE_SIZE_MIN) |
456 | tuner_settings.sample_size = SAMPLE_SIZE_MIN; | 422 | settings.sample_size = SAMPLE_SIZE_MIN; |
457 | else if(tuner_settings.sample_size >= BUFFER_SIZE) | 423 | else if(settings.sample_size >= BUFFER_SIZE) |
458 | tuner_settings.sample_size = BUFFER_SIZE; | 424 | settings.sample_size = BUFFER_SIZE; |
459 | 425 | ||
460 | /* sample size must be divisible by 4 - round up */ | 426 | /* sample size must be divisible by 4 - round up */ |
461 | tuner_settings.sample_size = (tuner_settings.sample_size + 3) & ~3; | 427 | settings.sample_size = (settings.sample_size + 3) & ~3; |
462 | } | 428 | } |
463 | 429 | ||
464 | bool main_menu(void) | 430 | static bool main_menu(void) |
465 | { | 431 | { |
466 | int selection = 0; | 432 | int selection = 0; |
467 | bool done = false; | 433 | bool done = false; |
@@ -494,58 +460,58 @@ bool main_menu(void) | |||
494 | { | 460 | { |
495 | case 1: | 461 | case 1: |
496 | rb->set_int("Volume Threshold", "%", UNIT_INT, | 462 | rb->set_int("Volume Threshold", "%", UNIT_INT, |
497 | &tuner_settings.volume_threshold, | 463 | &settings.volume_threshold, |
498 | NULL, 5, 5, 95, NULL); | 464 | NULL, 5, 5, 95, NULL); |
499 | break; | 465 | break; |
500 | case 2: | 466 | case 2: |
501 | rb->set_int("Listening Volume", "%", UNIT_INT, | 467 | rb->set_int("Listening Volume", "%", UNIT_INT, |
502 | &tuner_settings.record_gain, | 468 | &settings.record_gain, |
503 | NULL, 1, rb->sound_min(SOUND_MIC_GAIN), | 469 | NULL, 1, rb->sound_min(SOUND_MIC_GAIN), |
504 | rb->sound_max(SOUND_MIC_GAIN), NULL); | 470 | rb->sound_max(SOUND_MIC_GAIN), NULL); |
505 | break; | 471 | break; |
506 | case 3: | 472 | case 3: |
507 | rb->set_int("Lowest Frequency", "Hz", UNIT_INT, | 473 | rb->set_int("Lowest Frequency", "Hz", UNIT_INT, |
508 | &tuner_settings.lowest_freq, set_min_freq, 1, | 474 | &settings.lowest_freq, set_min_freq, 1, |
509 | /* Range depends on the size of the buffer */ | 475 | /* Range depends on the size of the buffer */ |
510 | sample_rate / (BUFFER_SIZE / 4), | 476 | sample_rate / (BUFFER_SIZE / 4), |
511 | sample_rate / (SAMPLE_SIZE_MIN / 4), NULL); | 477 | sample_rate / (SAMPLE_SIZE_MIN / 4), NULL); |
512 | break; | 478 | break; |
513 | case 4: | 479 | case 4: |
514 | rb->set_option( | 480 | rb->set_option( |
515 | "Algorithm Pickiness (Lower -> more discriminating)", | 481 | "Algorithm Pickiness (Lower -> more discriminating)", |
516 | &tuner_settings.yin_threshold, | 482 | &settings.yin_threshold, |
517 | INT, yin_threshold_text, | 483 | INT, yin_threshold_text, |
518 | sizeof(yin_threshold_text) / sizeof(yin_threshold_text[0]), | 484 | sizeof(yin_threshold_text) / sizeof(yin_threshold_text[0]), |
519 | NULL); | 485 | NULL); |
520 | break; | 486 | break; |
521 | case 5: | 487 | case 5: |
522 | rb->set_option("Display Accidentals As", | 488 | rb->set_option("Display Accidentals As", |
523 | &tuner_settings.use_sharps, | 489 | &settings.use_sharps, |
524 | BOOL, accidental_text, 2, NULL); | 490 | BOOL, accidental_text, 2, NULL); |
525 | break; | 491 | break; |
526 | case 6: | 492 | case 6: |
527 | rb->set_bool("Display Frequency (Hz)", | 493 | rb->set_bool("Display Frequency (Hz)", |
528 | &tuner_settings.display_hz); | 494 | &settings.display_hz); |
529 | break; | 495 | break; |
530 | case 7: | 496 | case 7: |
531 | freq_val = freq_A[tuner_settings.freq_A].frequency; | 497 | freq_val = freq_A[settings.freq_A].frequency; |
532 | rb->set_int("Frequency of A (Hz)", | 498 | rb->set_int("Frequency of A (Hz)", |
533 | "Hz", UNIT_INT, &freq_val, NULL, | 499 | "Hz", UNIT_INT, &freq_val, NULL, |
534 | 1, freq_A[0].frequency, freq_A[NUM_FREQ_A-1].frequency, | 500 | 1, freq_A[0].frequency, freq_A[NUM_FREQ_A-1].frequency, |
535 | NULL); | 501 | NULL); |
536 | tuner_settings.freq_A = freq_val - freq_A[0].frequency; | 502 | settings.freq_A = freq_val - freq_A[0].frequency; |
537 | break; | 503 | break; |
538 | case 8: | 504 | case 8: |
539 | reset = false; | 505 | reset = false; |
540 | rb->set_bool("Reset Tuner Settings?", &reset); | 506 | rb->set_bool("Reset Tuner Settings?", &reset); |
541 | if (reset) | 507 | if (reset) |
542 | tuner_settings_reset(&tuner_settings); | 508 | tuner_settings_reset(); |
543 | break; | 509 | break; |
544 | case 9: | 510 | case 9: |
545 | exit_tuner = true; | 511 | exit_tuner = true; |
546 | done = true; | 512 | done = true; |
547 | break; | 513 | break; |
548 | case 0: | 514 | case 0: |
549 | default: | 515 | default: |
550 | /* Return to the tuner */ | 516 | /* Return to the tuner */ |
551 | done = true; | 517 | done = true; |
@@ -562,15 +528,15 @@ bool main_menu(void) | |||
562 | /*=================================================================*/ | 528 | /*=================================================================*/ |
563 | 529 | ||
564 | /* Fixed-point log base 2*/ | 530 | /* Fixed-point log base 2*/ |
565 | /* Adapted from python code at | 531 | /* Adapted from python code at |
566 | http://en.wikipedia.org/wiki/Binary_logarithm#Algorithm | 532 | http://en.wikipedia.org/wiki/Binary_logarithm#Algorithm |
567 | */ | 533 | */ |
568 | fixed log(fixed inp) | 534 | static fixed log(fixed inp) |
569 | { | 535 | { |
570 | fixed x = inp; | 536 | fixed x = inp; |
571 | fixed fp = int2fixed(1); | 537 | fixed fp = int2fixed(1); |
572 | fixed res = int2fixed(0); | 538 | fixed res = int2fixed(0); |
573 | 539 | ||
574 | if(fp_lte(x, FP_ZERO)) | 540 | if(fp_lte(x, FP_ZERO)) |
575 | { | 541 | { |
576 | return FP_MIN; | 542 | return FP_MIN; |
@@ -611,59 +577,25 @@ fixed log(fixed inp) | |||
611 | /* GUI Stuff */ | 577 | /* GUI Stuff */ |
612 | /*=================================================================*/ | 578 | /*=================================================================*/ |
613 | 579 | ||
614 | /* The function name is pretty self-explaining ;) */ | ||
615 | void print_int_xy(int x, int y, int v) | ||
616 | { | ||
617 | char temp[20]; | ||
618 | #if LCD_DEPTH > 1 | ||
619 | rb->lcd_set_foreground(front_color); | ||
620 | #endif | ||
621 | rb->snprintf(temp,20,"%d",v); | ||
622 | rb->lcd_putsxy(x,y,temp); | ||
623 | } | ||
624 | |||
625 | /* Print out the frequency etc */ | ||
626 | void print_str(char* s) | ||
627 | { | ||
628 | #if LCD_DEPTH > 1 | ||
629 | rb->lcd_set_foreground(front_color); | ||
630 | #endif | ||
631 | rb->lcd_putsxy(0, HZ_Y, s); | ||
632 | } | ||
633 | |||
634 | /* What can I say? Read the function name... */ | ||
635 | void print_char_xy(int x, int y, char c) | ||
636 | { | ||
637 | char temp[2]; | ||
638 | |||
639 | temp[0]=c; | ||
640 | temp[1]=0; | ||
641 | #if LCD_DEPTH > 1 | ||
642 | rb->lcd_set_foreground(front_color); | ||
643 | #endif | ||
644 | |||
645 | rb->lcd_putsxy(x, y, temp); | ||
646 | } | ||
647 | |||
648 | /* Draw the note bitmap */ | 580 | /* Draw the note bitmap */ |
649 | void draw_note(const char *note) | 581 | static void draw_note(const char *note) |
650 | { | 582 | { |
651 | int i; | 583 | int i; |
652 | int note_x = (LCD_WIDTH - BMPWIDTH_pitch_notes) / 2; | 584 | int note_x = (LCD_WIDTH - BMPWIDTH_pitch_notes) / 2; |
653 | int accidental_index = NOTE_INDEX_SHARP; | 585 | int accidental_index = NOTE_INDEX_SHARP; |
654 | 586 | ||
655 | i = note[0]-'A'; | 587 | i = note[0]-'A'; |
656 | 588 | ||
657 | if(note[1] == '#') | 589 | if(note[1] == '#') |
658 | { | 590 | { |
659 | if(!(tuner_settings.use_sharps)) | 591 | if(!(settings.use_sharps)) |
660 | { | 592 | { |
661 | i = (i + 1) % 7; | 593 | i = (i + 1) % 7; |
662 | accidental_index = NOTE_INDEX_FLAT; | 594 | accidental_index = NOTE_INDEX_FLAT; |
663 | } | 595 | } |
664 | 596 | ||
665 | vertical_picture_draw_sprite(rb->screens[0], | 597 | vertical_picture_draw_sprite(rb->screens[0], |
666 | ¬e_bitmaps, | 598 | ¬e_bitmaps, |
667 | accidental_index, | 599 | accidental_index, |
668 | LCD_WIDTH / 2, | 600 | LCD_WIDTH / 2, |
669 | note_y); | 601 | note_y); |
@@ -674,9 +606,10 @@ void draw_note(const char *note) | |||
674 | note_x, | 606 | note_x, |
675 | note_y); | 607 | note_y); |
676 | } | 608 | } |
609 | |||
677 | /* Draw the red bar and the white lines */ | 610 | /* Draw the red bar and the white lines */ |
678 | void draw_bar(fixed wrong_by_cents) | 611 | static void draw_bar(fixed wrong_by_cents) |
679 | { | 612 | { |
680 | unsigned n; | 613 | unsigned n; |
681 | int x; | 614 | int x; |
682 | 615 | ||
@@ -698,11 +631,14 @@ void draw_bar(fixed wrong_by_cents) | |||
698 | rb->lcd_vline(x, BAR_HLINE_Y, BAR_HLINE_Y2); | 631 | rb->lcd_vline(x, BAR_HLINE_Y, BAR_HLINE_Y2); |
699 | } | 632 | } |
700 | 633 | ||
701 | print_int_xy(lbl_x_minus_50 ,bar_grad_y, -50); | 634 | #if LCD_DEPTH > 1 |
702 | print_int_xy(lbl_x_minus_20 ,bar_grad_y, -20); | 635 | rb->lcd_set_foreground(front_color); |
703 | print_int_xy(lbl_x_0 ,bar_grad_y, 0); | 636 | #endif |
704 | print_int_xy(lbl_x_20 ,bar_grad_y, 20); | 637 | rb->lcd_putsf(lbl_x_minus_50 ,bar_grad_y, "%d", -50); |
705 | print_int_xy(lbl_x_50 ,bar_grad_y, 50); | 638 | rb->lcd_putsf(lbl_x_minus_20 ,bar_grad_y, "%d", -20); |
639 | rb->lcd_putsf(lbl_x_0 ,bar_grad_y, "%d", 0); | ||
640 | rb->lcd_putsf(lbl_x_20 ,bar_grad_y, "%d", 20); | ||
641 | rb->lcd_putsf(lbl_x_50 ,bar_grad_y, "%d", 50); | ||
706 | 642 | ||
707 | #ifdef HAVE_LCD_COLOR | 643 | #ifdef HAVE_LCD_COLOR |
708 | rb->lcd_set_foreground(LCD_RGBPACK(255,0,0)); /* Color screens */ | 644 | rb->lcd_set_foreground(LCD_RGBPACK(255,0,0)); /* Color screens */ |
@@ -712,26 +648,25 @@ void draw_bar(fixed wrong_by_cents) | |||
712 | 648 | ||
713 | if (fp_gt(wrong_by_cents, FP_ZERO)) | 649 | if (fp_gt(wrong_by_cents, FP_ZERO)) |
714 | { | 650 | { |
715 | rb->lcd_fillrect(bar_x_0, BAR_Y, | 651 | rb->lcd_fillrect(bar_x_0, BAR_Y, |
716 | fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)), BAR_HEIGHT); | 652 | fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)), BAR_HEIGHT); |
717 | } | 653 | } |
718 | else | 654 | else |
719 | { | 655 | { |
720 | rb->lcd_fillrect(bar_x_0 + fixed2int(fp_mul(wrong_by_cents,LCD_FACTOR)), | 656 | rb->lcd_fillrect(bar_x_0 + fixed2int(fp_mul(wrong_by_cents,LCD_FACTOR)), |
721 | BAR_Y, | 657 | BAR_Y, |
722 | fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)) * -1, | 658 | fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)) * -1, |
723 | BAR_HEIGHT); | 659 | BAR_HEIGHT); |
724 | } | 660 | } |
725 | } | 661 | } |
726 | 662 | ||
727 | /* Calculate how wrong the note is and draw the GUI */ | 663 | /* Calculate how wrong the note is and draw the GUI */ |
728 | void display_frequency (fixed freq) | 664 | static void display_frequency (fixed freq) |
729 | { | 665 | { |
730 | fixed ldf, mldf; | 666 | fixed ldf, mldf; |
731 | fixed lfreq, nfreq; | 667 | fixed lfreq, nfreq; |
732 | fixed orig_freq; | 668 | fixed orig_freq; |
733 | int i, note = 0; | 669 | int i, note = 0; |
734 | char str_buf[30]; | ||
735 | 670 | ||
736 | if (fp_lt(freq, FP_LOW)) | 671 | if (fp_lt(freq, FP_LOW)) |
737 | freq = FP_LOW; | 672 | freq = FP_LOW; |
@@ -739,8 +674,8 @@ void display_frequency (fixed freq) | |||
739 | /* We calculate the frequency and its log as if */ | 674 | /* We calculate the frequency and its log as if */ |
740 | /* the reference frequency of A were 440 Hz. */ | 675 | /* the reference frequency of A were 440 Hz. */ |
741 | orig_freq = freq; | 676 | orig_freq = freq; |
742 | lfreq = fp_add(log(freq), freq_A[tuner_settings.freq_A].logratio); | 677 | lfreq = fp_add(log(freq), freq_A[settings.freq_A].logratio); |
743 | freq = fp_mul(freq, freq_A[tuner_settings.freq_A].ratio); | 678 | freq = fp_mul(freq, freq_A[settings.freq_A].ratio); |
744 | 679 | ||
745 | /* This calculates a log freq offset for note A */ | 680 | /* This calculates a log freq offset for note A */ |
746 | /* Get the frequency to within the range of our reference table, */ | 681 | /* Get the frequency to within the range of our reference table, */ |
@@ -775,39 +710,41 @@ void display_frequency (fixed freq) | |||
775 | if(fp_round(freq) != 0) | 710 | if(fp_round(freq) != 0) |
776 | { | 711 | { |
777 | draw_note(notes[note].name); | 712 | draw_note(notes[note].name); |
778 | if(tuner_settings.display_hz) | 713 | if(settings.display_hz) |
779 | { | 714 | { |
780 | rb->snprintf(str_buf,30, "%s : %d cents (%d.%02dHz)", | 715 | #if LCD_DEPTH > 1 |
716 | rb->lcd_set_foreground(front_color); | ||
717 | #endif | ||
718 | rb->lcd_putsf(0, HZ_Y, "%s : %d cents (%d.%02dHz)", | ||
781 | notes[note].name, fp_round(ldf) ,fixed2int(orig_freq), | 719 | notes[note].name, fp_round(ldf) ,fixed2int(orig_freq), |
782 | fp_round(fp_mul(fp_frac(orig_freq), | 720 | fp_round(fp_mul(fp_frac(orig_freq), |
783 | int2fixed(DISPLAY_HZ_PRECISION)))); | 721 | int2fixed(DISPLAY_HZ_PRECISION)))); |
784 | print_str(str_buf); | ||
785 | } | 722 | } |
786 | } | 723 | } |
787 | rb->lcd_update(); | 724 | rb->lcd_update(); |
788 | } | 725 | } |
789 | 726 | ||
790 | /*----------------------------------------------------------------------- | 727 | /*----------------------------------------------------------------------- |
791 | * Functions for the Yin algorithm | 728 | * Functions for the Yin algorithm |
792 | * | 729 | * |
793 | * These were all adapted from the versions in Aubio v0.3.2 | 730 | * These were all adapted from the versions in Aubio v0.3.2 |
794 | * Here's what the Aubio documentation has to say: | 731 | * Here's what the Aubio documentation has to say: |
795 | * | 732 | * |
796 | * This algorithm was developped by A. de Cheveigne and H. Kawahara and | 733 | * This algorithm was developped by A. de Cheveigne and H. Kawahara and |
797 | * published in: | 734 | * published in: |
798 | * | 735 | * |
799 | * de Cheveign?, A., Kawahara, H. (2002) "YIN, a fundamental frequency | 736 | * de Cheveign?, A., Kawahara, H. (2002) "YIN, a fundamental frequency |
800 | * estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. | 737 | * estimator for speech and music", J. Acoust. Soc. Am. 111, 1917-1930. |
801 | * | 738 | * |
802 | * see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html | 739 | * see http://recherche.ircam.fr/equipes/pcm/pub/people/cheveign.html |
803 | -------------------------------------------------------------------------*/ | 740 | -------------------------------------------------------------------------*/ |
804 | 741 | ||
805 | /* Find the index of the minimum element of an array of floats */ | 742 | /* Find the index of the minimum element of an array of floats */ |
806 | unsigned vec_min_elem(fixed *s, unsigned buflen) | 743 | static unsigned vec_min_elem(fixed *s, unsigned buflen) |
807 | { | 744 | { |
808 | unsigned j, pos=0.0f; | 745 | unsigned j, pos=0.0f; |
809 | fixed tmp = s[0]; | 746 | fixed tmp = s[0]; |
810 | for (j=0; j < buflen; j++) | 747 | for (j=0; j < buflen; j++) |
811 | { | 748 | { |
812 | if(fp_gt(tmp, s[j])) | 749 | if(fp_gt(tmp, s[j])) |
813 | { | 750 | { |
@@ -819,13 +756,13 @@ unsigned vec_min_elem(fixed *s, unsigned buflen) | |||
819 | } | 756 | } |
820 | 757 | ||
821 | 758 | ||
822 | static inline fixed aubio_quadfrac(fixed s0, fixed s1, fixed s2, fixed pf) | 759 | static inline fixed aubio_quadfrac(fixed s0, fixed s1, fixed s2, fixed pf) |
823 | { | 760 | { |
824 | /* Original floating point version: */ | 761 | /* Original floating point version: */ |
825 | /* tmp = s0 + (pf/2.0f) * (pf * ( s0 - 2.0f*s1 + s2 ) - | 762 | /* tmp = s0 + (pf/2.0f) * (pf * ( s0 - 2.0f*s1 + s2 ) - |
826 | 3.0f*s0 + 4.0f*s1 - s2);*/ | 763 | 3.0f*s0 + 4.0f*s1 - s2);*/ |
827 | /* Converted to explicit operator precedence: */ | 764 | /* Converted to explicit operator precedence: */ |
828 | /* tmp = s0 + ((pf/2.0f) * ((((pf * ((s0 - (2*s1)) + s2)) - | 765 | /* tmp = s0 + ((pf/2.0f) * ((((pf * ((s0 - (2*s1)) + s2)) - |
829 | (3*s0)) + (4*s1)) - s2)); */ | 766 | (3*s0)) + (4*s1)) - s2)); */ |
830 | 767 | ||
831 | /* I made it look like this so I could easily track the precedence and */ | 768 | /* I made it look like this so I could easily track the precedence and */ |
@@ -853,7 +790,7 @@ static inline fixed aubio_quadfrac(fixed s0, fixed s1, fixed s2, fixed pf) | |||
853 | s0, | 790 | s0, |
854 | fp_shl(s1, 1) | 791 | fp_shl(s1, 1) |
855 | ), | 792 | ), |
856 | s2 | 793 | s2 |
857 | ) | 794 | ) |
858 | ), | 795 | ), |
859 | fp_mul | 796 | fp_mul |
@@ -873,32 +810,32 @@ static inline fixed aubio_quadfrac(fixed s0, fixed s1, fixed s2, fixed pf) | |||
873 | 810 | ||
874 | #define QUADINT_STEP float2fixed(1.0f/200.0f) | 811 | #define QUADINT_STEP float2fixed(1.0f/200.0f) |
875 | 812 | ||
876 | fixed ICODE_ATTR vec_quadint_min(fixed *x, unsigned bufsize, unsigned pos, unsigned span) | 813 | static fixed ICODE_ATTR vec_quadint_min(fixed *x, unsigned bufsize, unsigned pos, unsigned span) |
877 | { | 814 | { |
878 | fixed res, frac, s0, s1, s2; | 815 | fixed res, frac, s0, s1, s2; |
879 | fixed exactpos = int2fixed(pos); | 816 | fixed exactpos = int2fixed(pos); |
880 | /* init resold to something big (in case x[pos+-span]<0)) */ | 817 | /* init resold to something big (in case x[pos+-span]<0)) */ |
881 | fixed resold = FP_MAX; | 818 | fixed resold = FP_MAX; |
882 | 819 | ||
883 | if ((pos > span) && (pos < bufsize-span)) | 820 | if ((pos > span) && (pos < bufsize-span)) |
884 | { | 821 | { |
885 | s0 = x[pos-span]; | 822 | s0 = x[pos-span]; |
886 | s1 = x[pos] ; | 823 | s1 = x[pos] ; |
887 | s2 = x[pos+span]; | 824 | s2 = x[pos+span]; |
888 | /* increase frac */ | 825 | /* increase frac */ |
889 | for (frac = float2fixed(0.0f); | 826 | for (frac = float2fixed(0.0f); |
890 | fp_lt(frac, float2fixed(2.0f)); | 827 | fp_lt(frac, float2fixed(2.0f)); |
891 | frac = fp_add(frac, QUADINT_STEP)) | 828 | frac = fp_add(frac, QUADINT_STEP)) |
892 | { | 829 | { |
893 | res = aubio_quadfrac(s0, s1, s2, frac); | 830 | res = aubio_quadfrac(s0, s1, s2, frac); |
894 | if (fp_lt(res, resold)) | 831 | if (fp_lt(res, resold)) |
895 | { | 832 | { |
896 | resold = res; | 833 | resold = res; |
897 | } | 834 | } |
898 | else | 835 | else |
899 | { | 836 | { |
900 | /* exactpos += (frac-QUADINT_STEP)*span - span/2.0f; */ | 837 | /* exactpos += (frac-QUADINT_STEP)*span - span/2.0f; */ |
901 | exactpos = fp_add(exactpos, | 838 | exactpos = fp_add(exactpos, |
902 | fp_sub( | 839 | fp_sub( |
903 | fp_mul( | 840 | fp_mul( |
904 | fp_sub(frac, QUADINT_STEP), | 841 | fp_sub(frac, QUADINT_STEP), |
@@ -915,17 +852,17 @@ fixed ICODE_ATTR vec_quadint_min(fixed *x, unsigned bufsize, unsigned pos, unsig | |||
915 | } | 852 | } |
916 | 853 | ||
917 | 854 | ||
918 | /* Calculate the period of the note in the | 855 | /* Calculate the period of the note in the |
919 | buffer using the YIN algorithm */ | 856 | buffer using the YIN algorithm */ |
920 | /* The yin pointer is just a buffer that the algorithm uses as a work | 857 | /* The yin pointer is just a buffer that the algorithm uses as a work |
921 | space. It needs to be half the length of the input buffer. */ | 858 | space. It needs to be half the length of the input buffer. */ |
922 | 859 | ||
923 | fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin) | 860 | static fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin) |
924 | { | 861 | { |
925 | fixed retval; | 862 | fixed retval; |
926 | unsigned j,tau = 0; | 863 | unsigned j,tau = 0; |
927 | int period; | 864 | int period; |
928 | unsigned yin_size = tuner_settings.sample_size / 4; | 865 | unsigned yin_size = settings.sample_size / 4; |
929 | 866 | ||
930 | fixed tmp = FP_ZERO, tmp2 = FP_ZERO; | 867 | fixed tmp = FP_ZERO, tmp2 = FP_ZERO; |
931 | yin[0] = int2fixed(1); | 868 | yin[0] = int2fixed(1); |
@@ -934,7 +871,7 @@ fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin) | |||
934 | yin[tau] = FP_ZERO; | 871 | yin[tau] = FP_ZERO; |
935 | for (j = 0; j < yin_size; j++) | 872 | for (j = 0; j < yin_size; j++) |
936 | { | 873 | { |
937 | tmp = fp_sub(int2mantissa(input[2 * j]), | 874 | tmp = fp_sub(int2mantissa(input[2 * j]), |
938 | int2mantissa(input[2 * (j + tau)])); | 875 | int2mantissa(input[2 * (j + tau)])); |
939 | yin[tau] = fp_add(yin[tau], fp_mul(tmp, tmp)); | 876 | yin[tau] = fp_add(yin[tau], fp_mul(tmp, tmp)); |
940 | } | 877 | } |
@@ -944,15 +881,15 @@ fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin) | |||
944 | yin[tau] = fp_mul(yin[tau], fp_div(int2fixed(tau), tmp2)); | 881 | yin[tau] = fp_mul(yin[tau], fp_div(int2fixed(tau), tmp2)); |
945 | } | 882 | } |
946 | period = tau - 3; | 883 | period = tau - 3; |
947 | if(tau > 4 && fp_lt(yin[period], | 884 | if(tau > 4 && fp_lt(yin[period], |
948 | yin_threshold_table[tuner_settings.yin_threshold]) | 885 | yin_threshold_table[settings.yin_threshold]) |
949 | && fp_lt(yin[period], yin[period+1])) | 886 | && fp_lt(yin[period], yin[period+1])) |
950 | { | 887 | { |
951 | retval = vec_quadint_min(yin, yin_size, period, 1); | 888 | retval = vec_quadint_min(yin, yin_size, period, 1); |
952 | return retval; | 889 | return retval; |
953 | } | 890 | } |
954 | } | 891 | } |
955 | retval = vec_quadint_min(yin, yin_size, | 892 | retval = vec_quadint_min(yin, yin_size, |
956 | vec_min_elem(yin, yin_size), 1); | 893 | vec_min_elem(yin, yin_size), 1); |
957 | return retval; | 894 | return retval; |
958 | /*return FP_ZERO;*/ | 895 | /*return FP_ZERO;*/ |
@@ -960,11 +897,11 @@ fixed ICODE_ATTR pitchyin(int16_t *input, fixed *yin) | |||
960 | 897 | ||
961 | /*-----------------------------------------------------------------*/ | 898 | /*-----------------------------------------------------------------*/ |
962 | 899 | ||
963 | uint32_t ICODE_ATTR buffer_magnitude(int16_t *input) | 900 | static uint32_t ICODE_ATTR buffer_magnitude(int16_t *input) |
964 | { | 901 | { |
965 | unsigned n; | 902 | unsigned n; |
966 | uint64_t tally = 0; | 903 | uint64_t tally = 0; |
967 | const unsigned size = tuner_settings.sample_size; | 904 | const unsigned size = settings.sample_size; |
968 | 905 | ||
969 | /* Operate on only one channel of the stereo signal */ | 906 | /* Operate on only one channel of the stereo signal */ |
970 | for(n = 0; n < size; n+=2) | 907 | for(n = 0; n < size; n+=2) |
@@ -982,7 +919,7 @@ uint32_t ICODE_ATTR buffer_magnitude(int16_t *input) | |||
982 | 919 | ||
983 | /* Stop the recording when the buffer is full */ | 920 | /* Stop the recording when the buffer is full */ |
984 | #ifndef SIMULATOR | 921 | #ifndef SIMULATOR |
985 | void recording_callback(int status, void **start, size_t *size) | 922 | static void recording_callback(int status, void **start, size_t *size) |
986 | { | 923 | { |
987 | int tail = audio_tail ^ 1; | 924 | int tail = audio_tail ^ 1; |
988 | 925 | ||
@@ -1003,13 +940,13 @@ static void record_data(void) | |||
1003 | { | 940 | { |
1004 | #ifndef SIMULATOR | 941 | #ifndef SIMULATOR |
1005 | /* Always record full buffer, even if not required */ | 942 | /* Always record full buffer, even if not required */ |
1006 | rb->pcm_record_data(recording_callback, audio_data[audio_tail], | 943 | rb->pcm_record_data(recording_callback, audio_data[audio_tail], |
1007 | BUFFER_SIZE * sizeof (int16_t)); | 944 | BUFFER_SIZE * sizeof (int16_t)); |
1008 | #endif | 945 | #endif |
1009 | } | 946 | } |
1010 | 947 | ||
1011 | /* The main program loop */ | 948 | /* The main program loop */ |
1012 | void record_and_get_pitch(void) | 949 | static void record_and_get_pitch(void) |
1013 | { | 950 | { |
1014 | int quit=0, button; | 951 | int quit=0, button; |
1015 | bool redraw = true; | 952 | bool redraw = true; |
@@ -1029,18 +966,18 @@ void record_and_get_pitch(void) | |||
1029 | 966 | ||
1030 | record_data(); | 967 | record_data(); |
1031 | 968 | ||
1032 | while(!quit) | 969 | while(!quit) |
1033 | { | 970 | { |
1034 | while (audio_head == audio_tail && !quit) /* wait for the buffer to be filled */ | 971 | while (audio_head == audio_tail && !quit) /* wait for the buffer to be filled */ |
1035 | { | 972 | { |
1036 | button=pluginlib_getaction(HZ/100, plugin_contexts, PLA_ARRAY_COUNT); | 973 | button=pluginlib_getaction(HZ/100, plugin_contexts, PLA_ARRAY_COUNT); |
1037 | 974 | ||
1038 | switch(button) | 975 | switch(button) |
1039 | { | 976 | { |
1040 | case PLA_EXIT: | 977 | case PLA_EXIT: |
1041 | quit=true; | 978 | quit=true; |
1042 | break; | 979 | break; |
1043 | 980 | ||
1044 | case PLA_CANCEL: | 981 | case PLA_CANCEL: |
1045 | rb->pcm_stop_recording(); | 982 | rb->pcm_stop_recording(); |
1046 | quit = main_menu() != 0; | 983 | quit = main_menu() != 0; |
@@ -1050,17 +987,17 @@ void record_and_get_pitch(void) | |||
1050 | record_data(); | 987 | record_data(); |
1051 | } | 988 | } |
1052 | break; | 989 | break; |
1053 | 990 | ||
1054 | break; | 991 | break; |
1055 | } | 992 | } |
1056 | } | 993 | } |
1057 | 994 | ||
1058 | if(!quit) | 995 | if(!quit) |
1059 | { | 996 | { |
1060 | #ifndef SIMULATOR | 997 | #ifndef SIMULATOR |
1061 | /* Only do the heavy lifting if the volume is high enough */ | 998 | /* Only do the heavy lifting if the volume is high enough */ |
1062 | if(buffer_magnitude(audio_data[audio_head]) > | 999 | if(buffer_magnitude(audio_data[audio_head]) > |
1063 | sqr(tuner_settings.volume_threshold * | 1000 | sqr(settings.volume_threshold * |
1064 | rb->sound_max(SOUND_MIC_GAIN))) | 1001 | rb->sound_max(SOUND_MIC_GAIN))) |
1065 | { | 1002 | { |
1066 | waiting = false; | 1003 | waiting = false; |
@@ -1071,7 +1008,7 @@ void record_and_get_pitch(void) | |||
1071 | #endif | 1008 | #endif |
1072 | #ifdef PLUGIN_USE_IRAM | 1009 | #ifdef PLUGIN_USE_IRAM |
1073 | rb->memcpy(iram_audio_data, audio_data[audio_head], | 1010 | rb->memcpy(iram_audio_data, audio_data[audio_head], |
1074 | tuner_settings.sample_size * sizeof (int16_t)); | 1011 | settings.sample_size * sizeof (int16_t)); |
1075 | #endif | 1012 | #endif |
1076 | /* This returns the period of the detected pitch in samples */ | 1013 | /* This returns the period of the detected pitch in samples */ |
1077 | period = pitchyin(iram_audio_data, yin_buffer); | 1014 | period = pitchyin(iram_audio_data, yin_buffer); |
@@ -1080,7 +1017,7 @@ void record_and_get_pitch(void) | |||
1080 | { | 1017 | { |
1081 | display_frequency(fp_period2freq(period)); | 1018 | display_frequency(fp_period2freq(period)); |
1082 | } | 1019 | } |
1083 | else | 1020 | else |
1084 | { | 1021 | { |
1085 | display_frequency(FP_ZERO); | 1022 | display_frequency(FP_ZERO); |
1086 | } | 1023 | } |
@@ -1115,7 +1052,7 @@ void record_and_get_pitch(void) | |||
1115 | } | 1052 | } |
1116 | 1053 | ||
1117 | /* Init recording, tuning, and GUI */ | 1054 | /* Init recording, tuning, and GUI */ |
1118 | void init_everything(void) | 1055 | static void init_everything(void) |
1119 | { | 1056 | { |
1120 | /* Disable all talking before initializing IRAM */ | 1057 | /* Disable all talking before initializing IRAM */ |
1121 | rb->talk_disable(true); | 1058 | rb->talk_disable(true); |
@@ -1123,17 +1060,18 @@ void init_everything(void) | |||
1123 | PLUGIN_IRAM_INIT(rb); | 1060 | PLUGIN_IRAM_INIT(rb); |
1124 | 1061 | ||
1125 | load_settings(); | 1062 | load_settings(); |
1063 | rb->storage_sleep(); | ||
1126 | 1064 | ||
1127 | /* Stop all playback (if no IRAM, otherwise IRAM_INIT would have) */ | 1065 | /* Stop all playback (if no IRAM, otherwise IRAM_INIT would have) */ |
1128 | rb->plugin_get_audio_buffer(NULL); | 1066 | rb->plugin_get_audio_buffer(NULL); |
1129 | 1067 | ||
1130 | /* --------- Init the audio recording ----------------- */ | 1068 | /* --------- Init the audio recording ----------------- */ |
1131 | rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); | 1069 | rb->audio_set_output_source(AUDIO_SRC_PLAYBACK); |
1132 | rb->audio_set_input_source(INPUT_TYPE, SRCF_RECORDING); | 1070 | rb->audio_set_input_source(INPUT_TYPE, SRCF_RECORDING); |
1133 | 1071 | ||
1134 | /* set to maximum gain */ | 1072 | /* set to maximum gain */ |
1135 | rb->audio_set_recording_gain(tuner_settings.record_gain, | 1073 | rb->audio_set_recording_gain(settings.record_gain, |
1136 | tuner_settings.record_gain, | 1074 | settings.record_gain, |
1137 | AUDIO_GAIN_MIC); | 1075 | AUDIO_GAIN_MIC); |
1138 | 1076 | ||
1139 | /* Highest C on piano is approx 4.186 kHz, so we need just over | 1077 | /* Highest C on piano is approx 4.186 kHz, so we need just over |
@@ -1145,15 +1083,15 @@ void init_everything(void) | |||
1145 | rb->pcm_init_recording(); | 1083 | rb->pcm_init_recording(); |
1146 | 1084 | ||
1147 | /* avoid divsion by zero */ | 1085 | /* avoid divsion by zero */ |
1148 | if(tuner_settings.lowest_freq == 0) | 1086 | if(settings.lowest_freq == 0) |
1149 | tuner_settings.lowest_freq = period2freq(BUFFER_SIZE / 4); | 1087 | settings.lowest_freq = period2freq(BUFFER_SIZE / 4); |
1150 | 1088 | ||
1151 | /* GUI */ | 1089 | /* GUI */ |
1152 | #if LCD_DEPTH > 1 | 1090 | #if LCD_DEPTH > 1 |
1153 | front_color = rb->lcd_get_foreground(); | 1091 | front_color = rb->lcd_get_foreground(); |
1154 | #endif | 1092 | #endif |
1155 | rb->lcd_getstringsize("X", &font_w, &font_h); | 1093 | rb->lcd_getstringsize("X", &font_w, &font_h); |
1156 | 1094 | ||
1157 | bar_x_0 = LCD_WIDTH / 2; | 1095 | bar_x_0 = LCD_WIDTH / 2; |
1158 | lbl_x_minus_50 = 0; | 1096 | lbl_x_minus_50 = 0; |
1159 | lbl_x_minus_20 = (LCD_WIDTH / 2) - | 1097 | lbl_x_minus_20 = (LCD_WIDTH / 2) - |
@@ -1174,10 +1112,10 @@ void init_everything(void) | |||
1174 | enum plugin_status plugin_start(const void* parameter) NO_PROF_ATTR | 1112 | enum plugin_status plugin_start(const void* parameter) NO_PROF_ATTR |
1175 | { | 1113 | { |
1176 | (void)parameter; | 1114 | (void)parameter; |
1177 | 1115 | ||
1178 | init_everything(); | 1116 | init_everything(); |
1179 | record_and_get_pitch(); | 1117 | record_and_get_pitch(); |
1180 | save_settings(); | 1118 | save_settings(); |
1181 | 1119 | ||
1182 | return 0; | 1120 | return PLUGIN_OK; |
1183 | } | 1121 | } |