From 99a0598c284471342fcda1fdcba90d4b666bfbb3 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Mon, 29 Aug 2005 20:07:17 +0000 Subject: Major peakmeter rework: * Changed set/get functions for dbfs mode to bool type. * Removed performance setting, leaving (slightly adapted) high performance mode only. * Refresh rate is always 20 Hz now. * Readout doesn't do an extra (hidden) peek, should allow for slightly better clip detection. * Brought back high performance peakmeter for recording. Peakmeter stops hogging the CPU when the disk is spinning; this is enough to avoid the performance problem when saving data. * Optimisations, code cleanup and code policeing. * (iriver) Reduced CPU load of peakmeter by not calculating excessive overlaps. ** Bumped config block version, so save your settings before upgrading. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7415 a1c6a512-1295-4272-9138-f99709370657 --- apps/recorder/peakmeter.c | 524 ++++++++++++++++++++++------------------------ apps/recorder/peakmeter.h | 7 +- apps/recorder/radio.c | 7 +- 3 files changed, 261 insertions(+), 277 deletions(-) (limited to 'apps/recorder') diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c index 002a3c48d5..088cf8e099 100644 --- a/apps/recorder/peakmeter.c +++ b/apps/recorder/peakmeter.c @@ -21,6 +21,7 @@ #include "thread.h" #include "kernel.h" #include "settings.h" +#include "ata.h" #include "lcd.h" #include "widgets.h" #include "wps-display.h" @@ -36,41 +37,48 @@ #include "pcm_playback.h" #endif -/* no inline in simulator mode */ -#ifdef SIMULATOR -#define inline +#if !defined(SIMULATOR) && CONFIG_HWCODEC != MASNONE +/* Data source */ +static int pm_src_left = MAS_REG_DQPEAK_L; +static int pm_src_right = MAS_REG_DQPEAK_R; #endif -/* buffer the read peak value */ -static int peak_meter_max_l; -static int peak_meter_max_r; - -/* point in time when peak_meter_max_x becomes invalid */ -static long peak_meter_timeout_l; -static long peak_meter_timeout_r; - -/* when true a clip has occurred */ -static bool peak_meter_l_clip = false; -static bool peak_meter_r_clip = false; - -/* point in time when peak_meter_x_oveflow becomes invalid */ -static long peak_meter_clip_timeout_l; -static long peak_meter_clip_timeout_r; - -static int peak_meter_clip_hold; - -/* specifies the value range in peak volume values */ -unsigned short peak_meter_range_min; -unsigned short peak_meter_range_max; -static unsigned short peak_meter_range; - -/* if set to true clip timeout is disabled */ -static bool peak_meter_clip_eternal = false; +/* Current values and cumulation */ +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; + +/* Peak hold */ +static int pm_peak_left; /* buffered peak values */ +static int pm_peak_right; +static long pm_peak_timeout_l; /* peak hold timeouts */ +static long pm_peak_timeout_r; + +/* Clip hold */ +static bool pm_clip_left = false; /* when true a clip has occurred */ +static bool pm_clip_right = false; +static long pm_clip_timeout_l; /* clip hold timeouts */ +static long pm_clip_timeout_r; + +/* 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; -static bool peak_meter_use_dbfs = true; -static unsigned short db_min = 0; -static unsigned short db_max = 9000; -static unsigned short db_range = 9000; +/** Parameters **/ +/* Range */ +unsigned short peak_meter_range_min; /* minimum of range in samples */ +unsigned short peak_meter_range_max; /* maximum of range in samples */ +static unsigned short pm_range; /* range width in samples */ +static bool pm_use_dbfs = true; /* true if peakmeter displays dBfs */ +static unsigned short pm_db_min = 0; /* minimum of range in 1/100 dB */ +static unsigned short pm_db_max = 9000; /* maximum of range in 1/100 dB */ +static unsigned short pm_db_range = 9000; /* range width in 1/100 dB */ +/* Timing behaviour */ +static int pm_peak_hold = 1; /* peak hold timeout index */ +static int pm_peak_release = 8; /* peak release in units per read */ +static int pm_clip_hold = 16; /* clip hold timeout index */ +static bool pm_clip_eternal = false; /* true if clip timeout is disabled */ #ifdef HAVE_RECORDING static unsigned short trig_strt_threshold; @@ -92,34 +100,6 @@ static int trig_status = TRIG_OFF; static void (*trigger_listener)(int) = NULL; #endif -#if CONFIG_HWCODEC == MASNONE -#define MAS_REG_DQPEAK_L 0 -#define MAS_REG_DQPEAK_R 0 -#endif - -#if !defined(SIMULATOR) && CONFIG_HWCODEC != MASNONE -static int peak_meter_src_l = MAS_REG_DQPEAK_L; -static int peak_meter_src_r = MAS_REG_DQPEAK_R; -#endif - -/* 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; - -/* -bool peak_meter_use_thread = false; -static char peak_meter_stack[DEFAULT_STACK_SIZE]; -*/ -/* used in wps.c to set the display frame rate of the peak meter */ -int peak_meter_fps = 20; - -static int peak_meter_l; -static int peak_meter_r; - -static int peak_meter_hold = 1; -static int peak_meter_release = 8; - /* debug only */ #ifdef PM_DEBUG static int peek_calls = 0; @@ -132,7 +112,7 @@ static unsigned int ticks_per_redraw[TICKS_PER_DRAW_SIZE]; #endif /* time out values for max */ -static const long max_time_out[] = { +static const short peak_time_out[] = { 0 * HZ, HZ / 5, 30, HZ / 2, HZ, 2 * HZ, 3 * HZ, 4 * HZ, 5 * HZ, 6 * HZ, 7 * HZ, 8 * HZ, 9 * HZ, 10 * HZ, 15 * HZ, 20 * HZ, 30 * HZ, 60 * HZ @@ -150,22 +130,6 @@ static const long clip_time_out[] = { /* precalculated peak values that represent magical dBfs values. Used to draw the scale */ #define DB_SCALE_SRC_VALUES_SIZE 12 -#if 0 -static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = { - 32767, /* 0 db */ - 23197, /* - 3 db */ - 16422, /* - 6 db */ - 11626, /* - 9 db */ - 8231, /* -12 db */ - 4125, /* -18 db */ - 2067, /* -24 db */ - 1036, /* -30 db */ - 328, /* -40 db */ - 104, /* -50 db */ - 33, /* -60 db */ - 1, /* -inf */ -}; -#else static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = { 32752, /* 0 db */ 22784, /* - 3 db */ @@ -180,11 +144,10 @@ static const int db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = { 33, /* -60 db */ 0, /* -inf */ }; -#endif static int db_scale_count = DB_SCALE_SRC_VALUES_SIZE; -/* if db_scale_valid is false the content of +/* if db_scale_valid is false the content of db_scale_lcd_coord needs recalculation */ static bool db_scale_valid = false; @@ -211,7 +174,8 @@ static int db_scale_lcd_coord[sizeof db_scale_src_values / sizeof (int)]; * for-loops. */ -int calc_db (int isample) { +int calc_db (int isample) +{ /* return n+m*(isample-istart)/100 */ int n; long m; @@ -312,7 +276,8 @@ int calc_db (int isample) { * minimal peak sample is searched. * @return int - A linear volume value with 0 <= value < MAX_PEAK */ -static int db_to_sample_bin_search(int min, int max, int db){ +static int db_to_sample_bin_search(int min, int max, int db) +{ int test = min + (max - min) / 2; if (min < max) { @@ -339,7 +304,8 @@ static int db_to_sample_bin_search(int min, int max, int db){ * @return int - The return value is in the range of * 0 <= return value < MAX_PEAK */ -int peak_meter_db2sample(int db) { +int peak_meter_db2sample(int db) +{ int retval = 0; /* what is the maximum pseudo db value */ @@ -371,13 +337,14 @@ int peak_meter_db2sample(int db) { /** * Set the min value for restriction of the value range. - * @param int newmin - depending wether dBfs is used + * @param int newmin - depending whether dBfs is used * newmin is a value in dBfs * 100 or in linear percent values. * for dBfs: -9000 < newmin <= 0 * for linear: 0 <= newmin <= 100 */ -void peak_meter_set_min(int newmin) { - if (peak_meter_use_dbfs) { +void peak_meter_set_min(int newmin) +{ + if (pm_use_dbfs) { peak_meter_range_min = peak_meter_db2sample(newmin); } else { @@ -386,10 +353,10 @@ void peak_meter_set_min(int newmin) { } } - peak_meter_range = peak_meter_range_max - peak_meter_range_min; + pm_range = peak_meter_range_max - peak_meter_range_min; - db_min = calc_db(peak_meter_range_min); - db_range = db_max - db_min; + pm_db_min = calc_db(peak_meter_range_min); + pm_db_range = pm_db_max - pm_db_min; db_scale_valid = false; } @@ -400,9 +367,10 @@ void peak_meter_set_min(int newmin) { * @return: using dBfs : -9000 < value <= 0 * using linear scale: 0 <= value <= 100 */ -int peak_meter_get_min(void) { +int peak_meter_get_min(void) +{ int retval = 0; - if (peak_meter_use_dbfs) { + if (pm_use_dbfs) { retval = calc_db(peak_meter_range_min) - calc_db(MAX_PEAK - 1); } else { retval = peak_meter_range_min * 100 / MAX_PEAK; @@ -417,8 +385,9 @@ int peak_meter_get_min(void) { * for dBfs: -9000 < newmax <= 0 * for linear: 0 <= newmax <= 100 */ -void peak_meter_set_max(int newmax) { - if (peak_meter_use_dbfs) { +void peak_meter_set_max(int newmax) +{ + if (pm_use_dbfs) { peak_meter_range_max = peak_meter_db2sample(newmax); } else { if (newmax > peak_meter_range_min) { @@ -426,10 +395,10 @@ void peak_meter_set_max(int newmax) { } } - peak_meter_range = peak_meter_range_max - peak_meter_range_min; + pm_range = peak_meter_range_max - peak_meter_range_min; - db_max = calc_db(peak_meter_range_max); - db_range = db_max - db_min; + pm_db_max = calc_db(peak_meter_range_max); + pm_db_range = pm_db_max - pm_db_min; db_scale_valid = false; } @@ -440,9 +409,10 @@ void peak_meter_set_max(int newmax) { * @return: using dBfs : -9000 < value <= 0 * using linear scale: 0 <= value <= 100 */ -int peak_meter_get_max(void) { +int peak_meter_get_max(void) +{ int retval = 0; - if (peak_meter_use_dbfs) { + if (pm_use_dbfs) { retval = calc_db(peak_meter_range_max) - calc_db(MAX_PEAK - 1); } else { retval = peak_meter_range_max * 100 / MAX_PEAK; @@ -451,23 +421,24 @@ int peak_meter_get_max(void) { } /** - * Returns 1 if the meter currently is - * displaying dBfs values, 0 if the meter - * displays percent values. - * @return int - returns 0 or 1. + * Returns whether the meter is currently displaying dBfs or percent values. + * @return bool - true if the meter is displaying dBfs + false if the meter is displaying percent values. */ -int peak_meter_get_use_dbfs(void) { - return peak_meter_use_dbfs ? 1 : 0; +bool peak_meter_get_use_dbfs(void) +{ + return pm_use_dbfs; } /** - * Specifies wether the values displayed are scaled + * Specifies whether the values displayed are scaled * as dBfs or as linear percent values. - * @param int - Set to 0 for linear percent scale. Any other value - * switches on dBfs. + * @param use - set to true for dBfs, + * set to false for linear scaling in percent */ -void peak_meter_set_use_dbfs(int use){ - peak_meter_use_dbfs = ((use & 1) == 1); +void peak_meter_set_use_dbfs(bool use) +{ + pm_use_dbfs = use; db_scale_valid = false; } @@ -486,7 +457,7 @@ void peak_meter_set_use_dbfs(int use){ */ void peak_meter_init_range( bool dbfs, int range_min, int range_max) { - peak_meter_use_dbfs = dbfs; + pm_use_dbfs = dbfs; peak_meter_set_min(range_min); peak_meter_set_max(range_max); } @@ -497,15 +468,16 @@ void peak_meter_init_range( bool dbfs, int range_min, int range_max) * to decrease with each redraw * @param int hold - Select the time preset for the time the peak indicator * is reset after a peak occurred. The preset values are - * stored in max_time_out. + * stored in peak_time_out. * @param int clip_hold - Select the time preset for the time the peak * indicator is reset after a peak occurred. The preset * values are stored in clip_time_out. */ -void peak_meter_init_times(int release, int hold, int clip_hold) { - peak_meter_hold = hold; - peak_meter_release = release; - peak_meter_clip_hold = clip_hold; +void peak_meter_init_times(int release, int hold, int clip_hold) +{ + pm_peak_hold = hold; + pm_peak_release = release; + pm_clip_hold = clip_hold; } /** @@ -523,17 +495,18 @@ void peak_meter_playback(bool playback) (void)playback; #else if (playback) { - peak_meter_src_l = MAS_REG_DQPEAK_L; - peak_meter_src_r = MAS_REG_DQPEAK_R; + pm_src_left = MAS_REG_DQPEAK_L; + pm_src_right = MAS_REG_DQPEAK_R; } else { - peak_meter_src_l = MAS_REG_QPEAK_L; - peak_meter_src_r = MAS_REG_QPEAK_R; + pm_src_left = MAS_REG_QPEAK_L; + pm_src_right = MAS_REG_QPEAK_R; } #endif } #ifdef HAVE_RECORDING -static void set_trig_status(int new_state) { +static void set_trig_status(int new_state) +{ if (trig_status != new_state) { trig_status = new_state; if (trigger_listener != NULL) { @@ -545,24 +518,25 @@ static void set_trig_status(int new_state) { /** * Reads peak values from the MAS, and detects clips. The - * values are stored in peak_meter_l peak_meter_r for later + * values are stored in pm_max_left pm_max_right for later * evauluation. Consecutive calls to peak_meter_peek detect * that ocurred. This function could be used by a thread for * busy reading the MAS. */ -inline void peak_meter_peek(void) +void peak_meter_peek(void) { + int left, right; + /* read current values */ #ifdef SIMULATOR - int left = 8000; - int right = 9000; + pm_cur_left = left = 8000; + pm_cur_right = right = 9000; #elif CONFIG_HWCODEC == MASNONE - int left; - int right; - pcm_calculate_peaks(&left, &right); + pcm_calculate_peaks(&pm_cur_left, &pm_cur_right); + left = pm_cur_left; + right = pm_cur_right; #else - /* read the peak values */ - int left = mas_codec_readreg(peak_meter_src_l); - int right = mas_codec_readreg(peak_meter_src_r); + pm_cur_left = left = mas_codec_readreg(pm_src_left); + pm_cur_right = right = mas_codec_readreg(pm_src_right); #endif /* check for clips @@ -571,26 +545,34 @@ inline void peak_meter_peek(void) to be inaccurate in both ways: it may detect clips when no clip occurred and it may fail to detect a real clip. */ - if ((left == peak_meter_l) && - (left == MAX_PEAK - 1)) { - peak_meter_l_clip = true; - peak_meter_clip_timeout_l = - current_tick + clip_time_out[peak_meter_clip_hold]; + if ((left == pm_max_left) && + (left == MAX_PEAK - 1)) { + pm_clip_left = true; + pm_clip_timeout_l = + current_tick + clip_time_out[pm_clip_hold]; } - if ((right == peak_meter_r) && + if ((right == pm_max_right) && (right == MAX_PEAK - 1)) { - peak_meter_r_clip = true; - peak_meter_clip_timeout_r = - current_tick + clip_time_out[peak_meter_clip_hold]; + pm_clip_right = true; + pm_clip_timeout_r = + current_tick + clip_time_out[pm_clip_hold]; } + /* 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 + functions peak_meter_read_x. */ + pm_max_left = MAX(pm_max_left, left); + pm_max_right = MAX(pm_max_right, right); + #ifdef HAVE_RECORDING switch (trig_status) { case TRIG_READY: /* no more changes, if trigger was activated as release trigger */ /* threshold exceeded? */ - if ((left > trig_strt_threshold) || (right > trig_strt_threshold)) { + if ((left > trig_strt_threshold) + || (right > trig_strt_threshold)) { if (trig_strt_duration) { /* reset trigger duration */ trig_hightime = current_tick; @@ -614,8 +596,8 @@ inline void peak_meter_peek(void) set_trig_status(TRIG_GO); } else { /* threshold exceeded? */ - if ((left > trig_strt_threshold) || - (right > trig_strt_threshold)) { + if ((left > trig_strt_threshold) + || (right > trig_strt_threshold)) { /* reset lowtime */ trig_lowtime = current_tick; } @@ -640,7 +622,8 @@ inline void peak_meter_peek(void) case TRIG_GO: case TRIG_CONTINUE: /* threshold exceeded? */ - if ((left > trig_stp_threshold) || (right > trig_stp_threshold)) { + if ((left > trig_stp_threshold) + || (right > trig_stp_threshold)) { /* restart hold time countdown */ trig_lowtime = current_tick; } else { @@ -653,8 +636,8 @@ inline void peak_meter_peek(void) /* gap time expired? */ if (current_tick - trig_lowtime > trig_rstrt_gap){ /* start threshold exceeded? */ - if ((left > trig_strt_threshold) || - (right > trig_strt_threshold)) { + if ((left > trig_strt_threshold) + || (right > trig_strt_threshold)) { set_trig_status(TRIG_RETRIG); trig_hightime = current_tick; @@ -662,8 +645,8 @@ inline void peak_meter_peek(void) else /* stop threshold exceeded */ - if ((left > trig_stp_threshold) || - (right > trig_stp_threshold)) { + if ((left > trig_stp_threshold) + || (right > trig_stp_threshold)) { if (current_tick - trig_hightime > trig_stp_hold){ trig_lowtime = current_tick; set_trig_status(TRIG_CONTINUE); @@ -685,8 +668,8 @@ inline void peak_meter_peek(void) /* still within the gap time */ else { /* stop threshold exceeded */ - if ((left > trig_stp_threshold) || - (right > trig_stp_threshold)) { + if ((left > trig_stp_threshold) + || (right > trig_stp_threshold)) { set_trig_status(TRIG_CONTINUE); trig_lowtime = current_tick; } @@ -702,13 +685,6 @@ inline void peak_meter_peek(void) } #endif - /* peaks are searched -> we have to find the maximum. When - many calls of peak_meter_peek the maximum value will be - stored in peak_meter_x. This maximum is reset by the - functions peak_meter_read_x. */ - peak_meter_l = MAX(peak_meter_l, left); - peak_meter_r = MAX(peak_meter_r, right); - #ifdef PM_DEBUG peek_calls++; #endif @@ -720,26 +696,18 @@ inline void peak_meter_peek(void) * since the last call of peak_meter_read_l. The value * is in the range 0 <= value < MAX_PEAK. */ -static int peak_meter_read_l (void) +static int peak_meter_read_l(void) { - /* peak_meter_l 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 = peak_meter_l; + /* 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; + #ifdef PM_DEBUG peek_calls = 0; #endif - -#ifdef SIMULATOR - peak_meter_l = 8000; -#elif CONFIG_HWCODEC == MASNONE - pcm_calculate_peaks(&peak_meter_l, NULL); -#else - /* reset peak_meter_l so that subsequent calls of - peak_meter_peek doesn't get fooled by an old - maximum value */ - peak_meter_l = mas_codec_readreg(peak_meter_src_l); -#endif + /* 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; return retval; } @@ -749,25 +717,18 @@ static int peak_meter_read_l (void) * since the last call of peak_meter_read_l. The value * is in the range 0 <= value < MAX_PEAK. */ -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 = peak_meter_r; +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; + #ifdef PM_DEBUG peek_calls = 0; #endif - -#ifdef SIMULATOR - peak_meter_l = 8000; -#elif CONFIG_HWCODEC == MASNONE - pcm_calculate_peaks(NULL, &peak_meter_r); -#else - /* reset peak_meter_r so that subsequent calls of - peak_meter_peek doesn't get fooled by an old - maximum value */ - peak_meter_r = mas_codec_readreg(peak_meter_src_r); -#endif + /* 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; return retval; } @@ -777,13 +738,14 @@ static int peak_meter_read_r (void) { * @param int unused - This parameter was added to * make the function compatible with set_int */ -void peak_meter_set_clip_hold(int time) { - peak_meter_clip_eternal = false; +void peak_meter_set_clip_hold(int time) +{ + pm_clip_eternal = false; if (time <= 0) { - peak_meter_l_clip = false; - peak_meter_r_clip = false; - peak_meter_clip_eternal = true; + pm_clip_left = false; + pm_clip_right = false; + pm_clip_eternal = true; } } @@ -795,7 +757,8 @@ void peak_meter_set_clip_hold(int time) { * @param int meterwidht - The widht of the meter in pixel * @return unsigned short - A value 0 <= return value <= meterwidth */ -unsigned short peak_meter_scale_value(unsigned short val, int meterwidth){ +unsigned short peak_meter_scale_value(unsigned short val, int meterwidth) +{ int retval; if (val <= peak_meter_range_min) { @@ -809,10 +772,10 @@ unsigned short peak_meter_scale_value(unsigned short val, int meterwidth){ retval = val; /* different scaling is used for dBfs and linear percent */ - if (peak_meter_use_dbfs) { + if (pm_use_dbfs) { /* scale the samples dBfs */ - retval = (calc_db(retval) - db_min) * meterwidth / db_range; + retval = (calc_db(retval) - pm_db_min) * meterwidth / pm_db_range; } /* Scale for linear percent display */ @@ -820,7 +783,7 @@ unsigned short peak_meter_scale_value(unsigned short val, int meterwidth){ { /* scale the samples */ retval = ((retval - peak_meter_range_min) * meterwidth) - / peak_meter_range; + / pm_range; } return retval; } @@ -854,8 +817,7 @@ void peak_meter_draw(int x, int y, int width, int height) /* read the volume info from MAS */ left = peak_meter_read_l(); - right = peak_meter_read_r(); - /*peak_meter_peek();*/ + right = peak_meter_read_r(); /* scale the samples dBfs */ left = peak_meter_scale_value(left, meterwidth); @@ -865,7 +827,7 @@ void peak_meter_draw(int x, int y, int width, int height) (The scale becomes invalid when the range changed.) */ if (!db_scale_valid){ - if (peak_meter_use_dbfs) { + if (pm_use_dbfs) { db_scale_count = DB_SCALE_SRC_VALUES_SIZE; for (i = 0; i < db_scale_count; i++){ /* find the real x-coords for predefined interesting @@ -884,7 +846,7 @@ void peak_meter_draw(int x, int y, int width, int height) for (i = 0; i < db_scale_count; i++) { db_scale_lcd_coord[i] = (i * (MAX_PEAK / 10) - peak_meter_range_min) * - meterwidth / peak_meter_range; + meterwidth / pm_range; } } @@ -894,41 +856,41 @@ void peak_meter_draw(int x, int y, int width, int height) } /* apply release */ - left = MAX(left , last_left - peak_meter_release); - right = MAX(right, last_right - peak_meter_release); + left = MAX(left , last_left - pm_peak_release); + right = MAX(right, last_right - pm_peak_release); /* reset max values after timeout */ - if (TIME_AFTER(current_tick, peak_meter_timeout_l)){ - peak_meter_max_l = 0; + if (TIME_AFTER(current_tick, pm_peak_timeout_l)){ + pm_peak_left = 0; } - if (TIME_AFTER(current_tick, peak_meter_timeout_r)){ - peak_meter_max_r = 0; + if (TIME_AFTER(current_tick, pm_peak_timeout_r)){ + pm_peak_right = 0; } - if (!peak_meter_clip_eternal) { - if (peak_meter_l_clip && - TIME_AFTER(current_tick, peak_meter_clip_timeout_l)){ - peak_meter_l_clip = false; + if (!pm_clip_eternal) { + if (pm_clip_left && + TIME_AFTER(current_tick, pm_clip_timeout_l)){ + pm_clip_left = false; } - if (peak_meter_r_clip && - TIME_AFTER(current_tick, peak_meter_clip_timeout_r)){ - peak_meter_r_clip = false; + if (pm_clip_right && + TIME_AFTER(current_tick, pm_clip_timeout_r)){ + pm_clip_right = false; } } /* check for new max values */ - if (left > peak_meter_max_l) { - peak_meter_max_l = left - 1; - peak_meter_timeout_l = - current_tick + max_time_out[peak_meter_hold]; + if (left > pm_peak_left) { + pm_peak_left = left - 1; + pm_peak_timeout_l = + current_tick + peak_time_out[pm_peak_hold]; } - if (right > peak_meter_max_r) { - peak_meter_max_r = right - 1; - peak_meter_timeout_r = - current_tick + max_time_out[peak_meter_hold]; + if (right > pm_peak_right) { + pm_peak_right = right - 1; + pm_peak_timeout_r = + current_tick + peak_time_out[pm_peak_hold]; } } @@ -939,19 +901,19 @@ void peak_meter_draw(int x, int y, int width, int height) /* draw left */ lcd_fillrect (x, y, left, height / 2 - 2 ); - if (peak_meter_max_l > 0) { - lcd_vline(x + peak_meter_max_l, y, y + height / 2 - 2 ); + if (pm_peak_left > 0) { + lcd_vline(x + pm_peak_left, y, y + height / 2 - 2 ); } - if (peak_meter_l_clip) { + if (pm_clip_left) { lcd_fillrect(x + meterwidth, y, 3, height / 2 - 1); } /* draw right */ lcd_fillrect(x, y + height / 2 + 1, right, height / 2 - 2); - if (peak_meter_max_r > 0) { - lcd_vline( x + peak_meter_max_r, y + height / 2, y + height - 2); + if (pm_peak_right > 0) { + lcd_vline( x + pm_peak_right, y + height / 2, y + height - 2); } - if (peak_meter_r_clip) { + if (pm_clip_right) { lcd_fillrect(x + meterwidth, y + height / 2, 3, height / 2 - 1); } @@ -1071,7 +1033,8 @@ void peak_meter_define_trigger( * Enables or disables the trigger. * @param on - If true the trigger is turned on. */ -void peak_meter_trigger(bool on) { +void peak_meter_trigger(bool on) +{ /* don't use set_trigger here as that would fire an undesired event */ trig_status = on ? TRIG_READY : TRIG_OFF; } @@ -1081,7 +1044,8 @@ void peak_meter_trigger(bool on) { * @param listener - The function that is called with each change of * trig_status. May be set to NULL if no callback is desired. */ -void peak_meter_set_trigger_listener(void (*listener)(int status)) { +void peak_meter_set_trigger_listener(void (*listener)(int status)) +{ trigger_listener = listener; } @@ -1097,78 +1061,99 @@ void peak_meter_set_trigger_listener(void (*listener)(int status)) { * peak_meter_release_trigger. To turn the trigger off call * peak_meter_trigger_off. */ -int peak_meter_trigger_status(void) { +int peak_meter_trigger_status(void) +{ return trig_status; /* & TRIG_PIT_MASK;*/ } -void peak_meter_draw_trig(int xpos, int ypos) { - int x = xpos + ICON_PLAY_STATE_WIDTH + 1; +void peak_meter_draw_trig(int xpos, int ypos) +{ + int barstart, barend; + int icon, ixpos; switch (trig_status) { - long time_left; case TRIG_READY: - scrollbar(x, ypos + 1, TRIGBAR_WIDTH, TRIG_HEIGHT - 2, - TRIGBAR_WIDTH, 0, 0, HORIZONTAL); - lcd_mono_bitmap(bitmap_icons_7x8[Icon_Stop], xpos, ypos, - ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT); + barstart = 0; + barend = 0; + icon = Icon_Stop; + ixpos = xpos; break; case TRIG_STEADY: - case TRIG_RETRIG: - time_left = trig_strt_duration - (current_tick - trig_hightime); - time_left = time_left * TRIGBAR_WIDTH / trig_strt_duration; - scrollbar(x, ypos + 1, TRIGBAR_WIDTH, TRIG_HEIGHT - 2, - TRIGBAR_WIDTH, 0, TRIGBAR_WIDTH - time_left, HORIZONTAL); - lcd_mono_bitmap(bitmap_icons_7x8[Icon_Stop], xpos, ypos, - ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT); + case TRIG_RETRIG: + barstart = 0; + barend = TRIGBAR_WIDTH * (current_tick - trig_hightime) + / trig_strt_duration; + icon = Icon_Stop; + ixpos = xpos; break; case TRIG_GO: case TRIG_CONTINUE: - scrollbar(x, ypos + 1, TRIGBAR_WIDTH, TRIG_HEIGHT - 2, - TRIGBAR_WIDTH, TRIGBAR_WIDTH, TRIGBAR_WIDTH, HORIZONTAL); - lcd_mono_bitmap(bitmap_icons_7x8[Icon_Record], - TRIG_WIDTH - ICON_PLAY_STATE_WIDTH, ypos, - ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT); + barstart = TRIGBAR_WIDTH; + barend = TRIGBAR_WIDTH; + icon = Icon_Record; + ixpos = TRIG_WIDTH - ICON_PLAY_STATE_WIDTH; break; - case TRIG_POSTREC: - time_left = trig_stp_hold - (current_tick - trig_lowtime); - time_left = time_left * TRIGBAR_WIDTH / trig_stp_hold; - scrollbar(x, ypos + 1, TRIGBAR_WIDTH, TRIG_HEIGHT - 2, - TRIGBAR_WIDTH, time_left, TRIGBAR_WIDTH, HORIZONTAL); - lcd_mono_bitmap(bitmap_icons_7x8[Icon_Record], - TRIG_WIDTH - ICON_PLAY_STATE_WIDTH, ypos, - ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT); + case TRIG_POSTREC: + barstart = TRIGBAR_WIDTH + - TRIGBAR_WIDTH * (current_tick - trig_lowtime) + / trig_stp_hold; + barend = TRIGBAR_WIDTH; + icon = Icon_Record; + ixpos = TRIG_WIDTH - ICON_PLAY_STATE_WIDTH; break; - } + default: + return; + } + scrollbar(xpos + ICON_PLAY_STATE_WIDTH + 1, ypos + 1, + TRIGBAR_WIDTH, TRIG_HEIGHT - 2, + TRIGBAR_WIDTH, barstart, barend, HORIZONTAL); + lcd_mono_bitmap(bitmap_icons_7x8[icon], ixpos, ypos, + ICON_PLAY_STATE_WIDTH, STATUSBAR_HEIGHT); } #endif int peak_meter_draw_get_btn(int x, int y, int width, int height) { - int button; + int button = BUTTON_NONE; long next_refresh = current_tick; long next_big_refresh = current_tick + HZ / 10; - button = BUTTON_NONE; +#ifndef SIMULATOR + bool highperf = !ata_disk_is_active(); +#else + bool highperf = false; +#endif + bool dopeek = true; - while (!TIME_AFTER(current_tick, next_big_refresh)) { + while (TIME_BEFORE(current_tick, next_big_refresh)) { button = button_get(false); if (button != BUTTON_NONE) { break; } - sleep(MAX(next_refresh - current_tick, 0) - 1); - next_refresh = current_tick + HZ / peak_meter_fps; - peak_meter_peek(); - peak_meter_draw(x, y, width, height); - lcd_update_rect(x, y, width, height); + if (dopeek) { /* Peek only once per refresh when disk is */ + peak_meter_peek(); /* spinning, but as often as possible */ + dopeek = highperf; /* otherwise. */ + yield(); + } else { + sleep(0); /* Sleep until end of current tick. */ + } + if (TIME_AFTER(current_tick, next_refresh)) { + peak_meter_draw(x, y, width, height); + lcd_update_rect(x, y, width, height); + next_refresh += HZ / PEAK_METER_FPS; + dopeek = true; + } } + return button; } #ifdef PM_DEBUG -static void peak_meter_clear_histogram(void) { +static void peak_meter_clear_histogram(void) +{ int i = 0; for (i = 0; i < TICKS_PER_DRAW_SIZE; i++) { ticks_per_redraw[i] = (unsigned int)0; @@ -1179,7 +1164,8 @@ static void peak_meter_clear_histogram(void) { } } -bool peak_meter_histogram(void) { +bool peak_meter_histogram(void) +{ int i; int btn = BUTTON_NONE; while ((btn & BUTTON_OFF) != BUTTON_OFF ) @@ -1210,7 +1196,7 @@ bool peak_meter_histogram(void) { lcd_hline(0, x, y + i); } lcd_update(); - + btn = button_get(true); if (btn == BUTTON_PLAY) { peak_meter_clear_histogram(); diff --git a/apps/recorder/peakmeter.h b/apps/recorder/peakmeter.h index 3c0a28bf3b..5513dfacf1 100644 --- a/apps/recorder/peakmeter.h +++ b/apps/recorder/peakmeter.h @@ -19,13 +19,14 @@ #ifndef __PEAKMETER_H__ #define __PEAKMETER_H__ +#define PEAK_METER_FPS 20 + /*#define PM_DEBUG */ #ifdef PM_DEBUG extern bool peak_meter_histogram(void); #endif extern bool peak_meter_enabled; -extern int peak_meter_fps; extern void peak_meter_playback(bool playback); extern void peak_meter_draw(int x, int y, int width, int height); @@ -39,8 +40,8 @@ extern void peak_meter_set_min(int newmin); extern int peak_meter_get_min(void); extern void peak_meter_set_max(int newmax); extern int peak_meter_get_max(void); -extern void peak_meter_set_use_dbfs(int use); -extern int peak_meter_get_use_dbfs(void); +extern void peak_meter_set_use_dbfs(bool use); +extern bool peak_meter_get_use_dbfs(void); extern int calc_db (int isample); extern int peak_meter_db2sample(int db); extern unsigned short peak_meter_scale_value(unsigned short val, int meterwidth); diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c index 4e6c52ea84..a0280ecf1f 100644 --- a/apps/recorder/radio.c +++ b/apps/recorder/radio.c @@ -304,7 +304,7 @@ bool radio_screen(void) if(search_dir) button = button_get(false); else - button = button_get_w_tmo(HZ / peak_meter_fps); + button = button_get_w_tmo(HZ / PEAK_METER_FPS); switch(button) { case FM_STOP: @@ -479,13 +479,10 @@ bool radio_screen(void) /* Only display the peak meter when not recording */ if(!audio_status()) { - lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - lcd_fillrect(0, 8 + fh*(top_of_screen + 3), LCD_WIDTH, fh); - lcd_set_drawmode(DRMODE_SOLID); peak_meter_draw(0, 8 + fh*(top_of_screen + 3), LCD_WIDTH, fh); lcd_update_rect(0, 8 + fh*(top_of_screen + 3), LCD_WIDTH, fh); } - + if(TIME_AFTER(current_tick, timeout)) { timeout = current_tick + HZ; -- cgit v1.2.3