shithub: sox

Download patch

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