Index: apps/recorder/recording.c
===================================================================
--- apps/recorder/recording.c (revision 24610)
+++ apps/recorder/recording.c (working copy)
@@ -30,6 +30,7 @@
#include "powermgmt.h"
#include "lcd.h"
#include "led.h"
+#include "mpeg.h"
#include "audio.h"
#if CONFIG_CODEC == SWCODEC
#include "thread.h"
@@ -270,6 +271,59 @@
static short agc_maxgain;
#endif /* HAVE_AGC */
+/* Histogram data */
+/* TO DO: move some of this stuff inside the recording function? */
+#ifdef HAVE_RECORDING_HISTOGRAM
+#define HIST_Y (hist_pos_y+hist_size_h-1)
+#define HIST_W (LCD_WIDTH / 2 - 4)
+static short hist_time_interval = 1; /* 1, 2, 4, 8 */
+static int hist_l = 0;
+static int hist_r = 0;
+static unsigned char history_l[HIST_W];
+static unsigned char history_r[HIST_W];
+const short hist_balance_marks[12] =
+ /* -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6 */
+ {-4988, -4377, -3690, -2920, -2057, -1087,
+ 1087, 2057, 2920, 3690, 4377, 4988};
+const short hist_peak_lin2dB[31] =
+#if 0
+ /* Clip, 0, -2, -4, -6, -8, -10 */
+ { 32767, 28539, 23197, 18427, 14637, 11627, 9236,
+ /* -12, -14, -16, -18, -20, -24, -30, -36, -48, -inf */
+ 7336, 5828, 4629, 3677, 2602, 1642, 734, 328, 104, 0 };
+#endif
+ /* Clip, 0, -1, -2, -3, -4, -5, -6, -7, -8 */
+ { 32767, 30579, 27569, 24573, 21901, 19519, 17397, 15505, 13819, 12316,
+ /* -9, -10, -11, -12, -13, -14, -15, -16, -18, -20, -22 */
+ 10977, 9783, 8719, 7771, 6926, 6173, 5502, 4629, 3677, 2921, 2320,
+ /* -24, -27, -30, -33, -36, -39, -42, -48, -60, -inf */
+ 1842, 1232, 872, 618, 437, 310, 207, 124, 33, 0 };
+const char hist_level_marks[6] =
+ /* logarithmic: 0, -3, -6, -12, -24, -48 [dB] */
+ { 29, 26, 23, 17, 9, 2};
+#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)
{
#ifdef HAVE_MIC_REC
@@ -317,6 +371,13 @@
*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;
}
@@ -1025,9 +1086,14 @@
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_RECORDING_HISTOGRAM)
+ unsigned short hist_pos_y = 0;
+ unsigned short hist_size_h = 0;
+ int history_pos = 0;
+#endif
#ifdef HAVE_FMRADIO_REC
int prev_rec_source = global_settings.rec_source; /* detect source change */
#endif
@@ -1084,49 +1150,6 @@
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,8 +1166,67 @@
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;
if(global_settings.peak_meter_clipcounter)
{
@@ -1673,12 +1755,11 @@
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 +1877,101 @@
}
}
+/*--------------------------------------------------------------------------------------*/
+#ifdef HAVE_RECORDING_HISTOGRAM
+ /* Draw histogram graphs (on main unit only).
+ * 4 modes: low size linear or logarithmic histogram with
+ * disk space usage, battery level and balance meter or
+ * high size linear or logarithmic peak histogram.
+ */
+#define HIST_BAL_X (LCD_WIDTH/2 + 4)
+#define HIST_BAL_W (LCD_WIDTH/2 - 5)
+#define BAL_MAX_R 4988
+#define BAL_MAX_L (-BAL_MAX_R * (HIST_BAL_W/2 + 1) / (HIST_BAL_W/2))
+ 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]);
+ }
+ }
+ lcd_set_foreground(LCD_WHITE);
+ for (i = 0; i < HIST_W; i++)
+ {
+ if (history_l[i] == hist_size_h)
+ lcd_drawpixel(1 + i, HIST_Y - 1);
+ if (history_r[i] == hist_size_h)
+ lcd_drawpixel(HIST_W + 7 + i, HIST_Y - 1);
+ }
+#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 +2098,6 @@
FOR_NB_SCREENS(i)
screens[i].setfont(FONT_UI);
-
/* if the directory was created or recording happened, make sure the
browser is updated */
Index: apps/recorder/peakmeter.c
===================================================================
--- apps/recorder/peakmeter.c (revision 24610)
+++ apps/recorder/peakmeter.c (working copy)
@@ -66,7 +66,7 @@
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 @@
{
/* 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;
-#ifdef HAVE_AGC
+#if defined(SIMULATOR) /*&& (CONFIG_CODEC != SWCODEC)*/
+ srand(current_tick);
+ pm_max_left = rand()%MAX_PEAK;
+#endif
+
+ 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 @@
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 @@
{
/* 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;
-#ifdef HAVE_AGC
+#if defined(SIMULATOR) /*&& (CONFIG_CODEC != SWCODEC)*/
+ srand(current_tick);
+ pm_max_right = rand()%MAX_PEAK;
+#endif
+
+ 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 @@
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.
Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 24610)
+++ apps/lang/english.lang (working copy)
@@ -13315,3 +13315,38 @@
lcd_bitmap: "Remote Base Skin"
+
+ id: LANG_RECORDING_HISTOGRAM_MODE
+ desc: in record settings menu
+ user: core
+
+ *: none
+ recording_histogram: "Histogram mode"
+
+
+ *: none
+ recording_histogram: "Histogram mode"
+
+
+ *: none
+ recording_histogram: "Histogram mode"
+
+
+
+ id: LANG_RECORDING_HISTOGRAM_INTERVAL
+ desc: in record settings menu
+ user: core
+
+ *: none
+ recording_histogram: "Histogram interval"
+
+
+ *: none
+ recording_histogram: "Histogram interval"
+
+
+ *: none
+ recording_histogram: "Histogram interval"
+
+
+
Index: apps/settings.h
===================================================================
--- apps/settings.h (revision 24610)
+++ apps/settings.h (working copy)
@@ -469,6 +469,10 @@
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_mode; /* recording peakmeter histogram + balance */
+ int rec_histogram_interval; /* recording peakmeter histogram + balance */
+#endif
#ifdef HAVE_AGC
int rec_agc_preset_mic; /* AGC mic preset modes:
Index: apps/menus/recording_menu.c
===================================================================
--- apps/menus/recording_menu.c (revision 24610)
+++ apps/menus/recording_menu.c (working copy)
@@ -393,6 +393,26 @@
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) },
+ { "5s", 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,7 +667,8 @@
#ifdef HAVE_AGC
&agc_preset, &agc_cliptime,
#endif
-#ifdef HAVE_LCD_BITMAP
+#if defined(HAVE_RECORDING_HISTOGRAM)
+ &recording_histogram,
&peak_meter_menu,
#endif
&browse_recconfigs, &save_recpresets_item
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c (revision 24610)
+++ apps/settings_list.c (working copy)
@@ -1135,6 +1135,13 @@
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,5s",
+ UNIT_SEC, NULL, NULL, NULL, 4, 0,1,2,5),
+#endif /* HAVE_RECORDING_HISTOGRAM */
+
#endif /* HAVE_RECORDING */
#ifdef HAVE_SPDIF_POWER
Index: apps/features.txt
===================================================================
--- apps/features.txt (revision 24610)
+++ apps/features.txt (working copy)
@@ -148,6 +148,10 @@
#endif
#endif
+#if defined(HAVE_RECORDING_HISTOGRAM)
+recording_histogram
+#endif
+
#if defined(HAVE_REMOTE_LCD)
remote
remote_lcd_invert
Index: firmware/export/config-h300.h
===================================================================
--- firmware/export/config-h300.h (revision 23678)
+++ firmware/export/config-h300.h (working copy)
@@ -106,6 +106,7 @@
/* 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 */
Index: firmware/export/config/iriverh300.h
===================================================================
--- firmware/export/config/iriverh300.h (revision 24610)
+++ firmware/export/config/iriverh300.h (working copy)
@@ -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)