ref: 1ecccdb9ae2721fd209b9af872987a3efa7278a7
parent: 7d66951a4e92e5fd78e9fbe843c82d4ab5992bd5
author: robs <robs>
date: Sun May 6 13:32:09 EDT 2007
Protection against concurrent use of stdin/stdout. Don't allow noiseprof to use stderr (it's for diagnostics). Allow noisered filename to be optional; fail if threshold out of range.
--- a/src/biquad.c
+++ b/src/biquad.c
@@ -66,7 +66,7 @@
p->a2 = p->a2/p->a0;
p->a1 = p->a1/p->a0;
- if (effp->globalinfo->plot == sox_plot_octave) {
+ if (effp->global_info->plot == sox_plot_octave) {
printf(
"%% GNU Octave file (may also work with MATLAB(R) )\n"
"title('SoX effect: %s gain=%g frequency=%g %s=%g (rate=%u)')\n"
@@ -86,7 +86,7 @@
);
return SOX_EOF;
}
- if (effp->globalinfo->plot == sox_plot_gnuplot) {
+ if (effp->global_info->plot == sox_plot_gnuplot) {
printf(
"# gnuplot file\n"
"set title 'SoX effect: %s gain=%g frequency=%g %s=%g (rate=%u)'\n"
--- a/src/compand.c
+++ b/src/compand.c
@@ -137,7 +137,7 @@
for (i = 0; i < l->expectedChannels; ++i)
sox_debug("Channel %i: attack = %g decay = %g", i,
l->channels[i].attack_times[0], l->channels[i].attack_times[1]);
- if (!sox_compandt_show(&l->transfer_fn, effp->globalinfo->plot))
+ if (!sox_compandt_show(&l->transfer_fn, effp->global_info->plot))
return SOX_EOF;
/* Convert attack and decay rates using number of samples */
--- a/src/noiseprof.c
+++ b/src/noiseprof.c
@@ -59,33 +59,34 @@
*/
static int sox_noiseprof_start(eff_t effp)
{
- profdata_t data = (profdata_t) effp->priv;
- unsigned channels = effp->ininfo.channels;
- unsigned i;
+ profdata_t data = (profdata_t) effp->priv;
+ unsigned channels = effp->ininfo.channels;
+ unsigned i;
- if (data->output_filename != NULL) {
- if (strcmp(data->output_filename, "-") != 0)
- data->output_file = fopen(data->output_filename, "w");
- else
- data->output_file = stdout;
- if (data->output_file == NULL) {
- sox_fail("Couldn't open output file %s: %s",
- data->output_filename, strerror(errno));
- }
- } else {
- /* FIXME: We should detect output to stdout, and redirect to stderr. */
- data->output_file = stderr;
+ /* Note: don't fall back to stderr if stdout is unavailable
+ * since we already use stderr for diagnostics. */
+ if (!data->output_filename || !strcmp(data->output_filename, "-")) {
+ if (effp->global_info->global_info->stdout_in_use_by) {
+ sox_fail("stdout already in use by '%s'", effp->global_info->global_info->stdout_in_use_by);
+ return SOX_EOF;
}
+ effp->global_info->global_info->stdout_in_use_by = effp->name;
+ data->output_file = stdout;
+ }
+ else if ((data->output_file = fopen(data->output_filename, "w")) == NULL) {
+ sox_fail("Couldn't open profile file %s: %s", data->output_filename, strerror(errno));
+ return SOX_EOF;
+ }
- data->chandata = (chandata_t*)xcalloc(channels, sizeof(*(data->chandata)));
- data->bufdata = 0;
- for (i = 0; i < channels; i ++) {
- data->chandata[i].sum = (float*)xcalloc(FREQCOUNT, sizeof(float));
- data->chandata[i].profilecount = (int*)xcalloc(FREQCOUNT, sizeof(int));
- data->chandata[i].window = (float*)xcalloc(WINDOWSIZE, sizeof(float));
- }
+ data->chandata = (chandata_t*)xcalloc(channels, sizeof(*(data->chandata)));
+ data->bufdata = 0;
+ for (i = 0; i < channels; i ++) {
+ data->chandata[i].sum = (float*)xcalloc(FREQCOUNT, sizeof(float));
+ data->chandata[i].profilecount = (int*)xcalloc(FREQCOUNT, sizeof(int));
+ data->chandata[i].window = (float*)xcalloc(WINDOWSIZE, sizeof(float));
+ }
- return SOX_SUCCESS;
+ return SOX_SUCCESS;
}
/* Collect statistics from the complete window on channel chan. */
@@ -192,8 +193,9 @@
fprintf(data->output_file, "Channel %d: ", i);
for (j = 0; j < FREQCOUNT; j ++) {
- fprintf(data->output_file, "%s%f", j == 0 ? "" : ", ",
- chan->sum[j] / chan->profilecount[j]);
+ double r = chan->profilecount[j] != 0 ?
+ chan->sum[j] / chan->profilecount[j] : 0;
+ fprintf(data->output_file, "%s%f", j == 0 ? "" : ", ", r);
}
fprintf(data->output_file, "\n");
@@ -203,7 +205,7 @@
free(data->chandata);
- if (data->output_file != stderr && data->output_file != stdout)
+ if (data->output_file != stdout)
fclose(data->output_file);
return (SOX_SUCCESS);
--- a/src/noisered.c
+++ b/src/noisered.c
@@ -16,6 +16,21 @@
#include <string.h>
#include <assert.h>
+#define NUMERIC_PARAMETER(p, min, max) { \
+ char * end_ptr; \
+ double d; \
+ if (argc == 0) break; \
+ d = strtod(*argv, &end_ptr); \
+ if (end_ptr != *argv) { \
+ if (d < min || d > max || *end_ptr != '\0') { \
+ sox_fail(effp->h->usage); \
+ return SOX_EOF; \
+ } \
+ this->p = d; \
+ --argc, ++argv; \
+ } \
+}
+
static sox_effect_t sox_noisered_effect;
typedef struct chandata {
@@ -35,32 +50,29 @@
} * reddata_t;
/*
- * Get the options. Filename is mandatory, though a reasonable default would
- * be stdin (if the input file isn't coming from there, of course!)
+ * Get the options. Default file is stdin (if the audio
+ * input file isn't coming from there, of course!)
*/
-static int sox_noisered_getopts(eff_t effp, int n, char **argv)
+static int sox_noisered_getopts(eff_t effp, int argc, char **argv)
{
- reddata_t data = (reddata_t) effp->priv;
+ reddata_t this = (reddata_t) effp->priv;
- if (n > 2 || n < 1) {
- sox_fail(sox_noisered_effect.usage);
- return (SOX_EOF);
- }
- data->threshold = 0.5;
- data->profile_filename = argv[0];
- if (n == 2)
- {
- data->threshold = atof(argv[1]);
+ if (argc > 0) {
+ this->profile_filename = argv[0];
+ ++argv;
+ --argc;
+ }
- if (data->threshold > 1)
- {
- data->threshold = 1;
- } else if (data->threshold < 0)
- {
- data->threshold = 0;
- }
- }
- return (SOX_SUCCESS);
+ this->threshold = 0.5;
+ do { /* break-able block */
+ NUMERIC_PARAMETER(threshold, 0, 1);
+ } while (0);
+
+ if (argc != 0) {
+ sox_fail(effp->h->usage);
+ return SOX_EOF;
+ }
+ return SOX_SUCCESS;
}
/*
@@ -84,13 +96,17 @@
}
/* Here we actually open the input file. */
- if (strcmp(data->profile_filename, "-") == 0)
+ if (!data->profile_filename || !strcmp(data->profile_filename, "-")) {
+ if (effp->global_info->global_info->stdin_in_use_by) {
+ sox_fail("stdin already in use by '%s'", effp->global_info->global_info->stdin_in_use_by);
+ return SOX_EOF;
+ }
+ effp->global_info->global_info->stdin_in_use_by = effp->name;
ifp = stdin;
- else
- ifp = fopen(data->profile_filename, "r");
- if (ifp == NULL) {
+ }
+ else if ((ifp = fopen(data->profile_filename, "r")) == NULL) {
sox_fail("Couldn't open profile file %s: %s",
- data->profile_filename, strerror(errno));
+ data->profile_filename, strerror(errno));
return SOX_EOF;
}
@@ -121,7 +137,7 @@
channels, fchannels);
return SOX_EOF;
}
- if (strcmp(data->profile_filename, "-") != 0)
+ if (ifp != stdin)
fclose(ifp);
return (SOX_SUCCESS);
--- a/src/rabbit.c
+++ b/src/rabbit.c
@@ -89,8 +89,8 @@
/* The next line makes the "speed" effect accurate; it's needed because
* ininfo.rate (sox_rate_t) isn't floating point (but it's probably not worth
* changing sox_rate_t just because of this): */
- double in_rate = floor(effp->ininfo.rate / effp->globalinfo->speed + .5)
- * effp->globalinfo->speed;
+ double in_rate = floor(effp->ininfo.rate / effp->global_info->speed + .5)
+ * effp->global_info->speed;
if (in_rate == effp->outinfo.rate)
return SOX_EFF_NULL;
--- a/src/resample.c
+++ b/src/resample.c
@@ -201,8 +201,8 @@
/* The next line makes the "speed" effect accurate; it's needed because
* ininfo.rate (sox_rate_t) isn't floating point (but it's probably not worth
* changing sox_rate_t just because of this): */
- double in_rate = floor(effp->ininfo.rate / effp->globalinfo->speed + .5)
- * effp->globalinfo->speed;
+ double in_rate = floor(effp->ininfo.rate / effp->global_info->speed + .5)
+ * effp->global_info->speed;
if (in_rate == effp->outinfo.rate)
return SOX_EFF_NULL;
--- a/src/sox.c
+++ b/src/sox.c
@@ -63,7 +63,7 @@
static sox_size_t mixing_clips = 0;
static sox_bool repeatable_random = sox_false; /* Whether to invoke srand. */
static sox_bool interactive = sox_false;
-static sox_globalinfo_t globalinfo = {sox_false, 1};
+static sox_effects_global_info_t effects_global_info = {sox_false, 1, &sox_global_info};
static sox_bool uservolume = sox_false;
typedef enum {RG_off, RG_track, RG_album} rg_mode;
static rg_mode replay_gain_mode = RG_off;
@@ -807,7 +807,7 @@
break;
case 7:
- globalinfo.plot = enum_option(option_index, plot_methods);
+ effects_global_info.plot = enum_option(option_index, plot_methods);
break;
case 8:
@@ -1124,7 +1124,7 @@
if (ofile->signal.channels == 0)
ofile->signal.channels = combiner.channels;
- combiner.rate = combiner.rate * globalinfo.speed + .5;
+ combiner.rate = combiner.rate * effects_global_info.speed + .5;
for (i = 0; i < nuser_effects; i++)
known_length = known_length && !(user_efftab[i].h->flags & SOX_EFF_LENGTH);
@@ -1321,7 +1321,7 @@
sox_warn("Effect `%s' is deprecated and may be removed in a future release; please refer to the manual sox(1) for an alternative effect", e->name);
optind++; /* Skip past effect name */
- e->globalinfo = &globalinfo;
+ e->global_info = &effects_global_info;
getopts = e->h->getopts? e->h->getopts : sox_effect_nothing_getopts;
if (getopts(e, argc_effect, &argv[optind]) == SOX_EOF)
exit(2);
@@ -1355,7 +1355,7 @@
sox_geteffect(e, name);
/* Set up & give default opts for added effects */
- e->globalinfo = &globalinfo;
+ e->global_info = &effects_global_info;
getopts = e->h->getopts? e->h->getopts : sox_effect_nothing_getopts;
if (getopts(e, 0, NULL) == SOX_EOF)
exit(2);
--- a/src/sox.h
+++ b/src/sox.h
@@ -186,16 +186,26 @@
SOX_ENCODINGS /* End of list marker */
} sox_encoding_t;
+typedef struct sox_global_info /* Global parameters (for effects & formats) */
+{
+ char const * stdin_in_use_by;
+ char const * stdout_in_use_by;
+} sox_global_info_t;
+
typedef enum {sox_plot_off, sox_plot_octave, sox_plot_gnuplot} sox_plot_t;
-/* Global parameters (for effects) */
-
-typedef struct sox_globalinfo
+typedef struct sox_effects_global_info /* Global parameters (for effects) */
{
sox_plot_t plot; /* To help the user choose effect & options */
double speed; /* Gather up all speed changes here, then resample */
-} sox_globalinfo_t;
+ sox_global_info_t * global_info;
+} sox_effects_global_info_t;
+typedef struct sox_formats_global_info /* Global parameters (for formats) */
+{
+ sox_global_info_t * global_info;
+} sox_formats_global_info_t;
+
typedef enum {SOX_OPTION_NO, SOX_OPTION_YES, SOX_OPTION_DEFAULT} sox_option_t;
/* Signal parameters */
@@ -380,7 +390,7 @@
struct sox_effect
{
char const *name; /* effect name */
- struct sox_globalinfo * globalinfo;/* global parameters */
+ struct sox_effects_global_info * global_info;/* global parameters */
struct sox_signalinfo ininfo; /* input signal specifications */
struct sox_signalinfo outinfo; /* output signal specifications */
const sox_effect_t *h; /* effects driver */
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -210,6 +210,7 @@
* data to get max performance.
*/
extern sox_size_t sox_bufsiz;
+extern sox_global_info_t sox_global_info;
extern const char sox_readerr[];
extern const char sox_writerr[];
--- a/src/soxio.c
+++ b/src/soxio.c
@@ -26,6 +26,7 @@
#endif
sox_size_t sox_bufsiz = 8192;
+sox_global_info_t sox_global_info;
void set_endianness_if_not_already_set(ft_t ft)
{
@@ -129,10 +130,14 @@
/* Open file handler based on input name. Used stdin file handler
* if the filename is "-"
*/
- if (!strcmp(ft->filename, "-"))
- {
- SET_BINARY_MODE(stdin);
- ft->fp = stdin;
+ if (!strcmp(ft->filename, "-")) {
+ if (sox_global_info.stdin_in_use_by) {
+ sox_fail("'-' (stdin) already in use by '%s'", sox_global_info.stdin_in_use_by);
+ goto input_error;
+ }
+ sox_global_info.stdin_in_use_by = "audio input";
+ SET_BINARY_MODE(stdin);
+ ft->fp = stdin;
}
else if ((ft->fp = xfopen(ft->filename, "rb")) == NULL)
{
@@ -241,8 +246,12 @@
/* Open file handler based on output name. Used stdout file handler
* if the filename is "-"
*/
- if (!strcmp(ft->filename, "-"))
- {
+ if (!strcmp(ft->filename, "-")) {
+ if (sox_global_info.stdout_in_use_by) {
+ sox_fail("'-' (stdout) already in use by '%s'", sox_global_info.stdout_in_use_by);
+ goto output_error;
+ }
+ sox_global_info.stdout_in_use_by = "audio output";
SET_BINARY_MODE(stdout);
ft->fp = stdout;
}
--- a/src/speed.c
+++ b/src/speed.c
@@ -42,7 +42,7 @@
if (scanned == 1 || (scanned == 2 && c == 'c')) {
is_cents |= scanned == 2;
if (is_cents || speed > 0) {
- effp->globalinfo->speed *= is_cents? pow(2., speed/1200) : speed;
+ effp->global_info->speed *= is_cents? pow(2., speed/1200) : speed;
return SOX_SUCCESS;
}
}