From be90f74e89978224a169c793d4e688867dc38b41 Mon Sep 17 00:00:00 2001 From: Peter D'Hoye Date: Wed, 3 Mar 2010 22:16:08 +0000 Subject: Histogram display on recording screen. Based on the work of Jvo Studer in FS #5021 but reduced and reworked since the recording screen code changed quite a bit since his patch. For now enabled on iriver h1x0 and h3x0 only. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25007 a1c6a512-1295-4272-9138-f99709370657 --- apps/recorder/peakmeter.c | 36 +++---- apps/recorder/recording.c | 238 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 209 insertions(+), 65 deletions(-) (limited to 'apps/recorder') diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c index fc68ce4267..8f32a837a7 100644 --- a/apps/recorder/peakmeter.c +++ b/apps/recorder/peakmeter.c @@ -66,7 +66,7 @@ static int pm_cur_left; /* current values (last peak_meter_peek) */ static int pm_cur_right; static int pm_max_left; /* maximum values between peak meter draws */ static int pm_max_right; -#ifdef HAVE_AGC +#if defined(HAVE_AGC) || defined(HAVE_RECORDING_HISTOGRAM) static int pm_peakhold_left; /* max. peak values between peakhold calls */ static int pm_peakhold_right; /* used for AGC and histogram display */ #endif @@ -799,9 +799,16 @@ static int peak_meter_read_l(void) { /* pm_max_left contains the maximum of all peak values that were read by peak_meter_peek since the last call of peak_meter_read_l */ - int retval = pm_max_left; + int retval; + +#if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC) + srand(current_tick); + pm_max_left = rand()%MAX_PEAK; +#endif -#ifdef HAVE_AGC + retval = pm_max_left; + +#if defined(HAVE_RECORDING_HISTOGRAM) || defined(HAVE_AGC) /* store max peak value for peak_meter_get_peakhold_x readout */ pm_peakhold_left = MAX(pm_max_left, pm_peakhold_left); #endif @@ -812,11 +819,6 @@ static int peak_meter_read_l(void) get fooled by an old maximum value */ pm_max_left = pm_cur_left; -#if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC) - srand(current_tick); - retval = rand()%MAX_PEAK; -#endif - return retval; } @@ -830,9 +832,16 @@ static int peak_meter_read_r(void) { /* peak_meter_r contains the maximum of all peak values that were read by peak_meter_peek since the last call of peak_meter_read_r */ - int retval = pm_max_right; + int retval; + +#if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC) + srand(current_tick); + pm_max_right = rand()%MAX_PEAK; +#endif -#ifdef HAVE_AGC + retval = pm_max_right; + +#if defined(HAVE_RECORDING_HISTOGRAM) || defined(HAVE_AGC) /* store max peak value for peak_meter_get_peakhold_x readout */ pm_peakhold_right = MAX(pm_max_right, pm_peakhold_right); #endif @@ -843,15 +852,10 @@ static int peak_meter_read_r(void) get fooled by an old maximum value */ pm_max_right = pm_cur_right; -#if defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC) - srand(current_tick); - retval = rand()%MAX_PEAK; -#endif - return retval; } -#ifdef HAVE_AGC +#if defined(HAVE_AGC) || defined(HAVE_RECORDING_HISTOGRAM) /** * Reads out the current peak-hold values since the last call. * This is used by the histogram feature in the recording screen. diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c index 8b52b7cac2..2c8e473c11 100644 --- a/apps/recorder/recording.c +++ b/apps/recorder/recording.c @@ -219,7 +219,6 @@ static char path_buffer[MAX_PATH]; * overflow every 13 years 8-) */ static long peak_time = 0; -static long hist_time = 0; static short peak_valid_mem[4]; #define BAL_MEM_SIZE 24 @@ -269,6 +268,38 @@ static short agc_baltime = 0; /* AGC maximum gain */ static short agc_maxgain; #endif /* HAVE_AGC */ +#if defined(HAVE_AGC) || defined(HAVE_RECORDING_HISTOGRAM) +static long hist_time = 0; +#endif /* HAVE_AGC or HAVE_RECORDING_HISTOGRAM */ +/* Histogram data */ +/* TO DO: move some of this stuff inside the recording function? */ +#ifdef HAVE_RECORDING_HISTOGRAM +static int hist_l = 0; +static int hist_r = 0; +#define HIST_Y (hist_pos_y+hist_size_h-1) +#define HIST_W (LCD_WIDTH / 2 - 4) +#if LCD_DEPTH > 1 +#ifdef HAVE_LCD_COLOR +#define LCD_BAL_L LCD_RGBPACK(0, 0, 255) +#define LCD_BAL_R LCD_RGBPACK(204, 0, 0) +#define LCD_HIST_OVER LCD_RGBPACK(204, 0, 0) +#define LCD_HIST_HI LCD_RGBPACK(255, 204, 0) +#define LCD_HIST_OK LCD_RGBPACK(51, 153, 0) +#else /* HAVE_LCD_COLOR */ +#define LCD_BATT_OK LCD_BLACK +#define LCD_BATT_LO LCD_DARKGRAY +#define LCD_DISK_OK LCD_BLACK +#define LCD_DISK_LO LCD_DARKGRAY +#define LCD_HIST_OVER LCD_BLACK +#define LCD_HIST_OK LCD_DARKGRAY +#define LCD_BAL LCD_DARKGRAY +#endif /* HAVE_LCD_COLOR */ +#else /* LCD_DEPTH > 1 */ +#define LCD_HIST_OVER LCD_DEFAULT_FG +#define LCD_HIST_OK LCD_DEFAULT_FG +#define LCD_BAL LCD_DEFAULT_FG +#endif /* LCD_DEPTH > 1 */ +#endif /* HAVE_RECORDING_HISTOGRAM */ static void set_gain(void) { @@ -317,6 +348,13 @@ static bool read_peak_levels(int *peak_l, int *peak_r, int *balance) *balance += balance_mem[i]; *balance = *balance / BAL_MEM_SIZE; +#ifdef HAVE_RECORDING_HISTOGRAM + if (*peak_l > hist_l) + hist_l = *peak_l; + if (*peak_r > hist_r) + hist_r = *peak_r; +#endif + return true; } @@ -1015,7 +1053,6 @@ bool recording_screen(bool no_source) #endif #ifdef HAVE_AGC bool peak_read = false; - bool peak_valid = false; int peak_l, peak_r; int balance = 0; #endif @@ -1025,9 +1062,21 @@ bool recording_screen(bool no_source) int pm_h[NB_SCREENS]; /* peakmeter height */ int trig_ypos[NB_SCREENS]; /* trigger bar y pos */ int trig_width[NB_SCREENS]; /* trigger bar width */ + int top_height_req[NB_SCREENS]; /* required height for top half */ bool compact_view[NB_SCREENS]; /* tweak layout tiny screens / big fonts */ - struct gui_synclist lists; /* the list in the bottom vp */ +#if defined(HAVE_AGC) || defined(HAVE_RECORDING_HISTOGRAM) + bool peak_valid = false; +#endif +#if defined(HAVE_RECORDING_HISTOGRAM) + unsigned short hist_pos_y = 0; + unsigned short hist_size_h = 0; + int history_pos = 0; + short hist_time_interval = 1; /* 1, 2, 4, 8 */ + unsigned char history_l[HIST_W]; + unsigned char history_r[HIST_W]; + const char hist_level_marks[6] = { 29, 26, 23, 17, 9, 2}; +#endif #ifdef HAVE_FMRADIO_REC int prev_rec_source = global_settings.rec_source; /* detect source change */ #endif @@ -1084,49 +1133,6 @@ bool recording_screen(bool no_source) rec_init_filename(); #endif - /* viewport init and calculations that only needs to be done once */ - FOR_NB_SCREENS(i) - { - struct viewport *v; - /* top vp, 4 lines, force sys font if total screen < 6 lines - NOTE: one could limit the list to 1 line and get away with 5 lines */ - v = &vp_top[i]; - viewport_set_defaults(v, i); - if (viewport_get_nb_lines(v) < 4) - { - /* compact needs 4 lines total */ - v->font = FONT_SYSFIXED; - compact_view[i] = false; - } - else - { - if (viewport_get_nb_lines(v) < (4+2)) /*top=4,list=2*/ - compact_view[i] = true; - else - compact_view[i] = false; - } - vp_list[i] = *v; /* get a copy now so it can be sized more easily */ - v->height = (font_get(v->font)->height)*(compact_view[i] ? 3 : 4); - - /* list section, rest of the screen */ - vp_list[i].y += vp_top[i].height; - vp_list[i].height -= vp_top[i].height; - screens[i].set_viewport(&vp_top[i]); /* req for next calls */ - - screens[i].getstringsize("W", &w, &h); - pm_y[i] = font_get(vp_top[i].font)->height * 2; - trig_ypos[i] = font_get(vp_top[i].font)->height * 3; - if(compact_view[i]) - trig_ypos[i] -= (font_get(vp_top[i].font)->height)/2; - } - - /* init the bottom list */ - gui_synclist_init(&lists, reclist_get_name, NULL, false, 1, vp_list); - gui_synclist_set_title(&lists, NULL, Icon_NOICON); - - - send_event(GUI_EVENT_ACTIONUPDATE, (void*)1); /* force a redraw */ - /* start of the loop: we stay in this loop until user quits recscreen */ while(done <= 0) { @@ -1143,6 +1149,65 @@ bool recording_screen(bool no_source) prev_rec_source = global_settings.rec_source; #endif + /* viewport init and calculations that only needs to be done once */ + FOR_NB_SCREENS(i) + { + struct viewport *v; + /* top vp, 4 lines, force sys font if total screen < 6 lines + NOTE: one could limit the list to 1 line and get away with 5 lines */ + top_height_req[i] = 4; +#if defined(HAVE_RECORDING_HISTOGRAM) + if((global_settings.rec_histogram_interval) && (!i)) + top_height_req[i] += 1; /* use one line for histogram */ + hist_time_interval = 1 << global_settings.rec_histogram_interval; +#endif + v = &vp_top[i]; + viewport_set_defaults(v, i); + if (viewport_get_nb_lines(v) < top_height_req[i]) + { + /* compact needs 4 lines total */ + v->font = FONT_SYSFIXED; + compact_view[i] = false; + } + else + { + /*top=4,list=2*/ + if (viewport_get_nb_lines(v) < (top_height_req[i]+2)) + compact_view[i] = true; + else + compact_view[i] = false; + } + vp_list[i] = *v; /* get a copy now so it can be sized more easily */ + v->height = (font_get(v->font)->height)*(compact_view[i] ? 3 : + top_height_req[i]); + + /* list section, rest of the screen */ + vp_list[i].y += vp_top[i].height; + vp_list[i].height -= vp_top[i].height; + screens[i].set_viewport(&vp_top[i]); /* req for next calls */ + + screens[i].getstringsize("W", &w, &h); + pm_y[i] = font_get(vp_top[i].font)->height * 2; + trig_ypos[i] = font_get(vp_top[i].font)->height * 3; + if(compact_view[i]) + trig_ypos[i] -= (font_get(vp_top[i].font)->height)/2; + } + + /* init the bottom list */ + gui_synclist_init(&lists, reclist_get_name, NULL, false, 1, vp_list); + gui_synclist_set_title(&lists, NULL, Icon_NOICON); + + send_event(GUI_EVENT_ACTIONUPDATE, (void*)1); /* force a redraw */ + +#if defined(HAVE_RECORDING_HISTOGRAM) + history_pos = 0; + hist_pos_y = (compact_view[0] ? 3 : 4) * (font_get(vp_top[0].font)->height) + + 1; + hist_size_h = font_get(vp_top[0].font)->height - 2; + memset(history_l, 0, sizeof(unsigned char)*HIST_W); + memset(history_r, 0, sizeof(unsigned char)*HIST_W); +#endif + FOR_NB_SCREENS(i) { pm_x[i] = 0; @@ -1673,12 +1738,11 @@ bool recording_screen(bool no_source) unsigned int dseconds, dhours, dminutes; unsigned long num_recorded_bytes, dsize, dmb; - FOR_NB_SCREENS(i) { screens[i].set_viewport(&vp_top[i]); screens[i].clear_viewport(); - } + } update_countdown = 5; last_seconds = seconds; @@ -1796,6 +1860,83 @@ bool recording_screen(bool no_source) } } +#ifdef HAVE_RECORDING_HISTOGRAM + if(global_settings.rec_histogram_interval) + { + if (peak_valid && !(hist_time % hist_time_interval) && hist_l) + { + history_l[history_pos] = hist_l * hist_size_h / 32767; + history_r[history_pos] = hist_r * hist_size_h / 32767; + history_pos = (history_pos + 1) % HIST_W; + history_l[history_pos] = history_r[history_pos] = 0; + history_l[(history_pos + 1) % HIST_W] = 0; + history_r[(history_pos + 1) % HIST_W] = 0; + hist_l = 0; + hist_r = 0; + } + lcd_set_drawmode(DRMODE_SOLID); + lcd_drawrect(0, hist_pos_y - 1, + HIST_W + 2, hist_size_h + 1); + lcd_drawrect(HIST_W + 6, hist_pos_y - 1, + HIST_W + 2, hist_size_h + 1); + lcd_set_drawmode(DRMODE_FG); +#ifdef HAVE_LCD_COLOR + for (i = 0; i < HIST_W; i++) + { + if (history_l[i]) + { + if (history_l[i] == hist_size_h) + lcd_set_foreground(LCD_HIST_OVER); + else if (history_l[i] > hist_level_marks[1]) + lcd_set_foreground(LCD_HIST_HI); + else + lcd_set_foreground(LCD_HIST_OK); + lcd_vline(1 + i, HIST_Y-1, HIST_Y - history_l[i]); + } + if (history_r[i]) + { + if (history_r[i] == hist_size_h) + lcd_set_foreground(LCD_HIST_OVER); + else if (history_r[i] > hist_level_marks[1]) + lcd_set_foreground(LCD_HIST_HI); + else + lcd_set_foreground(LCD_HIST_OK); + lcd_vline(HIST_W+7 + i, HIST_Y-1, HIST_Y - history_r[i]); + } + } +#else + for (i = 0; i < HIST_W; i++) + { + if (history_l[i]) + { + if (history_l[i] == hist_size_h) + lcd_set_foreground(LCD_HIST_OVER); + else + lcd_set_foreground(LCD_HIST_OK); + lcd_vline(1 + i, HIST_Y-1, HIST_Y - history_l[i]); + } + if (history_r[i]) + { + if (history_r[i] == hist_size_h) + lcd_set_foreground(LCD_HIST_OVER); + else + lcd_set_foreground(LCD_HIST_OK); + lcd_vline(HIST_W+7 + i, HIST_Y-1, HIST_Y - history_r[i]); + } + } +#endif /* HAVE_LCD_COLOR */ + lcd_set_foreground( +#ifdef HAVE_LCD_COLOR + global_settings.fg_color); +#else + LCD_DEFAULT_FG); +#endif + for (i = 0; i < 6; i++) + lcd_hline(HIST_W + 3, HIST_W + 4, + HIST_Y - hist_level_marks[i]); + } +#endif /* HAVE_RECORDING_HISTOGRAM */ + #ifdef HAVE_AGC hist_time++; #endif @@ -1922,7 +2063,6 @@ rec_abort: FOR_NB_SCREENS(i) screens[i].setfont(FONT_UI); - /* if the directory was created or recording happened, make sure the browser is updated */ -- cgit v1.2.3