ref: 9df5ab9d774de07f9511436de700b6371c3ecd7c
parent: f6c13968b67990f3648d5a15858ea9f4954625c2
author: robs <robs>
date: Wed Oct 3 16:58:43 EDT 2007
removing static data from effects chain
--- a/src/effects.c
+++ b/src/effects.c
@@ -32,7 +32,7 @@
sox_effects_globals_t sox_effects_globals =
- {sox_false, 1, &sox_globals};
+ {sox_plot_off, 1, &sox_globals};
int sox_usage(sox_effect_t * effp)
{
@@ -90,9 +90,6 @@
/* Effects chain: */
-sox_effect_t * sox_effects[SOX_MAX_EFFECTS];
-unsigned sox_neffects;
-
/* Effect can call in start() or flow() to set minimum input size to flow() */
int sox_effect_set_imin(sox_effect_t * effp, sox_size_t imin)
{
@@ -111,7 +108,7 @@
* output rate and channels the effect does produce are written back to *in,
* ready for the next effect in the chain.
*/
-int sox_add_effect(sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t
+int sox_add_effect(sox_effects_chain_t * chain, sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t
const * out)
{
int ret, (*start)(sox_effect_t * effp) = effp->handler.start;
@@ -122,6 +119,7 @@
sox_report("has no effect (is a proxy effect)");
return SOX_SUCCESS;
}
+ effp->global_info = &chain->global_info;
effp->ininfo = *in;
effp->outinfo = *out;
if (!(effp->handler.flags & SOX_EFF_CHAN))
@@ -146,31 +144,29 @@
*in = effp->outinfo;
- if (sox_neffects == SOX_MAX_EFFECTS) {
+ if (chain->length == SOX_MAX_EFFECTS) {
sox_fail("Too many effects!");
return SOX_EOF;
}
- sox_effects[sox_neffects] =
- xcalloc(effp->flows, sizeof(sox_effects[sox_neffects][0]));
- sox_effects[sox_neffects][0] = *effp;
+ chain->effects[chain->length] =
+ xcalloc(effp->flows, sizeof(chain->effects[chain->length][0]));
+ chain->effects[chain->length][0] = *effp;
for (f = 1; f < effp->flows; ++f) {
- sox_effects[sox_neffects][f] = eff0;
- sox_effects[sox_neffects][f].flow = f;
- if (start(&sox_effects[sox_neffects][f]) != SOX_SUCCESS)
+ chain->effects[chain->length][f] = eff0;
+ chain->effects[chain->length][f].flow = f;
+ if (start(&chain->effects[chain->length][f]) != SOX_SUCCESS)
return SOX_EOF;
}
- ++sox_neffects;
+ ++chain->length;
return SOX_SUCCESS;
}
-static sox_ssample_t **ibufc, **obufc; /* Channel interleave buffers */
-
-static int flow_effect(unsigned n)
+static int flow_effect(sox_effects_chain_t * chain, unsigned n)
{
- sox_effect_t * effp1 = &sox_effects[n - 1][0];
- sox_effect_t * effp = &sox_effects[n][0];
+ sox_effect_t * effp1 = &chain->effects[n - 1][0];
+ sox_effect_t * effp = &chain->effects[n][0];
int effstatus = SOX_SUCCESS;
sox_size_t i, f;
const sox_ssample_t *ibuf;
@@ -187,13 +183,13 @@
ibuf = &effp1->obuf[effp1->odone];
for (i = 0; i < idone; i += effp->flows)
for (f = 0; f < effp->flows; ++f)
- ibufc[f][i / effp->flows] = *ibuf++;
+ chain->ibufc[f][i / effp->flows] = *ibuf++;
for (f = 0; f < effp->flows; ++f) {
sox_size_t idonec = idone / effp->flows;
sox_size_t odonec = odone / effp->flows;
- int eff_status_c = effp->handler.flow(&sox_effects[n][f],
- ibufc[f], obufc[f], &idonec, &odonec);
+ int eff_status_c = effp->handler.flow(&chain->effects[n][f],
+ chain->ibufc[f], chain->obufc[f], &idonec, &odonec);
if (f && (idonec != idone_last || odonec != odone_last)) {
sox_fail("flowed asymmetrically!");
effstatus = SOX_EOF;
@@ -207,7 +203,7 @@
for (i = 0; i < odone_last; ++i)
for (f = 0; f < effp->flows; ++f)
- *obuf++ = obufc[f][i];
+ *obuf++ = chain->obufc[f][i];
idone = f * idone_last;
odone = f * odone_last;
@@ -227,9 +223,9 @@
}
/* The same as flow_effect but with no input */
-static int drain_effect(unsigned n)
+static int drain_effect(sox_effects_chain_t * chain, unsigned n)
{
- sox_effect_t * effp = &sox_effects[n][0];
+ sox_effect_t * effp = &chain->effects[n][0];
int effstatus = SOX_SUCCESS;
sox_size_t i, f;
sox_size_t odone = sox_globals.bufsiz - effp->olen;
@@ -242,7 +238,7 @@
for (f = 0; f < effp->flows; ++f) {
sox_size_t odonec = odone / effp->flows;
- int eff_status_c = effp->handler.drain(&sox_effects[n][f], obufc[f], &odonec);
+ int eff_status_c = effp->handler.drain(&chain->effects[n][f], chain->obufc[f], &odonec);
if (f && (odonec != odone_last)) {
sox_fail("drained asymmetrically!");
effstatus = SOX_EOF;
@@ -255,7 +251,7 @@
for (i = 0; i < odone_last; ++i)
for (f = 0; f < effp->flows; ++f)
- *obuf++ = obufc[f][i];
+ *obuf++ = chain->obufc[f][i];
odone = f * odone_last;
}
if (!odone) /* This is the only thing that drain has and flow hasn't */
@@ -267,7 +263,7 @@
}
/* Flow data through the effects chain until an effect or callback gives EOF */
-int sox_flow_effects(int (* callback)(sox_bool all_done))
+int sox_flow_effects(sox_effects_chain_t * chain, int (* callback)(sox_bool all_done))
{
int flow_status = SOX_SUCCESS;
sox_size_t e, source_e = 0; /* effect indices */
@@ -274,33 +270,33 @@
sox_size_t f, max_flows = 0;
sox_bool draining = sox_true;
- for (e = 0; e < sox_neffects; ++e) {
- sox_effects[e][0].obuf = xmalloc(sox_globals.bufsiz * sizeof(sox_effects[e][0].obuf[0]));
- sox_effects[e][0].odone = sox_effects[e][0].olen = 0;
- max_flows = max(max_flows, sox_effects[e][0].flows);
+ for (e = 0; e < chain->length; ++e) {
+ chain->effects[e][0].obuf = xmalloc(sox_globals.bufsiz * sizeof(chain->effects[e][0].obuf[0]));
+ chain->effects[e][0].odone = chain->effects[e][0].olen = 0;
+ max_flows = max(max_flows, chain->effects[e][0].flows);
}
- ibufc = xcalloc(max_flows, sizeof(*ibufc));
- obufc = xcalloc(max_flows, sizeof(*obufc));
+ chain->ibufc = xcalloc(max_flows, sizeof(*chain->ibufc));
+ chain->obufc = xcalloc(max_flows, sizeof(*chain->obufc));
for (f = 0; f < max_flows; ++f) {
- ibufc[f] = xcalloc(sox_globals.bufsiz / 2, sizeof(ibufc[f][0]));
- obufc[f] = xcalloc(sox_globals.bufsiz / 2, sizeof(obufc[f][0]));
+ chain->ibufc[f] = xcalloc(sox_globals.bufsiz / 2, sizeof(chain->ibufc[f][0]));
+ chain->obufc[f] = xcalloc(sox_globals.bufsiz / 2, sizeof(chain->obufc[f][0]));
}
- e = sox_neffects - 1;
- while (source_e < sox_neffects) {
-#define have_imin (e > 0 && e < sox_neffects && sox_effects[e - 1][0].olen - sox_effects[e - 1][0].odone >= sox_effects[e][0].imin)
+ e = chain->length - 1;
+ while (source_e < chain->length) {
+#define have_imin (e > 0 && e < chain->length && chain->effects[e - 1][0].olen - chain->effects[e - 1][0].odone >= chain->effects[e][0].imin)
if (e == source_e && (draining || !have_imin)) {
- if (drain_effect(e) == SOX_EOF) {
+ if (drain_effect(chain, e) == SOX_EOF) {
++source_e;
draining = sox_false;
}
- } else if (have_imin && flow_effect(e) == SOX_EOF) {
+ } else if (have_imin && flow_effect(chain, e) == SOX_EOF) {
flow_status = SOX_EOF;
source_e = e;
draining = sox_true;
}
- if (e < sox_neffects && sox_effects[e][0].olen > sox_effects[e][0].odone) /* False for output */
+ if (e < chain->length && chain->effects[e][0].olen > chain->effects[e][0].odone) /* False for output */
++e;
else if (e == source_e)
draining = sox_true;
@@ -307,7 +303,7 @@
else if ((int)--e < (int)source_e)
e = source_e;
- if (callback && callback(source_e == sox_neffects) != SOX_SUCCESS) {
+ if (callback && callback(source_e == chain->length) != SOX_SUCCESS) {
flow_status = SOX_EOF; /* Client has requested to stop the flow. */
break;
}
@@ -314,46 +310,46 @@
}
for (f = 0; f < max_flows; ++f) {
- free(ibufc[f]);
- free(obufc[f]);
+ free(chain->ibufc[f]);
+ free(chain->obufc[f]);
}
- free(obufc);
- free(ibufc);
+ free(chain->obufc);
+ free(chain->ibufc);
- for (e = 0; e < sox_neffects; ++e)
- free(sox_effects[e][0].obuf);
+ for (e = 0; e < chain->length; ++e)
+ free(chain->effects[e][0].obuf);
return flow_status;
}
-sox_size_t sox_effects_clips(void)
+sox_size_t sox_effects_clips(sox_effects_chain_t * chain)
{
unsigned i, f;
sox_size_t clips = 0;
- for (i = 1; i < sox_neffects - 1; ++i)
- for (f = 0; f < sox_effects[i][0].flows; ++f)
- clips += sox_effects[i][f].clips;
+ for (i = 1; i < chain->length - 1; ++i)
+ for (f = 0; f < chain->effects[i][0].flows; ++f)
+ clips += chain->effects[i][f].clips;
return clips;
}
-sox_size_t sox_stop_effect(sox_size_t e)
+sox_size_t sox_stop_effect(sox_effects_chain_t * chain, sox_size_t e)
{
unsigned f;
- sox_effect_t * effp = &sox_effects[e][0];
+ sox_effect_t * effp = &chain->effects[e][0];
sox_size_t clips = 0;
for (f = 0; f < effp->flows; ++f) {
- effp->handler.stop(&sox_effects[e][f]);
- clips += sox_effects[e][f].clips;
+ effp->handler.stop(&chain->effects[e][f]);
+ clips += chain->effects[e][f].clips;
}
return clips;
}
/* Remove all effects from the chain */
-void sox_delete_effects(void)
+void sox_delete_effects(sox_effects_chain_t * chain)
{
- while (sox_neffects)
- free(sox_effects[--sox_neffects]);
+ while (chain->length)
+ free(chain->effects[--chain->length]);
}
--- a/src/sox.c
+++ b/src/sox.c
@@ -126,8 +126,10 @@
#define MAX_USER_EFF (SOX_MAX_EFFECTS - 4)
static sox_effect_t user_efftab[MAX_USER_EFF];
static unsigned nuser_effects;
+static sox_effects_chain_t ofile_effects_chain;
+
/* Flowing */
static sox_signalinfo_t combiner, ofile_signal;
@@ -900,7 +902,7 @@
break;
case 7:
- sox_effects_globals.plot = enum_option(option_index, plot_methods);
+ ofile_effects_chain.global_info.plot = enum_option(option_index, plot_methods);
break;
case 8:
@@ -1289,7 +1291,7 @@
return &handler;
}
-static void add_auto_effect(char const * name, sox_signalinfo_t * signal)
+static void add_auto_effect(sox_effects_chain_t * chain, char const * name, sox_signalinfo_t * signal)
{
sox_effect_t eff;
@@ -1298,12 +1300,12 @@
eff.handler.getopts(&eff, 0, NULL); /* Set up with default opts */
/* But could fail here */
- if (sox_add_effect(&eff, signal, &ofile->ft->signal) != SOX_SUCCESS)
+ if (sox_add_effect(chain, &eff, signal, &ofile->ft->signal) != SOX_SUCCESS)
exit(2);
}
/* If needed effects are not given, auto-add at (performance) optimal point. */
-static void add_effects(void)
+static void add_effects(sox_effects_chain_t * chain)
{
sox_signalinfo_t signal = combiner;
unsigned i, min_chan = 0, min_rate = 0;
@@ -1318,36 +1320,36 @@
}
/* 1st `effect' in the chain is the input combiner */
sox_create_effect(&eff, input_combiner_effect_fn());
- sox_add_effect(&eff, &signal, &ofile->ft->signal);
+ sox_add_effect(chain, &eff, &signal, &ofile->ft->signal);
/* Add auto effects if appropriate; add user specified effects */
for (i = 0; i <= nuser_effects; i++) {
/* If reducing channels, it's faster to do so before all other effects: */
if (signal.channels > ofile->ft->signal.channels && i >= min_chan)
- add_auto_effect("mixer", &signal);
+ add_auto_effect(chain, "mixer", &signal);
/* If reducing rate, it's faster to do so before all other effects
* (except reducing channels): */
if (signal.rate > ofile->ft->signal.rate && i >= min_rate)
- add_auto_effect("resample", &signal);
+ add_auto_effect(chain, "resample", &signal);
if (i < nuser_effects)
- if (sox_add_effect(&user_efftab[i], &signal, &ofile->ft->signal) != SOX_SUCCESS)
+ if (sox_add_effect(chain, &user_efftab[i], &signal, &ofile->ft->signal) != SOX_SUCCESS)
exit(2);
}
/* Add auto effects if still needed at this point */
if (signal.rate != ofile->ft->signal.rate)
- add_auto_effect("resample", &signal); /* Must be up-sampling */
+ add_auto_effect(chain, "resample", &signal); /* Must be up-sampling */
if (signal.channels != ofile->ft->signal.channels)
- add_auto_effect("mixer", &signal); /* Must be increasing channels */
+ add_auto_effect(chain, "mixer", &signal); /* Must be increasing channels */
/* Last `effect' in the chain is the output file */
sox_create_effect(&eff, output_effect_fn());
- if (sox_add_effect(&eff, &signal, &ofile->ft->signal) != SOX_SUCCESS)
+ if (sox_add_effect(chain, &eff, &signal, &ofile->ft->signal) != SOX_SUCCESS)
exit(2);
- for (i = 0; i < sox_neffects; ++i) {
- sox_effect_t * effp = &sox_effects[i][0];
+ for (i = 0; i < chain->length; ++i) {
+ sox_effect_t const * effp = &chain->effects[i][0];
sox_report("effects chain: %-10s %gHz %u channels %u bits %s",
effp->handler.name, effp->ininfo.rate, effp->ininfo.channels, effp->ininfo.size * 8,
(effp->handler.flags & SOX_EFF_MCHAN)? "(multi)" : "");
@@ -1366,9 +1368,9 @@
* This hack is a huge time savings when trimming
* gigs of audio data into managable chunks
*/
- if (input_count == 1 && sox_neffects > 1 && strcmp(sox_effects[1][0].handler.name, "trim") == 0) {
+ if (input_count == 1 && ofile_effects_chain.length > 1 && strcmp(ofile_effects_chain.effects[1][0].handler.name, "trim") == 0) {
if ((files[0]->ft->handler->flags & SOX_FILE_SEEK) && files[0]->ft->seekable){
- sox_size_t offset = sox_trim_get_start(&sox_effects[1][0]);
+ sox_size_t offset = sox_trim_get_start(&ofile_effects_chain.effects[1][0]);
if (offset && sox_seek(files[0]->ft, offset, SOX_SEEK_SET) != SOX_EOF) {
read_wide_samples = offset / files[0]->ft->signal.channels;
/* Assuming a failed seek stayed where it was. If the
@@ -1375,7 +1377,7 @@
* seek worked then reset the start location of
* trim so that it thinks user didn't request a skip.
*/
- sox_trim_clear_start(&sox_effects[1][0]);
+ sox_trim_clear_start(&ofile_effects_chain.effects[1][0]);
}
}
}
@@ -1437,14 +1439,14 @@
return user_abort? SOX_EOF : SOX_SUCCESS;
}
-static void sox_stop_effects(void)
+static void sox_stop_effects(sox_effects_chain_t * chain)
{
sox_size_t e, clips;
- for (e = 0; e < sox_neffects; ++e)
- if ((clips = sox_stop_effect(e)) != 0)
+ for (e = 0; e < chain->length; ++e)
+ if ((clips = sox_stop_effect(chain, e)) != 0)
sox_warn("%s clipped %u samples; decrease volume?",
- sox_effects[e][0].handler.name, clips);
+ chain->effects[e][0].handler.name, clips);
}
/*
@@ -1517,7 +1519,8 @@
open_output_file(olen);
- add_effects();
+ ofile_effects_chain.global_info = sox_effects_globals;
+ add_effects(&ofile_effects_chain);
optimize_trim();
@@ -1525,10 +1528,10 @@
/* FIXME: For SIGTERM at least we really should guarantee to stop quickly */
signal(SIGTERM, sigint); /* Stop gracefully even in extremis */
- flowstatus = sox_flow_effects(update_status);
+ flowstatus = sox_flow_effects(&ofile_effects_chain, update_status);
- sox_stop_effects();
- sox_delete_effects();
+ sox_stop_effects(&ofile_effects_chain);
+ sox_delete_effects(&ofile_effects_chain);
return flowstatus;
}
@@ -1538,7 +1541,7 @@
sox_size_t clips = 0;
for (i = 0; i < file_count; ++i)
clips += files[i]->ft->clips + files[i]->volume_clips;
- return clips + mixing_clips + sox_effects_clips();
+ return clips + mixing_clips + sox_effects_clips(&ofile_effects_chain);
}
static char const * sigfigs3(sox_size_t number)
--- a/src/sox.h
+++ b/src/sox.h
@@ -429,15 +429,17 @@
void sox_create_effect(sox_effect_t * effp, sox_effect_handler_t const *e);
/* Effects chain */
-#define SOX_MAX_EFFECTS 20
-extern sox_effect_t * sox_effects[SOX_MAX_EFFECTS];
-extern unsigned sox_neffects;
+
int sox_effect_set_imin(sox_effect_t * effp, sox_size_t imin);
-int sox_add_effect(sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t const * out);
-int sox_flow_effects(int (* callback)(sox_bool all_done));
-sox_size_t sox_effects_clips(void);
-sox_size_t sox_stop_effect(sox_size_t e);
-void sox_delete_effects(void);
+
+struct sox_effects_chain;
+typedef struct sox_effects_chain sox_effects_chain_t;
+
+int sox_add_effect(sox_effects_chain_t *, sox_effect_t * effp, sox_signalinfo_t * in, sox_signalinfo_t const * out);
+int sox_flow_effects(sox_effects_chain_t *, int (* callback)(sox_bool all_done));
+sox_size_t sox_effects_clips(sox_effects_chain_t *);
+sox_size_t sox_stop_effect(sox_effects_chain_t *, sox_size_t e);
+void sox_delete_effects(sox_effects_chain_t *);
char const * sox_parsesamples(sox_rate_t rate, const char *str, sox_size_t *samples, int def);
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -352,4 +352,11 @@
} \
}
+struct sox_effects_chain {
+#define SOX_MAX_EFFECTS 20
+ sox_effect_t * effects[SOX_MAX_EFFECTS];
+ unsigned length;
+ sox_ssample_t **ibufc, **obufc; /* Channel interleave buffers */
+ sox_effects_globals_t global_info;
+};
#endif