summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/features.txt4
-rw-r--r--apps/lang/english.lang35
-rw-r--r--apps/menus/recording_menu.c25
-rw-r--r--apps/recorder/peakmeter.c36
-rw-r--r--apps/recorder/recording.c238
-rw-r--r--apps/settings.h3
-rw-r--r--apps/settings_list.c7
-rw-r--r--firmware/export/config/iriverh120.h2
-rw-r--r--firmware/export/config/iriverh300.h2
9 files changed, 286 insertions, 66 deletions
diff --git a/apps/features.txt b/apps/features.txt
index f94a74cd19..242d2d4386 100644
--- a/apps/features.txt
+++ b/apps/features.txt
@@ -148,6 +148,10 @@ recording_mic
#endif
#endif
+#if defined(HAVE_RECORDING_HISTOGRAM)
+recording_histogram
+#endif
+
#if defined(HAVE_REMOTE_LCD)
remote
remote_lcd_invert
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index ecbd41505d..45c82fe378 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -13349,3 +13349,38 @@
remote: "Remote Screen"
</voice>
</phrase>
+<phrase>
+ id: LANG_RECORDING_HISTOGRAM_MODE
+ desc: in record settings menu
+ user: core
+ <source>
+ *: none
+ recording_histogram: "Histogram mode"
+ </source>
+ <dest>
+ *: none
+ recording_histogram: "Histogram mode"
+ </dest>
+ <voice>
+ *: none
+ recording_histogram: "Histogram mode"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_RECORDING_HISTOGRAM_INTERVAL
+ desc: in record settings menu
+ user: core
+ <source>
+ *: none
+ recording_histogram: "Histogram interval"
+ </source>
+ <dest>
+ *: none
+ recording_histogram: "Histogram interval"
+ </dest>
+ <voice>
+ *: none
+ recording_histogram: "Histogram interval"
+ </voice>
+</phrase>
+
diff --git a/apps/menus/recording_menu.c b/apps/menus/recording_menu.c
index 4bbc4b163c..b5bbecb9aa 100644
--- a/apps/menus/recording_menu.c
+++ b/apps/menus/recording_menu.c
@@ -350,7 +350,7 @@ static int clear_rec_directory(void)
}
MENUITEM_FUNCTION(clear_rec_directory_item, 0, ID2P(LANG_CLEAR_REC_DIR),
clear_rec_directory, NULL, NULL, Icon_Folder);
-
+
MENUITEM_SETTING(cliplight, &global_settings.cliplight, NULL);
#ifdef HAVE_AGC
@@ -393,6 +393,26 @@ MENUITEM_FUNCTION(agc_cliptime, 0, ID2P(LANG_RECORDING_AGC_CLIPTIME),
agc_cliptime_func, NULL, NULL, Icon_Menu_setting);
#endif /* HAVE_AGC */
+#if defined(HAVE_RECORDING_HISTOGRAM)
+static bool history_interval(void)
+{
+ static const struct opt_items names[] = {
+ { "0s", TALK_ID(0, UNIT_SEC) },
+ { "1s", TALK_ID(1, UNIT_SEC) },
+ { "2s", TALK_ID(2, UNIT_SEC) },
+ { "4s", TALK_ID(5, UNIT_SEC) }
+ };
+ return set_option(str(LANG_RECORDING_HISTOGRAM_INTERVAL),
+ &global_settings.rec_histogram_interval,
+ INT, names, 4, NULL );
+}
+
+MENUITEM_FUNCTION(recording_histogram, 0,
+ ID2P(LANG_RECORDING_HISTOGRAM_INTERVAL),
+ history_interval, NULL, NULL, Icon_Menu_setting);
+
+#endif
+
/** Rec trigger **/
enum trigger_menu_option
{
@@ -647,6 +667,9 @@ MAKE_MENU(recording_settings_menu, ID2P(LANG_RECORDING_SETTINGS),
#ifdef HAVE_AGC
&agc_preset, &agc_cliptime,
#endif
+#if defined(HAVE_RECORDING_HISTOGRAM)
+ &recording_histogram,
+#endif
#ifdef HAVE_LCD_BITMAP
&peak_meter_menu,
#endif
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 */
diff --git a/apps/settings.h b/apps/settings.h
index bba33366ae..1186f47fb0 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -469,6 +469,9 @@ struct user_settings
int rec_stop_gap; /* index of trig_durations */
int rec_trigger_mode; /* see TRIG_MODE_XXX constants */
int rec_trigger_type; /* what to do when trigger released */
+#ifdef HAVE_RECORDING_HISTOGRAM
+ int rec_histogram_interval; /* recording peakmeter histogram */
+#endif
#ifdef HAVE_AGC
int rec_agc_preset_mic; /* AGC mic preset modes:
diff --git a/apps/settings_list.c b/apps/settings_list.c
index ade159b85c..0a7c3c5b99 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -1135,6 +1135,13 @@ const struct settings_list settings[] = {
CHOICE_SETTING(F_RECSETTING, rec_trigger_type, LANG_RECORD_TRIGGER_TYPE, TRIG_TYPE_STOP,
"trigger type","stop,pause,nf stp", NULL ,3,
ID2P(LANG_RECORD_TRIGGER_STOP), ID2P(LANG_PAUSE), ID2P(LANG_RECORD_TRIGGER_NEWFILESTP)),
+#ifdef HAVE_RECORDING_HISTOGRAM
+ /* TO DO: additional restictions of following REP items? */
+ TABLE_SETTING(F_RECSETTING, rec_histogram_interval, LANG_RECORDING_HISTOGRAM_INTERVAL, 0,
+ "histogram interval","0s,1s,2s,4s",
+ UNIT_SEC, NULL, NULL, NULL, 4, 0,1,2,4),
+#endif /* HAVE_RECORDING_HISTOGRAM */
+
#endif /* HAVE_RECORDING */
#ifdef HAVE_SPDIF_POWER
diff --git a/firmware/export/config/iriverh120.h b/firmware/export/config/iriverh120.h
index 8751c121cc..55ef43dad2 100644
--- a/firmware/export/config/iriverh120.h
+++ b/firmware/export/config/iriverh120.h
@@ -111,6 +111,8 @@
/* define this if you have recording possibility */
#define HAVE_RECORDING
+#define HAVE_RECORDING_HISTOGRAM
+
/* Define bitmask of input sources - recordable bitmask can be defined
explicitly if different */
#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | \
diff --git a/firmware/export/config/iriverh300.h b/firmware/export/config/iriverh300.h
index d2348397d2..9b92c8616b 100644
--- a/firmware/export/config/iriverh300.h
+++ b/firmware/export/config/iriverh300.h
@@ -107,6 +107,8 @@
/* define this if you have recording possibility */
#define HAVE_RECORDING
+#define HAVE_RECORDING_HISTOGRAM
+
/* Define bitmask of input sources - recordable bitmask can be defined
explicitly if different */
#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO)