ref: 7765a3215eadbb56ca67429b93538dfc559cbd12
parent: 38f21528d72f4fc3f5408fcd5104190d1d4e588c
author: robs <robs>
date: Wed Feb 20 03:12:52 EST 2008
VU meter improvements: o delineated meter limits o now only one red level: >= -1dB FSD o add 3-second peak hold display (dB headroom)
--- a/src/sox.c
+++ b/src/sox.c
@@ -422,7 +422,7 @@
{
size_t len;
- for (len = 0; len < *isamp; len += effp->ininfo.channels) {
+ if (show_progress) for (len = 0; len < *isamp; len += effp->ininfo.channels) {
omax[0] = max(omax[0], ibuf[len]);
omin[0] = min(omin[0], ibuf[len]);
if (effp->ininfo.channels > 1) {
@@ -557,35 +557,58 @@
return string[n];
}
+static sox_bool since(struct timeval * then, double secs, sox_bool always_reset)
+{
+ sox_bool ret;
+ struct timeval now;
+ time_t d;
+ gettimeofday(&now, NULL);
+ d = now.tv_sec - then->tv_sec;
+ ret = d > ceil(secs) || now.tv_usec - then->tv_usec + d * TIME_FRAC >= secs * TIME_FRAC;
+ if (ret || always_reset)
+ *then = now;
+ return ret;
+}
+
+#define MIN_HEADROOM 6.
+static double min_headroom = MIN_HEADROOM;
+
static char const * vu(unsigned channel)
{
+ static struct timeval then;
static char const * const text[][2] = {
+ /* White: 2dB steps */
{"", ""}, {"-", "-"}, {"=", "="}, {"-=", "=-"},
{"==", "=="}, {"-==", "==-"}, {"===", "==="}, {"-===", "===-"},
{"====", "===="}, {"-====", "====-"}, {"=====", "====="},
{"-=====", "=====-"}, {"======", "======"},
- {"!=====", "=====!"}, {"!!====", "====!!"}, /* 2 `red' levels */
+ /* Red: 1dB steps */
+ {"!=====", "=====!"},
};
- int const red = 2, white = array_length(text) - red;
+ int const red = 1, white = array_length(text) - red;
double const MAX = SOX_SAMPLE_MAX, MIN = SOX_SAMPLE_MIN;
double linear = max(omax[channel] / MAX, omin[channel] / MIN);
- int vu_dB = linear? floor(2 * white + red - .5 + linear_to_dB(linear)) : 0;
- int index = vu_dB < 2 * white? max(vu_dB / 2, 0) : vu_dB - white;
+ double dB = linear_to_dB(linear);
+ int vu_dB = linear? floor(2 * white + red + dB) : 0;
+ int index = vu_dB < 2 * white? max(vu_dB / 2, 0) : min(vu_dB - white, red + white - 1);
omax[channel] = omin[channel] = 0;
+ if (-dB < min_headroom) {
+ gettimeofday(&then, NULL);
+ min_headroom = -dB;
+ }
+ else if (since(&then, 3., sox_false))
+ min_headroom = -dB;
+
return text[index][channel];
}
-static sox_bool since(struct timeval * then, double secs, sox_bool always_reset)
+static char * headroom(void)
{
- sox_bool ret;
- struct timeval now;
- time_t d;
- gettimeofday(&now, NULL);
- d = now.tv_sec - then->tv_sec;
- ret = d > ceil(secs) || now.tv_usec - then->tv_usec + d * TIME_FRAC >= secs * TIME_FRAC;
- if (ret || always_reset)
- *then = now;
- return ret;
+ static char buff[10];
+ unsigned h = (unsigned)(min_headroom * 10);
+ if (min_headroom >= MIN_HEADROOM) return " ";
+ sprintf(buff, "Hd:%u.%u", h /10, h % 10);
+ return buff;
}
static void display_status(sox_bool all_done)
@@ -593,7 +616,7 @@
static struct timeval then;
if (!show_progress)
return;
- if (all_done || since(&then, .15, sox_false)) {
+ if (all_done || since(&then, .1, sox_false)) {
double read_time = (double)read_wide_samples / combiner.rate;
double left_time = 0, in_time = 0, percentage = 0;
@@ -602,10 +625,10 @@
left_time = max(in_time - read_time, 0);
percentage = max(100. * read_wide_samples / input_wide_samples, 0);
}
- fprintf(stderr, "\r%s [%s] of %s (%-5s) Samps out:%-5s%6s|%-6sClips:%-5s",
- str_time(read_time), str_time(left_time), str_time(in_time),
- sigfigs3p(percentage), sigfigs3(output_samples),
- vu(0), vu(1), sigfigs3(total_clips()));
+ fprintf(stderr, "\r%-5s %s [%s] of %s Out:%-5s [%6s|%-6s]%s Clip:%-5s",
+ sigfigs3p(percentage), str_time(read_time), str_time(left_time),
+ str_time(in_time), sigfigs3(output_samples),
+ vu(0), vu(1), headroom(), sigfigs3(total_clips()));
}
if (all_done)
fputc('\n', stderr);