ref: b106f2ad26fda2a76299020097a8cb50fda01dd2
parent: bb56888a97ad1ab8facfd915c095fb5ba79a0b0d
author: robs <robs>
date: Sun Feb 17 12:32:55 EST 2008
simple V.U. meter
--- a/AUTHORS
+++ b/AUTHORS
@@ -24,6 +24,7 @@
Others: soxi, open input files via URL, file merging, play
multiple files with mixed format types, play with replay-gain,
building with cmake, much manual improvement and expansion,
+ improved displays with -S & -V including V.U. and clips,
various fixes, enhancements and clean-ups.
Contributors:
--- a/ChangeLog
+++ b/ChangeLog
@@ -37,6 +37,7 @@
o Command line support for multiple file comments. (robs)
o Added soxi utility to extract/display file header fields. (robs)
o Added pkg-config support. (Pascal Giard)
+ o Added simple V.U. meter. (robs)
Bug fixes:
--- a/sox.1
+++ b/sox.1
@@ -253,6 +253,16 @@
(Note that the syntax of the
.B set
command may vary from system to system.)
+.SP
+To set a suitable recording level, a V.U. meter is usually used. SoX includes a
+simple V.U. meter that can be invoked as follows:
+.EX
+ rec -n
+.EE
+The recording level should be adjusted (using the system mixer program)
+so that the meter is `in the red' (a single exclamation mark is shown)
+\fIat most very occasionally\fR, and never `off the scale' (two
+exclamation marks are shown).
.SS Accuracy
Many file formats that compress audio discard some of the audio signal
information whilst doing so; converting to such a format then converting
@@ -543,6 +553,36 @@
Display input file format/header information and input file(s)
processing progress in terms of elapsed/remaining time and percentage
complete.
+Also displays the number of samples written to the output file, a V.U. meter,
+and an indication if clipping has occurred.
+The V.U. meter shows up to two channels and is calibrated for digital
+audio as follows:
+.TS
+center box;
+cI lI lI
+cI lI lI
+r l l.
+dB FSD Display
+>= (right channel) Comment
+\-25.5 \-
+\-23.5 T{
+=
+T}
+\-21.5 =\-
+\-19.5 ==
+\-17.5 ==\-
+\-15.5 ===
+\-13.5 ===\-
+\-11.5 ====
+\-9.5 ====\-
+\-7.5 =====
+\-5.5 =====\-
+\-3.5 ======
+\-1.5 =====! `In the red'
+\-0.5 ====!! `Off the scale'
+.TE
+
+.SP
This option is enabled by default when using
SoX to play or record audio.
.TP
--- a/src/sox.c
+++ b/src/sox.c
@@ -134,6 +134,7 @@
static sox_bool user_abort = sox_false;
static sox_bool user_skip = sox_false;
static int success = 0;
+static sox_sample_t omax[2], omin[2];
/* local forward declarations */
@@ -718,7 +719,7 @@
parse_effects(argc, argv);
/* Not the best way for users to do this; now deprecated in favour of soxi. */
- if (!nuser_effects && ofile->filetype && !strcmp(ofile->filetype, "null")) {
+ if (!show_progress && !nuser_effects && ofile->filetype && !strcmp(ofile->filetype, "null")) {
for (i = 0; i < input_count; i++)
report_file_info(files[i]);
exit(0);
@@ -1224,6 +1225,19 @@
sox_sample_t * obuf UNUSED, sox_size_t * isamp, sox_size_t * osamp)
{
size_t len;
+
+ 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) {
+ omax[1] = max(omax[1], ibuf[len + 1]);
+ omin[1] = min(omin[1], ibuf[len + 1]);
+ }
+ else {
+ omax[1] = omax[0];
+ omin[1] = omin[0];
+ }
+ }
for (*osamp = *isamp; *osamp; ibuf += len, *osamp -= len) {
len = sox_write(ofile->ft, ibuf, *osamp);
if (len == 0) {
@@ -1528,6 +1542,24 @@
return string[n];
}
+static char const * vu(unsigned channel)
+{
+ static char const * const text[][2] = {
+ {"", ""}, {"-", "-"}, {"=", "="}, {"-=", "=-"},
+ {"==", "=="}, {"-==", "==-"}, {"===", "==="}, {"-===", "===-"},
+ {"====", "===="}, {"-====", "====-"}, {"=====", "====="},
+ {"-=====", "=====-"}, {"======", "======"},
+ {"!=====", "=====!"}, {"!!====", "====!!"}, /* 2 `red' levels */
+ };
+ int const red = 2, 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;
+ omax[channel] = omin[channel] = 0;
+ return text[index][channel];
+}
+
static void display_status(sox_bool all_done)
{
static struct timeval then;
@@ -1542,9 +1574,10 @@
left_time = max(in_time - read_time, 0);
percentage = max(100. * read_wide_samples / input_wide_samples, 0);
}
- fprintf(stderr, "\rTime: %s [%s] of %s (%-5s) Samples out: %-6sClips: %-5s",
+ 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), sigfigs3(total_clips()));
+ sigfigs3p(percentage), sigfigs3(output_samples),
+ vu(0), vu(1), sigfigs3(total_clips()));
}
if (all_done)
fputc('\n', stderr);