From c38f6072cc43f7abcba5b3476f1496dcf822be99 Mon Sep 17 00:00:00 2001 From: Alexander Levin Date: Sat, 12 Sep 2009 21:19:17 +0000 Subject: UI improvements for the pitch detector (ongoing work by David Johnston from FS#8768) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22685 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/bitmaps/native/SOURCES | 21 + .../bitmaps/native/pitch_notes.128x128x16.bmp | Bin 0 -> 64856 bytes .../bitmaps/native/pitch_notes.128x96x2.bmp | Bin 0 -> 14472 bytes .../bitmaps/native/pitch_notes.132x80x16.bmp | Bin 0 -> 26552 bytes .../bitmaps/native/pitch_notes.160x128x16.bmp | Bin 0 -> 64856 bytes .../bitmaps/native/pitch_notes.160x128x2.bmp | Bin 0 -> 21672 bytes .../bitmaps/native/pitch_notes.176x132x16.bmp | Bin 0 -> 64856 bytes .../bitmaps/native/pitch_notes.176x220x16.bmp | Bin 0 -> 204176 bytes .../bitmaps/native/pitch_notes.220x176x16.bmp | Bin 0 -> 121016 bytes .../bitmaps/native/pitch_notes.320x240x16.bmp | Bin 0 -> 248456 bytes apps/plugins/pitch_detector.c | 567 ++++++++++++--------- 11 files changed, 333 insertions(+), 255 deletions(-) create mode 100644 apps/plugins/bitmaps/native/pitch_notes.128x128x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.128x96x2.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.132x80x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.160x128x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.160x128x2.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.176x132x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.176x220x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.220x176x16.bmp create mode 100644 apps/plugins/bitmaps/native/pitch_notes.320x240x16.bmp (limited to 'apps/plugins') diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES index 4d4cee074a..9f0897d48a 100644 --- a/apps/plugins/bitmaps/native/SOURCES +++ b/apps/plugins/bitmaps/native/SOURCES @@ -826,5 +826,26 @@ rockboxlogo.91x32x1.bmp #endif #endif +/* Pitch detector */ +#if (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) && (LCD_DEPTH >= 16) +pitch_notes.320x240x16.bmp +#elif (LCD_WIDTH >= 220) && (LCD_HEIGHT >= 176) && (LCD_DEPTH >= 16) +pitch_notes.220x176x16.bmp +#elif (LCD_WIDTH >= 176) && (LCD_HEIGHT >= 132) && (LCD_DEPTH >= 16) +pitch_notes.176x132x16.bmp +#elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 16) +pitch_notes.160x128x16.bmp +#elif (LCD_WIDTH >= 128) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 16) +pitch_notes.128x128x16.bmp +#elif (LCD_WIDTH >= 160) && (LCD_HEIGHT >= 128) && (LCD_DEPTH >= 2) +pitch_notes.160x128x2.bmp +#elif (LCD_WIDTH >= 138) && (LCD_HEIGHT >= 110) && (LCD_DEPTH >= 2) +pitch_notes.160x128x2.bmp +#elif (LCD_WIDTH >= 132) && (LCD_HEIGHT >= 80) && (LCD_DEPTH >= 16) +pitch_notes.132x80x16.bmp +#elif (LCD_WIDTH >= 112) && (LCD_HEIGHT >= 64) && (LCD_DEPTH >= 1) +/* There isn't a target currently with this screen and recording ability */ +#endif + #endif /* HAVE_LCD_BITMAP */ diff --git a/apps/plugins/bitmaps/native/pitch_notes.128x128x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.128x128x16.bmp new file mode 100644 index 0000000000..af59728cb7 Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.128x128x16.bmp differ diff --git a/apps/plugins/bitmaps/native/pitch_notes.128x96x2.bmp b/apps/plugins/bitmaps/native/pitch_notes.128x96x2.bmp new file mode 100644 index 0000000000..da5845610c Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.128x96x2.bmp differ diff --git a/apps/plugins/bitmaps/native/pitch_notes.132x80x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.132x80x16.bmp new file mode 100644 index 0000000000..d77d25efe2 Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.132x80x16.bmp differ diff --git a/apps/plugins/bitmaps/native/pitch_notes.160x128x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.160x128x16.bmp new file mode 100644 index 0000000000..af59728cb7 Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.160x128x16.bmp differ diff --git a/apps/plugins/bitmaps/native/pitch_notes.160x128x2.bmp b/apps/plugins/bitmaps/native/pitch_notes.160x128x2.bmp new file mode 100644 index 0000000000..ee400902fa Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.160x128x2.bmp differ diff --git a/apps/plugins/bitmaps/native/pitch_notes.176x132x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.176x132x16.bmp new file mode 100644 index 0000000000..af59728cb7 Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.176x132x16.bmp differ diff --git a/apps/plugins/bitmaps/native/pitch_notes.176x220x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.176x220x16.bmp new file mode 100644 index 0000000000..a95ef0d6cb Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.176x220x16.bmp differ diff --git a/apps/plugins/bitmaps/native/pitch_notes.220x176x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.220x176x16.bmp new file mode 100644 index 0000000000..087235380b Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.220x176x16.bmp differ diff --git a/apps/plugins/bitmaps/native/pitch_notes.320x240x16.bmp b/apps/plugins/bitmaps/native/pitch_notes.320x240x16.bmp new file mode 100644 index 0000000000..5454a67490 Binary files /dev/null and b/apps/plugins/bitmaps/native/pitch_notes.320x240x16.bmp differ diff --git a/apps/plugins/pitch_detector.c b/apps/plugins/pitch_detector.c index 8d0b3b7957..857d74afc4 100644 --- a/apps/plugins/pitch_detector.c +++ b/apps/plugins/pitch_detector.c @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id:$ + * $Id$ * * Copyright (C) 2008 Lechner Michael / smoking gnu * @@ -29,7 +29,6 @@ * recording code to use proper, gapless recording with a callback function * that provides new buffer, instead of stopping and restarting recording * everytime the buffer is full - * - Convert all floating point operations to fixed-point * - Adapt the Yin FFT algorithm, which would reduce complexity from O(n^2) * to O(nlogn), theoretically reducing latency by a factor of ~10. -David * @@ -68,6 +67,8 @@ #include "plugin.h" #include "lib/pluginlib_actions.h" +#include "lib/picture.h" +#include "pluginbitmaps/pitch_notes.h" PLUGIN_HEADER @@ -120,9 +121,10 @@ typedef struct _fixed fixed; #define FP_LOW ((fixed){1}) /* Some defines for converting between period and frequency */ + /* I introduce some divisors in this because the fixed point */ /* variables aren't big enough to hold higher than a certain */ -/* vallue. This loses a bit of precision but it means we */ +/* value. This loses a bit of precision but it means we */ /* don't have to use 32.32 variables (yikes). */ /* With an 18-bit decimal precision, the max value in the */ /* integer part is 8192. Divide 44100 by 7 and it'll fit in */ @@ -157,7 +159,24 @@ typedef struct _fixed fixed; #define LCD_FACTOR (fp_div(int2fixed(LCD_WIDTH), int2fixed(100))) /* The threshold for the YIN algorithm */ -#define YIN_THRESHOLD float2fixed(0.05f) +#define DEFAULT_YIN_THRESHOLD 5 /* 0.10 */ +const fixed yin_threshold_table[] = +{ + float2fixed(0.01), + float2fixed(0.02), + float2fixed(0.03), + float2fixed(0.04), + float2fixed(0.05), + float2fixed(0.10), + float2fixed(0.15), + float2fixed(0.20), + float2fixed(0.25), + float2fixed(0.30), + float2fixed(0.35), + float2fixed(0.40), + float2fixed(0.45), + float2fixed(0.50), +}; /* How loud the audio has to be to start displaying pitch */ /* Must be between 0 and 100 */ @@ -168,6 +187,40 @@ typedef struct _fixed fixed; /* How many decimal places to display for the Hz value */ #define DISPLAY_HZ_PRECISION 100 +/* Where to put the various GUI elements */ +int note_y; +int bar_grad_y; +#define LCD_RES_MIN (LCD_HEIGHT < LCD_WIDTH ? LCD_HEIGHT : LCD_WIDTH) +#define BAR_PADDING (LCD_RES_MIN / 32) +#define BAR_Y (LCD_HEIGHT * 3 / 4) +#define BAR_HEIGHT (LCD_RES_MIN / 4 - BAR_PADDING) +#define BAR_HLINE_Y (BAR_Y - BAR_PADDING) +#define BAR_HLINE_Y2 (BAR_Y + BAR_HEIGHT + BAR_PADDING - 1) +#define HZ_Y 0 +#define GRADUATION 10 /* Subdivisions of the whole 100-cent scale */ + +/* Bitmaps for drawing the note names. These need to have height + <= (bar_grad_y - note_y), or 15/32 * LCD_HEIGHT + */ +#define NUM_NOTE_IMAGES 9 +#define NOTE_INDEX_A 0 +#define NOTE_INDEX_B 1 +#define NOTE_INDEX_C 2 +#define NOTE_INDEX_D 3 +#define NOTE_INDEX_E 4 +#define NOTE_INDEX_F 5 +#define NOTE_INDEX_G 6 +#define NOTE_INDEX_SHARP 7 +#define NOTE_INDEX_FLAT 8 +const struct picture note_bitmaps = +{ + pitch_notes, + BMPWIDTH_pitch_notes, + BMPHEIGHT_pitch_notes, + BMPHEIGHT_pitch_notes/NUM_NOTE_IMAGES +}; + + typedef signed short audio_sample_type; /* It's stereo, so make the buffer twice as big */ audio_sample_type audio_data[BUFFER_SIZE]; @@ -209,21 +262,12 @@ static const fixed lfreqs[12] = /* GUI */ static unsigned back_color, front_color; -static int font_w, font_h; -static int bar_x_minus_50, bar_x_minus_20, bar_x_0, bar_x_20, bar_x_50; -static int letter_y; /* y of the notes letters */ -static int note_bar_y; /* y of the yellow bars (under the notes) */ -static int bar_h; /* height of the yellow (note) and red (error) bars */ -static int freq_y; /* y of the line with the frequency */ -static int error_ticks_y; /* y of the error values (-50, -20, ...) */ -static int error_hline_y; /* y of the top line for error bar */ -static int error_hline_y2;/* y of the bottom line for error bar */ -static int error_bar_y; /* y of the error bar */ -static int error_bar_margin; /* distance between the error bar and the hline */ - -static const char *english_notes[12] = {"A","A#","B","C","C#","D","D#","E", - "F","F#", "G", "G#"}; -static const char gui_letters[8] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', '#'}; +static int font_w,font_h; +static int bar_x_0; +static int lbl_x_minus_50, lbl_x_minus_20, lbl_x_0, lbl_x_20, lbl_x_50; + +static const char *english_notes[] = {"A","A#","B","C","C#","D","D#","E", + "F","F#","G","G#"}; static const char **notes = english_notes; /*Settings for the plugin */ @@ -235,8 +279,117 @@ struct tuner_settings unsigned sample_size; unsigned lowest_freq; unsigned yin_threshold; + bool use_sharps; + bool display_hz; } tuner_settings; +/*=================================================================*/ +/* Settings loading and saving(adapted from the clock plugin) */ +/*=================================================================*/ + +#define SETTINGS_FILENAME PLUGIN_APPS_DIR "/.pitch_settings" + +enum message +{ + MESSAGE_LOADING, + MESSAGE_LOADED, + MESSAGE_ERRLOAD, + MESSAGE_SAVING, + MESSAGE_SAVED, + MESSAGE_ERRSAVE +}; + +enum settings_file_status +{ + LOADED, ERRLOAD, + SAVED, ERRSAVE +}; + +/* The settings as they exist on the hard disk, so that + * we can know at saving time if changes have been made */ +struct tuner_settings hdd_tuner_settings; + +/*---------------------------------------------------------------------*/ + +bool settings_needs_saving(struct tuner_settings* settings) +{ + return(rb->memcmp(settings, &hdd_tuner_settings, sizeof(*settings))); +} + +/*---------------------------------------------------------------------*/ + +void tuner_settings_reset(struct tuner_settings* settings) +{ + settings->volume_threshold = VOLUME_THRESHOLD; + settings->record_gain = rb->global_settings->rec_mic_gain; + settings->sample_size = BUFFER_SIZE; + settings->lowest_freq = period2freq(BUFFER_SIZE / 4); + settings->yin_threshold = DEFAULT_YIN_THRESHOLD; + settings->use_sharps = true; + settings->display_hz = false; +} + +/*---------------------------------------------------------------------*/ + +void tuner_settings_reset_query(int yes) +{ + if(yes) + tuner_settings_reset(&tuner_settings); +} + +/*---------------------------------------------------------------------*/ + +enum settings_file_status tuner_settings_load(struct tuner_settings* settings, + char* filename) +{ + int fd = rb->open(filename, O_RDONLY); + if(fd >= 0){ /* does file exist? */ + /* basic consistency check */ + if(rb->filesize(fd) == sizeof(*settings)){ + rb->read(fd, settings, sizeof(*settings)); + rb->close(fd); + rb->memcpy(&hdd_tuner_settings, settings, sizeof(*settings)); + return(LOADED); + } + } + /* Initializes the settings with default values at least */ + tuner_settings_reset(settings); + return(ERRLOAD); +} + +/*---------------------------------------------------------------------*/ + +enum settings_file_status tuner_settings_save(struct tuner_settings* settings, + char* filename) +{ + int fd = rb->creat(filename); + if(fd >= 0){ /* does file exist? */ + rb->write (fd, settings, sizeof(*settings)); + rb->close(fd); + return(SAVED); + } + return(ERRSAVE); +} + +/*---------------------------------------------------------------------*/ + +void load_settings(void) +{ + tuner_settings_load(&tuner_settings, SETTINGS_FILENAME); + + rb->storage_sleep(); +} + +/*---------------------------------------------------------------------*/ + +void save_settings(void) +{ + if(!settings_needs_saving(&tuner_settings)) + return; + + tuner_settings_save(&tuner_settings, SETTINGS_FILENAME); +} + /*=================================================================*/ /* MENU */ /*=================================================================*/ @@ -252,27 +405,9 @@ const struct button_mapping* plugin_contexts[]={ }; #define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0]) -fixed yin_threshold_table[] = -{ - float2fixed(0.01), - float2fixed(0.02), - float2fixed(0.03), - float2fixed(0.04), - float2fixed(0.05), - float2fixed(0.10), - float2fixed(0.15), - float2fixed(0.20), - float2fixed(0.25), - float2fixed(0.30), - float2fixed(0.35), - float2fixed(0.40), - float2fixed(0.45), - float2fixed(0.50), -}; - -#define DEFAULT_YIN_THRESHOLD 5 /* 0.10 */ - /* Option strings */ + +/* This has to match yin_threshold_table */ static const struct opt_items yin_threshold_text[] = { { "0.01", -1 }, @@ -291,6 +426,18 @@ static const struct opt_items yin_threshold_text[] = { "0.50", -1 }, }; +static const struct opt_items accidental_text[] = +{ + { "Flat", -1 }, + { "Sharp", -1 }, +}; + +static const struct opt_items noyes_text[] = +{ + { "No", -1 }, + { "Yes", -1 } +}; + void set_min_freq(int new_freq) { tuner_settings.sample_size = freq2period(new_freq) * 4; @@ -311,6 +458,7 @@ bool main_menu(void) bool done = false; bool exit_tuner=false; int choice; + bool reset = false; MENUITEM_STRINGLIST(menu,"Tuner Settings",NULL, "Return to Tuner", @@ -318,6 +466,9 @@ bool main_menu(void) "Listening Volume", "Lowest Frequency", "Algorithm Pickiness", + "Accidentals", + "Display Frequency (Hz)", + "Reset Settings", "Quit"); while(!done) @@ -353,11 +504,25 @@ bool main_menu(void) NULL); break; case 5: - exit_tuner = true; - done = true; + rb->set_option("Display Accidentals As", + &tuner_settings.use_sharps, + BOOL, accidental_text, 2, NULL); break; - case 0: - default: /* Return to the tuner */ + case 6: + rb->set_option("Display Frequency (Hz)", + &tuner_settings.display_hz, + BOOL, noyes_text, 2, NULL); + break; + case 7: + rb->set_option("Reset Tuner Settings?", + &reset, + BOOL, noyes_text, 2, tuner_settings_reset_query); + break; + case 8: + exit_tuner = true; + case 0: + default: + /* Return to the tuner */ done = true; break; @@ -366,103 +531,6 @@ bool main_menu(void) return(exit_tuner); } -/*=================================================================*/ -/* Settings loading and saving(adapted from the clock plugin) */ -/*=================================================================*/ - -#define SETTINGS_FILENAME PLUGIN_APPS_DIR "/.pitch_settings" - -enum message -{ - MESSAGE_LOADING, - MESSAGE_LOADED, - MESSAGE_ERRLOAD, - MESSAGE_SAVING, - MESSAGE_SAVED, - MESSAGE_ERRSAVE -}; - -enum settings_file_status -{ - LOADED, ERRLOAD, - SAVED, ERRSAVE -}; - -/* The settings as they exist on the hard disk, so that - * we can know at saving time if changes have been made */ -struct tuner_settings hdd_tuner_settings; - -/*---------------------------------------------------------------------*/ - -bool settings_needs_saving(struct tuner_settings* settings) -{ - return(rb->memcmp(settings, &hdd_tuner_settings, sizeof(*settings))); -} - -/*---------------------------------------------------------------------*/ - -void tuner_settings_reset(struct tuner_settings* settings) -{ - settings->volume_threshold = VOLUME_THRESHOLD; - settings->record_gain = rb->global_settings->rec_mic_gain; - settings->sample_size = BUFFER_SIZE; - settings->lowest_freq = period2freq(BUFFER_SIZE / 4); - settings->yin_threshold = DEFAULT_YIN_THRESHOLD; -} - -/*---------------------------------------------------------------------*/ - -enum settings_file_status tuner_settings_load(struct tuner_settings* settings, - char* filename) -{ - int fd = rb->open(filename, O_RDONLY); - if(fd >= 0){ /* does file exist? */ - /* basic consistency check */ - if(rb->filesize(fd) == sizeof(*settings)){ - rb->read(fd, settings, sizeof(*settings)); - rb->close(fd); - rb->memcpy(&hdd_tuner_settings, settings, sizeof(*settings)); - return(LOADED); - } - } - /* Initializes the settings with default values at least */ - tuner_settings_reset(settings); - return(ERRLOAD); -} - -/*---------------------------------------------------------------------*/ - -enum settings_file_status tuner_settings_save(struct tuner_settings* settings, - char* filename) -{ - int fd = rb->creat(filename); - if(fd >= 0){ /* does file exist? */ - rb->write (fd, settings, sizeof(*settings)); - rb->close(fd); - return(SAVED); - } - return(ERRSAVE); -} - -/*---------------------------------------------------------------------*/ - -void load_settings(void) -{ - tuner_settings_load(&tuner_settings, SETTINGS_FILENAME); - - rb->storage_sleep(); -} - -/*---------------------------------------------------------------------*/ - -void save_settings(void) -{ - if(!settings_needs_saving(&tuner_settings)) - return; - - tuner_settings_save(&tuner_settings, SETTINGS_FILENAME); -} - /*=================================================================*/ /* Binary Log */ /*=================================================================*/ @@ -525,15 +593,13 @@ void print_int_xy(int x, int y, int v) rb->lcd_set_foreground(front_color); rb->snprintf(temp,20,"%d",v); rb->lcd_putsxy(x,y,temp); - rb->lcd_update(); } -/* Print out the frequency etc - will be removed later on */ +/* Print out the frequency etc */ void print_str(char* s) { rb->lcd_set_foreground(front_color); - rb->lcd_putsxy(0, freq_y, s); - rb->lcd_update(); + rb->lcd_putsxy(0, HZ_Y, s); } /* What can I say? Read the function name... */ @@ -548,9 +614,67 @@ void print_char_xy(int x, int y, char c) rb->lcd_putsxy(x, y, temp); } +/* Draw the note bitmap */ +void draw_note(const char *note) +{ + int i; + int note_x = (LCD_WIDTH - BMPWIDTH_pitch_notes) / 2; + int accidental_index = NOTE_INDEX_SHARP; + + i = note[0]-'A'; + + if(note[1] == '#') + { + if(!(tuner_settings.use_sharps)) + { + i = (i + 1) % 7; + accidental_index = NOTE_INDEX_FLAT; + } + + vertical_picture_draw_sprite(rb->screens[0], + ¬e_bitmaps, + accidental_index, + LCD_WIDTH / 2, + note_y); + note_x = LCD_WIDTH / 2 - BMPWIDTH_pitch_notes; + } + + vertical_picture_draw_sprite(rb->screens[0], ¬e_bitmaps, i, + note_x, + note_y); +} /* Draw the red bar and the white lines */ void draw_bar(fixed wrong_by_cents) { + unsigned n; + int x; + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(LCD_RGBPACK(255,255,255)); /* Color screens */ +#elif LCD_DEPTH > 1 + rb->lcd_set_foreground(LCD_BLACK); /* Greyscale screens */ +#else + rb->lcd_set_foreground(LCD_BLACK); /* Black and white screens */ +#endif + + rb->lcd_hline(0,LCD_WIDTH-1, BAR_HLINE_Y); + rb->lcd_hline(0,LCD_WIDTH-1, BAR_HLINE_Y2); + + /* Draw graduation lines on the off-by readout */ + for(n = 0; n <= GRADUATION; n++) + { + x = (LCD_WIDTH * n + GRADUATION / 2) / GRADUATION; + if (x >= LCD_WIDTH) + x = LCD_WIDTH - 1; + rb->lcd_vline(x, BAR_HLINE_Y, BAR_HLINE_Y2); + } + + print_int_xy(lbl_x_minus_50 ,bar_grad_y, -50); + print_int_xy(lbl_x_minus_20 ,bar_grad_y, -20); + print_int_xy(lbl_x_0 ,bar_grad_y, 0); + print_int_xy(lbl_x_20 ,bar_grad_y, 20); + print_int_xy(lbl_x_50 ,bar_grad_y, 50); + #ifdef HAVE_LCD_COLOR rb->lcd_set_foreground(LCD_RGBPACK(255,0,0)); /* Color screens */ #elif LCD_DEPTH > 1 @@ -561,66 +685,16 @@ void draw_bar(fixed wrong_by_cents) if (fp_gt(wrong_by_cents, FP_ZERO)) { - rb->lcd_fillrect(bar_x_0, error_bar_y, - fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)), bar_h); + rb->lcd_fillrect(bar_x_0, BAR_Y, + fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)), BAR_HEIGHT); } else { rb->lcd_fillrect(bar_x_0 + fixed2int(fp_mul(wrong_by_cents,LCD_FACTOR)), - error_bar_y, + BAR_Y, fixed2int(fp_mul(wrong_by_cents, LCD_FACTOR)) * -1, - bar_h); + BAR_HEIGHT); } -#ifdef HAVE_LCD_COLOR - rb->lcd_set_foreground(LCD_RGBPACK(255,255,255)); /* Color screens */ -#elif LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_BLACK); /* Greyscale screens */ -#else - rb->lcd_set_foreground(LCD_BLACK); /* Black and white screens */ -#endif - - rb->lcd_hline(0,LCD_WIDTH-1, error_hline_y); - rb->lcd_hline(0,LCD_WIDTH-1, error_hline_y2); - rb->lcd_vline(LCD_WIDTH / 2, error_hline_y, error_hline_y2); - - print_int_xy(bar_x_minus_50 , error_ticks_y, -50); - print_int_xy(bar_x_minus_20 , error_ticks_y, -20); - print_int_xy(bar_x_0 , error_ticks_y, 0); - print_int_xy(bar_x_20 , error_ticks_y, 20); - print_int_xy(bar_x_50 , error_ticks_y, 50); -} - -/* Print the letters A-G and the # on the screen */ -void draw_letters(void) -{ - int i; - - rb->lcd_set_foreground(front_color); - - for (i=0; i<8; i++) - { - print_char_xy(i*(LCD_WIDTH / 8 ) + font_w, letter_y, gui_letters[i]); - } -} - -/* Draw the yellow point(s) below the letters and the '#' */ -void draw_points(const char *s) -{ - int i; - - i = s[0]-'A'; -#ifdef HAVE_LCD_COLOR - rb->lcd_set_foreground(LCD_RGBPACK(255,255,0)); /* Color screens */ -#elif LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_DARKGRAY); /* Grey screens */ -#else - rb->lcd_set_foreground(LCD_BLACK); /* Black and White screens */ -#endif - - rb->lcd_fillrect(i*(LCD_WIDTH / 8 ) + font_w, note_bar_y, font_w, font_h); - - if (s[1] == '#') - rb->lcd_fillrect(7*(LCD_WIDTH / 8 ) + font_w, note_bar_y, font_w, font_h); } /* Calculate how wrong the note is and draw the GUI */ @@ -629,7 +703,6 @@ void display_frequency (fixed freq) fixed ldf, mldf; fixed lfreq, nfreq; int i, note = 0; - bool draw_freq; char str_buf[30]; if (fp_lt(freq, FP_LOW)) @@ -663,26 +736,19 @@ void display_frequency (fixed freq) ldf=fp_mul(int2fixed(1200), log(fp_div(freq,nfreq))); - draw_freq = (fp_round(freq) != 0); - if (draw_freq) - { - rb->snprintf(str_buf,30, "%s : %d cents (%d.%dHz)", - notes[note], fp_round(ldf) ,fixed2int(freq), - fp_round(fp_mul(fp_frac(freq), - int2fixed(DISPLAY_HZ_PRECISION)))); - } - else - { - ldf = FP_ZERO; /* prevents red bar at -32 cents when freq= 0*/ - } - rb->lcd_clear_display(); draw_bar(ldf); /* The red bar */ - draw_letters(); /* The A-G letters and the # */ - if (draw_freq) + if(fp_round(freq) != 0) { - draw_points(notes[note]); /* The yellow point(s) */ - print_str(str_buf); + draw_note(notes[note]); + if(tuner_settings.display_hz) + { + rb->snprintf(str_buf,30, "%s : %d cents (%d.%02dHz)", + notes[note], fp_round(ldf) ,fixed2int(freq), + fp_round(fp_mul(fp_frac(freq), + int2fixed(DISPLAY_HZ_PRECISION)))); + print_str(str_buf); + } } rb->lcd_update(); } @@ -796,7 +862,7 @@ fixed vec_quadint_min(fixed *x, unsigned bufsize, unsigned pos, unsigned span) resold = res; } else - { + { /* exactpos += (frac-QUADINT_STEP)*span - span/2.0f; */ exactpos = fp_add(exactpos, fp_sub( @@ -898,20 +964,28 @@ void record_and_get_pitch(void) long timer; char debug_string[20]; */ +#ifndef SIMULATOR fixed period; bool waiting = false; +#endif while(!quit) { +#ifndef SIMULATOR /* Start recording */ rb->pcm_record_data(recording_callback, (void *) audio_data, (size_t) tuner_settings.sample_size * sizeof(audio_sample_type)); +#endif recording=1; while (recording && !quit) /* wait for the buffer to be filled */ { rb->yield(); +#ifdef SIMULATOR + /* Only do this loop once if this is the simulator */ + recording = 0; +#endif button=pluginlib_getaction(0, plugin_contexts, PLA_ARRAY_COUNT); switch(button) { @@ -923,8 +997,8 @@ void record_and_get_pitch(void) case PLA_MENU: if(main_menu()) quit=true; + else redraw = true; rb->yield(); - redraw = true; break; default: @@ -934,11 +1008,9 @@ void record_and_get_pitch(void) } } - /* Let's keep track of how long this takes */ - /* timer = *(rb->current_tick); */ - if(!quit) { +#ifndef SIMULATOR /* Only do the heavy lifting if the volume is high enough */ if(buffer_magnitude(audio_data) > sqr(tuner_settings.volume_threshold * @@ -946,9 +1018,9 @@ void record_and_get_pitch(void) { if(waiting) { - #ifdef HAVE_ADJUSTABLE_CPU_FREQ +#ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(true); - #endif +#endif waiting = false; } @@ -971,26 +1043,16 @@ void record_and_get_pitch(void) { waiting = true; redraw = false; - #ifdef HAVE_ADJUSTABLE_CPU_FREQ +#ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(false); - #endif +#endif /*rb->backlight_off();*/ display_frequency(FP_ZERO); } - - /*rb->snprintf(debug_string, 20, "%x,%x", - audio_data[50], audio_data[52]); - rb->lcd_putsxy(0, 40, debug_string); - rb->lcd_update(); - */ - - /* Print out how long it took to find the pitch */ - /* - rb->snprintf(debug_string, 20, "latency: %ld", - *(rb->current_tick) - timer); - rb->lcd_putsxy(0, 40, debug_string); - rb->lcd_update(); - */ +#else /* SIMULATOR */ + /* Display a preselected frequency */ + display_frequency(int2fixed(445)); +#endif } } rb->pcm_close_recording(); @@ -1023,23 +1085,18 @@ void init_everything(void) front_color = rb->lcd_get_foreground(); rb->lcd_getstringsize("X", &font_w, &font_h); - bar_x_minus_50 = 0; - bar_x_minus_20 = (LCD_WIDTH / 2) - + bar_x_0 = LCD_WIDTH / 2; + lbl_x_minus_50 = 0; + lbl_x_minus_20 = (LCD_WIDTH / 2) - fixed2int(fp_mul(LCD_FACTOR, int2fixed(20))) - font_w; - bar_x_0 = LCD_WIDTH / 2; - bar_x_20 = (LCD_WIDTH / 2) + - fixed2int(fp_mul(LCD_FACTOR, int2fixed(20))) - font_w; - bar_x_50 = LCD_WIDTH - 2 * font_w; - - letter_y = 10; - note_bar_y = letter_y + font_h; - bar_h = font_h; - freq_y = note_bar_y + bar_h + 3; - error_ticks_y = freq_y + font_h + 8; - error_hline_y = error_ticks_y + font_h + 2; - error_bar_margin = 2; - error_bar_y = error_hline_y + error_bar_margin; - error_hline_y2 = error_bar_y + bar_h + error_bar_margin; + lbl_x_0 = (LCD_WIDTH - font_w) / 2; + lbl_x_20 = (LCD_WIDTH / 2) + + fixed2int(fp_mul(LCD_FACTOR, int2fixed(20))) - font_w; + lbl_x_50 = LCD_WIDTH - 2 * font_w; + + bar_grad_y = BAR_Y - BAR_PADDING - font_h; + /* Put the note right between the top and bottom text elements */ + note_y = ((font_h + bar_grad_y - note_bitmaps.slide_height) / 2); } -- cgit v1.2.3