shithub: sox

Download patch

ref: e38ffc2c9716d8764aef7e88ad40d0ebbb572ff2
parent: 083d40f17c381101a75fe3dd80ed27e0b378a09a
author: cbagwell <cbagwell>
date: Sat Feb 19 20:43:31 EST 2011

Support an absolute end position for trim effect instead of only
an offset from trim begin.

--- a/ChangeLog
+++ b/ChangeLog
@@ -54,6 +54,8 @@
   o Enable LADSPA effects on all platforms without any external
     dependencies.  Mainly useful for Linux, Windows and OS X which have
     binaries readily available. (cbagwell)
+  o Support specifying an absolute end location for trim effect instead
+    only an offset from trim begin location. (Ulrich Klauer)
 
 Other new features:
 
--- a/sox.1
+++ b/sox.1
@@ -3925,7 +3925,7 @@
 .I depth
 (default 40).
 .TP
-\fBtrim \fIstart\fR [\fIlength\fR]
+\fBtrim \fIstart\fR [\fIlength\fR\^|\^\fB=\fIend\fR]
 Trim can trim off unwanted audio from the beginning and end of the
 audio.  Audio is not sent to the output stream until
 the \fIstart\fR location is reached.
@@ -3932,16 +3932,17 @@
 .SP
 The optional \fIlength\fR parameter gives the length of audio to output
 after the \fIstart\fR sample and is thus used to trim off the end of the
-audio.  Using a value of 0 for the \fIstart\fR parameter will allow
-trimming off the end only.
+audio.  Alternatively, an absolute end location can be given by
+preceding it with an equals sign.  Using a value of 0 for the \fIstart\fR
+parameter will allow trimming off the end only.
 .SP
-Both options can be specified using either an amount of time or an
+Both parameters can be specified using either an amount of time or an
 exact count of samples.  The format for specifying lengths in time is
 hh:mm:ss.frac.  A start value of 1:30\*d5 will not start until 1 minute,
 thirty and \(12 seconds into the audio.  The format for specifying
 sample counts is the number of samples with the letter `s' appended to
-it.  A value of 8000s will wait until 8000 samples are read before
-starting to process audio.
+it.  A value of 8000s for the \fIstart\fR parameter will wait until
+8000 samples are read before starting to process audio.
 .TP
 \fBvad \fR[\fIoptions\fR]
 Voice Activity Detector.  Attempts to trim silence and quiet
--- a/src/trim.c
+++ b/src/trim.c
@@ -12,7 +12,8 @@
 typedef struct {
     /* options here */
     char *start_str;
-    char *length_str;
+    char *end_str;
+    sox_bool end_is_absolute;
 
     /* options converted to values */
     size_t start;
@@ -28,6 +29,7 @@
  */
 static int sox_trim_getopts(sox_effect_t * effp, int argc, char **argv)
 {
+    char *end;
     priv_t * trim = (priv_t *) effp->priv;
   --argc, ++argv;
 
@@ -36,10 +38,15 @@
      */
     switch (argc) {
         case 2:
-            trim->length_str = lsx_malloc(strlen(argv[1])+1);
-            strcpy(trim->length_str,argv[1]);
+            end = argv[1];
+            if (*end == '=') {
+                trim->end_is_absolute = sox_true;
+                end++;
+            } else trim->end_is_absolute = sox_false;
+            trim->end_str = lsx_malloc(strlen(end)+1);
+            strcpy(trim->end_str, end);
             /* Do a dummy parse to see if it will fail */
-            if (lsx_parsesamples(0., trim->length_str, &trim->length, 't') == NULL)
+            if (lsx_parsesamples(0., trim->end_str, &trim->length, 't') == NULL)
               return lsx_usage(effp);
         case 1:
             trim->start_str = lsx_malloc(strlen(argv[0])+1);
@@ -65,19 +72,29 @@
     if (lsx_parsesamples(effp->in_signal.rate, trim->start_str,
                         &trim->start, 't') == NULL)
       return lsx_usage(effp);
-    /* Account for # of channels */
-    trim->start *= effp->in_signal.channels;
 
-    if (trim->length_str)
+    if (trim->end_str)
     {
-        if (lsx_parsesamples(effp->in_signal.rate, trim->length_str,
+        if (lsx_parsesamples(effp->in_signal.rate, trim->end_str,
                     &trim->length, 't') == NULL)
           return lsx_usage(effp);
+        if (trim->end_is_absolute) {
+            if (trim->length < trim->start) {
+                lsx_warn("end earlier than start");
+                trim->length = 0;
+                  /* with trim->end_str != NULL, this really means zero */
+            } else
+                trim->length -= trim->start;
+        }
     }
     else
         trim->length = 0;
+          /* with trim->end_str == NULL, this means indefinite length */
 
+    lsx_debug("start at %lus, length %lu", trim->start, trim->length);
+
     /* Account for # of channels */
+    trim->start *= effp->in_signal.channels;
     trim->length *= effp->in_signal.channels;
 
     trim->index = 0;
@@ -130,7 +147,7 @@
     } /* !trimmed */
 
     if (trim->trimmed || start_trim) {
-        if (trim->length_str && ((trim->trimmed+done) >= trim->length)) {
+        if (trim->end_str && ((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.
              */
@@ -153,7 +170,7 @@
     priv_t * trim = (priv_t *) effp->priv;
 
     free(trim->start_str);
-    free(trim->length_str);
+    free(trim->end_str);
 
     return (SOX_SUCCESS);
 }
@@ -173,7 +190,7 @@
 const sox_effect_handler_t *lsx_trim_effect_fn(void)
 {
   static sox_effect_handler_t handler = {
-    "trim", "start [length]", SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_MODIFY,
+    "trim", "start [length|=end]", SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_MODIFY,
     sox_trim_getopts, sox_trim_start, sox_trim_flow,
     NULL, NULL, lsx_kill, sizeof(priv_t)
   };