shithub: sox

Download patch

ref: c4a08032074cdf097cfb13683efb4cfad74b96c6
parent: d3a8f86ef1aaf2861afb292ba546be24afdf9cfa
author: cbagwell <cbagwell>
date: Thu Sep 16 19:08:58 EDT 2004

Bugfixes to trim effect.  Allows crossfade script to work without pops.

--- a/Changelog
+++ b/Changelog
@@ -41,6 +41,10 @@
     to not result in the original file.
   o Fixed a possible overflow in lots of effects were MIN
     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.
 
 sox-12.17.5
 -----------
--- a/scripts/crossfade_cat.sh
+++ b/scripts/crossfade_cat.sh
@@ -45,21 +45,21 @@
 
 fade_first_opts=
 if [ "$fade_first" == "yes" ]; then
-    fade_first_opts="fade h 0 0:0:$fade_length"
+    fade_first_opts="fade t 0 0:0:$fade_length"
 fi
 
 fade_second_opts=
 if [ "$fade_second" == "yes" ]; then
-    fade_second_opts="fade h 0:0:$fade_length"
+    fade_second_opts="fade t 0:0:$fade_length"
 fi
 
 echo "crossfade and concatenate files"
 echo
 echo  "Finding length of $first_file..."
-first_length=`$SOX "$first_file" 2>&1 -e stat | grep Length | cut -d : -f 2 | cut -d . -f 1 | cut -f 1`
-echo "Length is $first_length"
+first_length=`$SOX "$first_file" 2>&1 -e stat | grep Length | cut -d : -f 2 | cut -f 1`
+echo "Length is $first_length seconds"
 
-trim_length=`expr $first_length - $fade_length`
+trim_length=`echo "$first_length - $fade_length" | bc`
 
 # Get crossfade section from first file and optionally do the fade out
 echo "Obtaining $fade_length seconds of fade out portion from $first_file..."
@@ -79,7 +79,7 @@
 
 echo -e "Removing temporary files...\n" 
 rm fadeout.wav fadein.wav crossfade.wav song1.wav song2.wav
-mins=`expr $trim_length / 60`
-secs=`expr $trim_length % 60`
+mins=`echo "$trim_length / 60" | bc`
+secs=`echo "$trim_length % 60" | bc`
 echo "The crossfade in mix.wav occurs at around $mins mins $secs secs"
 
--- a/src/fade.c
+++ b/src/fade.c
@@ -230,8 +230,9 @@
         t_ibuf = (fade->samplesdone < 0 ? 0 : *ibuf);
 
         if ((fade->samplesdone >= fade->in_start) &&
-            (fade->out_stop == 0 || fade->samplesdone < fade->out_stop))
+            (!fade->do_out || fade->samplesdone < fade->out_stop))
         { /* something to generate output */
+
             if (fade->samplesdone < fade->in_stop)
             { /* fade-in phase, increase gain */
                 *obuf = t_ibuf *
@@ -239,14 +240,11 @@
                               fade->in_stop - fade->in_start,
                               fade->in_fadetype);
             } /* endif fade-in */
-
-            if (fade->samplesdone >= fade->in_stop &&
-                (!fade->do_out || fade->samplesdone < fade->out_start))
+            else if (!fade->do_out || fade->samplesdone < fade->out_start)
             { /* steady gain phase */
                 *obuf = t_ibuf;
             } /* endif  steady phase */
-
-            if (fade->do_out && fade->samplesdone >= fade->out_start)
+            else
             { /* fade-out phase, decrease gain */
                 *obuf = t_ibuf *
                     fade_gain(fade->out_stop - fade->samplesdone,
@@ -261,6 +259,9 @@
             t_output = 0;
         } /* endif something to output */
 
+        /* samplesdone < 0 means we are inventing samples right now
+         * and so not consuming (happens when in_start < 0).
+         */
         if (fade->samplesdone >= 0 )
         { /* Something to input  */
             *isamp += 1;
--- a/src/sox.c
+++ b/src/sox.c
@@ -988,10 +988,10 @@
         efftab[e].olen = odonel + odoner;
         done = idonel + idoner + odonel + odoner;
     }
-    if (done == 0)
-        st_fail("Effect took & gave no samples!");
     if (effstatus == ST_EOF)
         return -1;
+    if (done == 0)
+        st_fail("Effect took & gave no samples!");
     return 1;
 }
 
--- a/src/trim.c
+++ b/src/trim.c
@@ -45,41 +45,41 @@
      * time related strings.
      */
     switch (n) {
-	case 2:
-	    trim->length_str = malloc(strlen(argv[1])+1);
-	    if (!trim->length_str)
-	    {
-		st_fail("Could not allocate memory");
-		return(ST_EOF);
-	    }
-	    strcpy(trim->length_str,argv[1]);
-	    /* Do a dummy parse to see if it will fail */
-	    if (st_parsesamples(0, trim->length_str,
-			        &trim->length, 't') != ST_SUCCESS)
-	    {
-		st_fail(TRIM_USAGE);
-		return(ST_EOF);
-	    }
-	case 1:
-	    trim->start_str = malloc(strlen(argv[0])+1);
-	    if (!trim->start_str)
-	    {
-		st_fail("Could not allocate memory");
-		return(ST_EOF);
-	    }
-	    strcpy(trim->start_str,argv[0]);
-	    /* Do a dummy parse to see if it will fail */
-	    if (st_parsesamples(0, trim->start_str,
-			        &trim->start, 't') != ST_SUCCESS)
-	    {
-		st_fail(TRIM_USAGE);
-		return(ST_EOF);
-	    }
-	    break;
-	default:
-	    st_fail(TRIM_USAGE);
-	    return ST_EOF;
-	    break;
+        case 2:
+            trim->length_str = malloc(strlen(argv[1])+1);
+            if (!trim->length_str)
+            {
+                st_fail("Could not allocate memory");
+                return(ST_EOF);
+            }
+            strcpy(trim->length_str,argv[1]);
+            /* Do a dummy parse to see if it will fail */
+            if (st_parsesamples(0, trim->length_str,
+                                &trim->length, 't') != ST_SUCCESS)
+            {
+                st_fail(TRIM_USAGE);
+                return(ST_EOF);
+            }
+        case 1:
+            trim->start_str = malloc(strlen(argv[0])+1);
+            if (!trim->start_str)
+            {
+                st_fail("Could not allocate memory");
+                return(ST_EOF);
+            }
+            strcpy(trim->start_str,argv[0]);
+            /* Do a dummy parse to see if it will fail */
+            if (st_parsesamples(0, trim->start_str,
+                                &trim->start, 't') != ST_SUCCESS)
+            {
+                st_fail(TRIM_USAGE);
+                return(ST_EOF);
+            }
+            break;
+        default:
+            st_fail(TRIM_USAGE);
+            return ST_EOF;
+            break;
 
     }
     return (ST_SUCCESS);
@@ -93,24 +93,25 @@
     trim_t trim = (trim_t) effp->priv;
 
     if (st_parsesamples(effp->ininfo.rate, trim->start_str,
-		        &trim->start, 't') != ST_SUCCESS)
+                        &trim->start, 't') != ST_SUCCESS)
     {
-	st_fail(TRIM_USAGE);
-	return(ST_EOF);
+        st_fail(TRIM_USAGE);
+        return(ST_EOF);
     }
     /* Account for # of channels */
     trim->start *= effp->ininfo.channels;
+
     if (trim->length_str)
     {
-	if (st_parsesamples(effp->ininfo.rate, trim->length_str,
-		    &trim->length, 't') != ST_SUCCESS)
-	{
-	    st_fail(TRIM_USAGE);
-	    return(ST_EOF);
-	}
+        if (st_parsesamples(effp->ininfo.rate, trim->length_str,
+                    &trim->length, 't') != ST_SUCCESS)
+        {
+            st_fail(TRIM_USAGE);
+            return(ST_EOF);
+        }
     }
     else
-	trim->length = 0;
+        trim->length = 0;
 
     /* Account for # of channels */
     trim->length *= effp->ininfo.channels;
@@ -144,35 +145,35 @@
      * If so then we can skip trimming from the front side.
      */
     if (!trim->trimmed) {
-	if ((trim->index+done) <= trim->start) {
-	    /* If we haven't read more then "start" samples, return that
-	     * we've read all this buffer without outputing anything
-	     */
-	    *osamp = 0;
-	    *isamp = done;
-	    trim->index += done;
-	    return (ST_SUCCESS);
-	} else {
-	    start_trim = 1;
-	    /* We've read at least "start" samples.  Now find
-	     * out where our target data begins and subtract that
-	     * from the total to be copied this round.
-	     */
-	    offset = trim->start - trim->index;
-	    done -= offset;
-	}
+        if ((trim->index+done) <= trim->start) {
+            /* If we haven't read more then "start" samples, return that
+             * we've read all this buffer without outputing anything
+             */
+            *osamp = 0;
+            *isamp = done;
+            trim->index += done;
+            return (ST_SUCCESS);
+        } else {
+            start_trim = 1;
+            /* We've read at least "start" samples.  Now find
+             * out where our target data begins and subtract that
+             * from the total to be copied this round.
+             */
+            offset = trim->start - trim->index;
+            done -= offset;
+        }
     } /* !trimmed */
 
     if (trim->trimmed || start_trim) {
-	if (trim->length && ((trim->trimmed+done) >= trim->length)) {
-	    /* Since we know the end is in this block, we set done
-	     * to the desired length less the amount already read.
-	     */
-	    done = trim->length - trim->trimmed;
-	    finished = 1;
-	}
+        if (trim->length && ((trim->trimmed+done) >= trim->length)) {
+            /* Since we know the end is in this block, we set done
+             * to the desired length less the amount already read.
+             */
+            done = trim->length - trim->trimmed;
+            finished = 1;
+        }
 
-	trim->trimmed += done;
+        trim->trimmed += done;
     }
 
     memcpy(obuf, ibuf+offset, done * sizeof(st_sample_t));
@@ -181,10 +182,13 @@
     *isamp = offset + done;
     trim->index += done;
 
-    if (finished)
-	return (ST_EOF);
+    /* return ST_EOF when nothing consumed and we detect
+     * we are finished.
+     */
+    if (finished && !done)
+        return (ST_EOF);
     else
-	return (ST_SUCCESS);
+        return (ST_SUCCESS);
 }
 
 /*
@@ -196,9 +200,9 @@
     trim_t trim = (trim_t) effp->priv;
 
     if (trim->start_str)
-	free(trim->start_str);
+        free(trim->start_str);
     if (trim->length_str)
-	free(trim->length_str);
+        free(trim->length_str);
 
     return (ST_SUCCESS);
 }