shithub: sox

Download patch

ref: f8dd6e1c6e4b2585ec7735acb26b126548b90319
parent: c4a08032074cdf097cfb13683efb4cfad74b96c6
author: cbagwell <cbagwell>
date: Thu Sep 16 21:11:16 EDT 2004

fix for lost last buffer when some effects reported early ST_EOF.

--- a/Changelog
+++ b/Changelog
@@ -43,8 +43,9 @@
     value was treated as -MAX instead of -MAX-1.
   o Modifed sox so its OK for effects to not process any
     input or output bytes as long as they return ST_EOF.
-  o Bugfix to trim effect were bytes were left off the end
-    of the file when output length was specified.
+  o When effects output data and reported ST_EOF at the
+    same time, that buffer was discarded as well as
+    data from any chained effect.
 
 sox-12.17.5
 -----------
--- a/src/sox.c
+++ b/src/sox.c
@@ -122,10 +122,12 @@
 #define MAX_USER_EFF 14
 
 /*
- * In efftab's, location 0 is always the input stream.
+ * efftab[0] is a dummy entry used only as an input buffer for
+ * reading input data into.
  *
  * If one was to support effects for quad-channel files, there would
- * need to be an effect tabel for each channel.
+ * need to be an effect table for each channel to handle effects
+ * that done st ST_EFF_MCHAN.
  */
 
 static struct st_effect efftab[MAX_EFF]; /* left/mono channel effects */
@@ -665,9 +667,10 @@
      */
     do {
 #ifndef SOXMIX
-        efftab[0].olen = (*file_desc[current_input]->h->read)(file_desc[current_input],
-                                                              efftab[0].obuf, 
-                                                              (st_ssize_t)ST_BUFSIZ);
+        efftab[0].olen = 
+            (*file_desc[current_input]->h->read)(file_desc[current_input],
+                                                 efftab[0].obuf, 
+                                                 (st_ssize_t)ST_BUFSIZ);
         /* FIXME: libst needs the feof() and ferror() concepts
          * to see if ST_EOF means a real failure.  Until then we
          * must treat ST_EOF as just hiting the end of the buffer.
@@ -781,11 +784,11 @@
         flowstatus = flow_effect_out();
 
         /* Negative flowstatus says no more output will ever be generated. */
-        if (flowstatus < 0 || 
+        if (flowstatus == ST_EOF || 
             (writing && file_desc[file_count-1]->st_errno))
             break;
 
-    } while (1); /* break; efftab[0].olen == 0 */
+    } while (1); 
 
 #ifdef SOXMIX
     /* Free input buffers now that they are not used */
@@ -868,15 +871,22 @@
 static int flow_effect_out(void)
 {
     int e, havedata, flowstatus = 0;
+    int input_eff = 0;
 
     do {
       /* run entire chain BACKWARDS: pull, don't push.*/
       /* this is because buffering system isn't a nice queueing system */
-      for(e = neffects - 1; e > 0; e--)
+      for(e = neffects - 1; e > input_eff; e--)
       {
-          flowstatus = flow_effect(e);
-          if (flowstatus)
-              break;
+          /* flow_effect returns ST_EOF when it will not process
+           * any more samples.  This is used to bail out early.
+           * Since we are "pulling" data, it is OK that we are not
+           * calling any more previous effects since their output
+           * would not be looked at anyways.
+           */
+          flowstatus  = flow_effect(e);
+          if (flowstatus == ST_EOF)
+              input_eff = e;
       }
 
       /* If outputing and output data was generated then write it */
@@ -904,16 +914,12 @@
           }
       }
 
-      /* If any effect will never again produce data, give up.  This
-       * works because of the pull status: the effect won't be able to
-       * shut us down until all downstream buffers have been emptied.
-       */
-      if (flowstatus < 0)
-          break;
-
       /* if stuff still in pipeline, set up to flow effects again */
+      /* When all effects have reported ST_EOF then this check will
+       * show no more data.
+       */
       havedata = 0;
-      for(e = 0; e < neffects - 1; e++)
+      for(e = neffects - 2; e > input_eff; e--)
           if (efftab[e].odone < efftab[e].olen) {
               havedata = 1;
               break;
@@ -920,7 +926,14 @@
           }
     } while (havedata);
 
-    return flowstatus;
+    /* If input_eff isn't pointing at fake first entry then there
+     * is no need to read any more data from disk.  Return this
+     * fact to caller.
+     */
+    if (input_eff > 0)
+        return ST_EOF;
+
+    return ST_SUCCESS;
 }
 
 static int flow_effect(e)
@@ -940,7 +953,6 @@
          */
         idone = efftab[e-1].olen - efftab[e-1].odone;
         odone = ST_BUFSIZ;
-        /* FIXME: Should look at return code and abort on ST_EOF */
         effstatus = (* efftab[e].h->flow)(&efftab[e],
                                           &efftab[e-1].obuf[efftab[e-1].odone],
                                           efftab[e].obuf, &idone, &odone);
@@ -964,7 +976,6 @@
         /* left */
         idonel = (idone + 1)/2;         /* odd-length logic */
         odonel = odone/2;
-        /* FIXME: Should look at return code and abort on ST_EOF */
         effstatus = (* efftab[e].h->flow)(&efftab[e],
                                           ibufl, obufl, &idonel, &odonel);
 
@@ -971,7 +982,7 @@
         /* right */
         idoner = idone/2;               /* odd-length logic */
         odoner = odone/2;
-        /* FIXME: Should look at return code and abort on ST_EOF */
+        /* FIXME: effstatus of previous operation is lost. */
         effstatus = (* efftabR[e].h->flow)(&efftabR[e],
                                            ibufr, obufr, &idoner, &odoner);
 
@@ -989,10 +1000,10 @@
         done = idonel + idoner + odonel + odoner;
     }
     if (effstatus == ST_EOF)
-        return -1;
+        return ST_EOF;
     if (done == 0)
         st_fail("Effect took & gave no samples!");
-    return 1;
+    return ST_SUCCESS;
 }
 
 static int drain_effect(e)
@@ -1003,6 +1014,7 @@
 
     if (! efftabR[e].name) {
         efftab[e].olen = ST_BUFSIZ;
+        /* FIXME: Should look at return code and abort on ST_EOF */
         (* efftab[e].h->drain)(&efftab[e],efftab[e].obuf,
                                &efftab[e].olen);
     }
@@ -1011,6 +1023,7 @@
 
         /* left */
         olenl = olen/2;
+        /* FIXME: Should look at return code and abort on ST_EOF */
         (* efftab[e].h->drain)(&efftab[e], obufl, &olenl);
 
         /* right */