1
0
Fork 0
forked from len0rd/rockbox

Implement FS #2976: Clip Counter for recording screen. If enabled in peak meter settings, it shows the number of times clipping occurred (clip indicator going on). Count is reset on recording start and only counts during actual recording. Stays on screen when stopping or pauzing. Also fix a drawing bug when peakmeters start at a non-zero x offset.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14455 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Peter D'Hoye 2007-08-25 15:53:54 +00:00
parent cdfb22f9df
commit 583f186ce4
10 changed files with 176 additions and 40 deletions

View file

@ -11122,3 +11122,31 @@
rtc: "oh"
</voice>
</phrase>
<phrase>
id: LANG_PM_CLIPCOUNTER
desc: in settings, for recording peak meter
user:
<source>
*: "Peak meter clipcounter"
</source>
<dest>
*: "Peak meter clipcounter"
</dest>
<voice>
*: ""
</voice>
</phrase>
<phrase>
id: LANG_PM_CLIPCOUNT
desc: in recording GUI, for recording peak meter
user:
<source>
*: "CLIP:"
</source>
<dest>
*: "CLIP:"
</dest>
<voice>
*: ""
</voice>
</phrase>

View file

@ -401,7 +401,8 @@ MENUITEM_SETTING(peak_meter_hold,
&global_settings.peak_meter_hold, peakmeter_callback);
MENUITEM_SETTING(peak_meter_clip_hold,
&global_settings.peak_meter_clip_hold, peakmeter_callback);
MENUITEM_SETTING(peak_meter_clipcounter,
&global_settings.peak_meter_clipcounter, NULL);
MENUITEM_SETTING(peak_meter_release,
&global_settings.peak_meter_release, peakmeter_callback);
/**
@ -529,7 +530,7 @@ MENUITEM_FUNCTION(peak_meter_max_item, 0, ID2P(LANG_PM_MAX),
peak_meter_max, NULL, NULL, Icon_NOICON);
MAKE_MENU(peak_meter_menu, ID2P(LANG_PM_MENU), NULL, Icon_NOICON,
&peak_meter_release, &peak_meter_hold,
&peak_meter_clip_hold,
&peak_meter_clip_hold, &peak_meter_clipcounter,
&peak_meter_scale_item, &peak_meter_min_item, &peak_meter_max_item);
#endif /* HAVE_LCD_BITMAP */
/* PEAK METER MENU */

View file

@ -53,7 +53,9 @@
#endif
#include "tree.h"
#include "eeprom_settings.h"
#ifdef HAVE_RECORDING
#include "recording.h"
#endif
#ifdef HAVE_LCD_BITMAP
#include "bmp.h"
#include "icons.h"
@ -659,7 +661,7 @@ static bool clean_shutdown(void (*callback)(void *), void *parameter)
#if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
if (audio_stat & AUDIO_STATUS_RECORD)
{
audio_stop_recording();
rec_command(RECORDING_CMD_STOP);
/* wait for stop to complete */
while (audio_status() & AUDIO_STATUS_RECORD)
sleep(1);

View file

@ -16,6 +16,9 @@
* KIND, either express or implied.
*
****************************************************************************/
#ifdef SIMULATOR
#include <stdlib.h> /* sim uses rand for peakmeter simulation */
#endif
#include "config.h"
#include "mas.h"
#include "thread.h"
@ -47,7 +50,6 @@
#endif
static bool pm_playback = true; /* selects between playback and recording peaks */
#endif
static struct meter_scales scales[NB_SCREENS];
@ -74,6 +76,10 @@ static bool pm_clip_right = false;
static long pm_clip_timeout_l; /* clip hold timeouts */
static long pm_clip_timeout_r;
/* clipping counter (only used for recording) */
static unsigned int pm_clipcount = 0; /* clipping count */
static bool pm_clipcount_active = false; /* counting or not */
/* Temporarily en- / disables peak meter. This is especially for external
applications to detect if the peak_meter is in use and needs drawing at all */
bool peak_meter_enabled = true;
@ -490,6 +496,30 @@ void peak_meter_init_times(int release, int hold, int clip_hold)
pm_clip_hold = clip_hold;
}
/**
* Enable/disable clip counting
*/
void pm_activate_clipcount(bool active)
{
pm_clipcount_active = active;
}
/**
* Get clipping counter value
*/
int pm_get_clipcount(void)
{
return pm_clipcount;
}
/**
* Set clipping counter to zero (typically at start of recording or playback)
*/
void pm_reset_clipcount(void)
{
pm_clipcount = 0;
}
/**
* Set the source of the peak meter to playback or to
* record.
@ -523,6 +553,7 @@ static void set_trig_status(int new_state)
}
}
}
#endif
/**
@ -535,6 +566,7 @@ static void set_trig_status(int new_state)
void peak_meter_peek(void)
{
int left, right;
bool was_clipping = pm_clip_left || pm_clip_right;
/* read current values */
#if CONFIG_CODEC == SWCODEC
if (pm_playback)
@ -585,6 +617,12 @@ void peak_meter_peek(void)
current_tick + clip_time_out[pm_clip_hold];
}
if(!was_clipping && (pm_clip_left || pm_clip_right))
{
if(pm_clipcount_active)
pm_clipcount++;
}
/* peaks are searched -> we have to find the maximum. When
many calls of peak_meter_peek the maximum value will be
stored in pm_max_xxx. This maximum is reset by the
@ -757,6 +795,12 @@ static int peak_meter_read_l(void)
/* reset pm_max_left so that subsequent calls of peak_meter_peek don't
get fooled by an old maximum value */
pm_max_left = pm_cur_left;
#ifdef SIMULATOR
srand(current_tick);
retval = rand()%MAX_PEAK;
#endif
return retval;
}
@ -782,6 +826,12 @@ static int peak_meter_read_r(void)
/* reset pm_max_right so that subsequent calls of peak_meter_peek don't
get fooled by an old maximum value */
pm_max_right = pm_cur_right;
#ifdef SIMULATOR
srand(current_tick);
retval = rand()%MAX_PEAK;
#endif
return retval;
}
@ -860,7 +910,7 @@ unsigned short peak_meter_scale_value(unsigned short val, int meterwidth)
void peak_meter_screen(struct screen *display, int x, int y, int height)
{
peak_meter_draw(display, &scales[display->screen_type], x, y,
display->width, height);
display->width - x, height);
}
/**
* Draws a peak meter in the specified size at the specified position.
@ -1282,7 +1332,7 @@ int peak_meter_draw_get_btn(int x, int y[], int height, int nb_screens)
for(i = 0; i < nb_screens; i++)
{
peak_meter_screen(&screens[i], x, y[i], height);
screens[i].update_rect(x, y[i], screens[i].width, height);
screens[i].update_rect(x, y[i], screens[i].width - x, height);
}
next_refresh += HZ / PEAK_METER_FPS;
dopeek = true;

View file

@ -26,6 +26,10 @@
extern bool peak_meter_histogram(void);
#endif
extern int pm_get_clipcount(void);
extern void pm_reset_clipcount(void);
extern void pm_activate_clipcount(bool active);
extern bool peak_meter_enabled;
extern void peak_meter_playback(bool playback);

View file

@ -582,13 +582,13 @@ int radio_screen(void)
#ifndef SIMULATOR
if(audio_status() == AUDIO_STATUS_RECORD)
{
rec_new_file();
rec_command(RECORDING_CMD_START_NEWFILE);
update_screen = true;
}
else
{
have_recorded = true;
rec_record();
rec_command(RECORDING_CMD_START);
update_screen = true;
}
#endif /* SIMULATOR */

View file

@ -694,19 +694,38 @@ void rec_set_recording_options(struct audio_recording_options *options)
audio_set_recording_options(options);
}
/* steals mp3 buffer, creates unique filename and starts recording */
void rec_record(void)
void rec_command(enum recording_command cmd)
{
switch(cmd)
{
case RECORDING_CMD_STOP:
pm_activate_clipcount(false);
audio_stop_recording();
break;
case RECORDING_CMD_START:
/* steal mp3 buffer, create unique filename and start recording */
pm_reset_clipcount();
pm_activate_clipcount(true);
#if CONFIG_CODEC != SWCODEC
talk_buffer_steal(); /* we use the mp3 buffer */
#endif
audio_record(rec_create_filename(path_buffer));
}
/* creates unique filename and starts recording */
void rec_new_file(void)
{
break;
case RECORDING_CMD_START_NEWFILE:
/* create unique filename and start recording*/
pm_reset_clipcount();
pm_activate_clipcount(true); /* just to be sure */
audio_new_file(rec_create_filename(path_buffer));
break;
case RECORDING_CMD_PAUSE:
pm_activate_clipcount(false);
audio_pause_recording();
break;
case RECORDING_CMD_RESUME:
pm_activate_clipcount(true);
audio_resume_recording();
break;
}
}
/* used in trigger_listerner and recording_screen */
@ -725,7 +744,7 @@ static void trigger_listener(int trigger_status)
if(!(audio_status() & AUDIO_STATUS_RECORD))
{
rec_status |= RCSTAT_HAVE_RECORDED;
rec_record();
rec_command(RECORDING_CMD_START);
#if CONFIG_CODEC != SWCODEC
/* give control to mpeg thread so that it can start
recording */
@ -738,11 +757,13 @@ static void trigger_listener(int trigger_status)
{
if((audio_status() & AUDIO_STATUS_PAUSE) &&
(global_settings.rec_trigger_type == 1))
audio_resume_recording();
{
rec_command(RECORDING_CMD_RESUME);
}
/* New file on trig start*/
else if (global_settings.rec_trigger_type != 2)
{
rec_new_file();
rec_command(RECORDING_CMD_START_NEWFILE);
/* tell recording_screen to reset the time */
last_seconds = 0;
}
@ -756,15 +777,15 @@ static void trigger_listener(int trigger_status)
switch(global_settings.rec_trigger_type)
{
case 0: /* Stop */
audio_stop_recording();
rec_command(RECORDING_CMD_STOP);
break;
case 1: /* Pause */
audio_pause_recording();
rec_command(RECORDING_CMD_PAUSE);
break;
case 2: /* New file on trig stop*/
rec_new_file();
rec_command(RECORDING_CMD_START_NEWFILE);
/* tell recording_screen to reset the time */
last_seconds = 0;
break;
@ -825,6 +846,9 @@ bool recording_screen(bool no_source)
int trig_xpos[NB_SCREENS];
int trig_ypos[NB_SCREENS];
int trig_width[NB_SCREENS];
/* pm_x = offset pm to put clipcount in front.
Use lcd_getstringsize() when not using SYSFONT */
int pm_x = global_settings.peak_meter_clipcounter ? 30 : 0;
static const unsigned char *byte_units[] = {
ID2P(LANG_BYTE),
@ -881,6 +905,8 @@ bool recording_screen(bool no_source)
rec_init_filename();
#endif
pm_reset_clipcount();
pm_activate_clipcount(false);
settings_apply_trigger();
#ifdef HAVE_AGC
@ -973,7 +999,7 @@ bool recording_screen(bool no_source)
#endif /* CONFIG_LED */
/* Wait for a button a while (HZ/10) drawing the peak meter */
button = peak_meter_draw_get_btn(0, pm_y, h * PM_HEIGHT, screen_update);
button = peak_meter_draw_get_btn(pm_x, pm_y, h * PM_HEIGHT, screen_update);
if (last_audio_stat != audio_stat)
{
@ -1021,7 +1047,7 @@ bool recording_screen(bool no_source)
if(audio_stat & AUDIO_STATUS_RECORD)
{
audio_stop_recording();
rec_command(RECORDING_CMD_STOP);
}
else
{
@ -1045,7 +1071,7 @@ bool recording_screen(bool no_source)
{
/* manual recording */
rec_status |= RCSTAT_HAVE_RECORDED;
rec_record();
rec_command(RECORDING_CMD_START);
last_seconds = 0;
if (global_settings.talk_menu)
{
@ -1068,7 +1094,7 @@ bool recording_screen(bool no_source)
/*if new file button pressed, start new file */
if (button == ACTION_REC_NEWFILE)
{
rec_new_file();
rec_command(RECORDING_CMD_START_NEWFILE);
last_seconds = 0;
}
else
@ -1076,7 +1102,7 @@ bool recording_screen(bool no_source)
{
if(audio_stat & AUDIO_STATUS_PAUSE)
{
audio_resume_recording();
rec_command(RECORDING_CMD_RESUME);
if (global_settings.talk_menu)
{
/* no voice possible here, but a beep */
@ -1085,7 +1111,7 @@ bool recording_screen(bool no_source)
}
else
{
audio_pause_recording();
rec_command(RECORDING_CMD_PAUSE);
}
}
}
@ -1332,7 +1358,7 @@ bool recording_screen(bool no_source)
case ACTION_REC_F3:
if(audio_stat & AUDIO_STATUS_RECORD)
{
rec_new_file();
rec_command(RECORDING_CMD_START_NEWFILE);
last_seconds = 0;
}
else
@ -1497,18 +1523,33 @@ bool recording_screen(bool no_source)
if (!(global_settings.rec_split_type)
|| (num_recorded_bytes >= MAX_FILE_SIZE))
{
rec_new_file();
rec_command(RECORDING_CMD_START_NEWFILE);
last_seconds = 0;
}
else
{
peak_meter_trigger(false);
peak_meter_set_trigger_listener(NULL);
audio_stop_recording();
rec_command(RECORDING_CMD_STOP);
}
update_countdown = 1;
}
/* draw the clipcounter just in front of the peakmeter */
if(global_settings.peak_meter_clipcounter)
{
char clpstr[32];
snprintf(clpstr, 32, "%4d", pm_get_clipcount());
for(i = 0; i < screen_update; i++)
{
if(PM_HEIGHT > 1)
screens[i].puts(0, 2 + filename_offset[i],
str(LANG_PM_CLIPCOUNT));
screens[i].puts(0, 1 + PM_HEIGHT + filename_offset[i],
clpstr);
}
}
snprintf(buf, sizeof(buf), "%s: %s", str(LANG_SYSFONT_VOLUME),
fmt_gain(SOUND_VOLUME,
global_settings.volume,
@ -1749,7 +1790,7 @@ bool recording_screen(bool no_source)
for(i = 0; i < screen_update; i++)
{
gui_statusbar_draw(&(statusbars.statusbars[i]), true);
peak_meter_screen(&screens[i], 0, pm_y[i], h*PM_HEIGHT);
peak_meter_screen(&screens[i], pm_x, pm_y[i], h*PM_HEIGHT);
screens[i].update();
}
@ -1805,7 +1846,7 @@ bool recording_screen(bool no_source)
}
#if CONFIG_CODEC == SWCODEC
audio_stop_recording();
rec_command(RECORDING_CMD_STOP);
audio_close_recording();
#ifdef HAVE_FMRADIO_REC

View file

@ -42,10 +42,17 @@ void rec_init_recording_options(struct audio_recording_options *options);
/* SRCF_RECORDING is implied for SWCODEC */
void rec_set_recording_options(struct audio_recording_options *options);
/* steals mp3 buffer, creates unique filename and starts recording */
void rec_record(void);
enum recording_command
{
RECORDING_CMD_STOP,
RECORDING_CMD_START, /* steal mp3 buffer, create unique filename and
start recording */
RECORDING_CMD_START_NEWFILE, /* create unique filename and start recording*/
RECORDING_CMD_PAUSE,
RECORDING_CMD_RESUME
};
/* creates unique filename and starts recording */
void rec_new_file(void);
/* centralized way to start/stop/... recording */
void rec_command(enum recording_command rec_cmd);
#endif /* RECORDING_H */

View file

@ -465,6 +465,7 @@ struct user_settings
bool peak_meter_dbfs; /* show linear or dbfs values */
int peak_meter_min; /* range minimum */
int peak_meter_max; /* range maximum */
bool peak_meter_clipcounter; /* clipping count indicator */
bool car_adapter_mode; /* 0=off 1=on */
/* show status bar */

View file

@ -712,6 +712,8 @@ const struct settings_list settings[] = {
OFFON_SETTING(0,peak_meter_dbfs,LANG_PM_DBFS,true,"peak meter dbfs",NULL),
{F_T_INT,&global_settings.peak_meter_min,LANG_PM_MIN,INT(60),"peak meter min",NULL,UNUSED},
{F_T_INT,&global_settings.peak_meter_max,LANG_PM_MAX,INT(0),"peak meter max",NULL,UNUSED},
OFFON_SETTING(0,peak_meter_clipcounter,LANG_PM_CLIPCOUNTER,false,
"peak meter clipcounter",NULL),
#endif
#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
SOUND_SETTING(0, mdb_strength, LANG_MDB_STRENGTH,