shithub: sox

Download patch

ref: b4ee498064d4c43799d835f5a0ada856bf3f6838
parent: a447efea202f06165d60800d33abc38e560f7240
author: Ulrich Klauer <ulrich@chirlu.de>
date: Mon Oct 15 22:39:27 EDT 2012

trim: use lsx_parseposition

Use the new lsx_parseposition function for the trim effect, removing much
of the dedicated parsing as it is now handled by lsx_parseposition. Update
documentation.

--- a/sox.1
+++ b/sox.1
@@ -3969,20 +3969,12 @@
 .I depth
 (default 40).
 .TP
-\fBtrim\fR {[\fB=\fR\^|\^\fB\-\fR]\fIposition\fR}
+\fBtrim\fR {\fIposition(+)\fR}
 Cuts portions out of the audio.  Any number of \fIposition\fRs may be
 given; audio is not sent to the output until the first \fIposition\fR
 is reached.  The effect then alternates between copying and discarding
-audio at each \fIposition\fR.
-.SP
-If a \fIposition\fR is preceded by an equals or minus sign, it is
-interpreted relative to the beginning or the end of the audio,
-respectively.  (The audio length must be known for end-relative
-locations to work.)  Otherwise, it is considered an offset from the
-last \fIposition\fR, or from the start of audio for the first
-parameter.  Using a value of 0 for the first \fIposition\fR
+audio at each \fIposition\fR.  Using a value of 0 for the first \fIposition\fR
 parameter allows copying from the beginning of the audio.
-Any time specification may be used for \fIposition\fR.
 .SP
 For example,
 .EX
@@ -3992,7 +3984,11 @@
 .EX
    play infile trim 12:34 =15:00 -2:00
 .EE
-will play from 12 minutes 34 seconds into the audio up to 15 minutes into
+and
+.EX
+   play infile trim 12:34 2:26 -2:00
+.EE
+will both play from 12 minutes 34 seconds into the audio up to 15 minutes into
 the audio (i.e. 2 minutes and 26 seconds long), then resume playing two
 minutes before the end of audio.
 .TP
--- a/src/trim.c
+++ b/src/trim.c
@@ -28,15 +28,11 @@
   struct {
     uint64_t sample; /* NB: wide samples */
     char *argstr;
-    enum {
-      a_start, a_latest, a_end
-    } anchor;
   } *pos;
   /* state */
   unsigned int current_pos;
   uint64_t samples_read; /* NB: wide samples */
   sox_bool copying;
-  sox_bool uses_end;
 } priv_t;
 
 static int parse(sox_effect_t *effp, int argc, char **argv)
@@ -46,24 +42,15 @@
   --argc, ++argv;
   p->num_pos = argc;
   lsx_Calloc(p->pos, p->num_pos);
-  p->uses_end = sox_false;
   for (i = 0; i < p->num_pos; i++) {
-    uint64_t dummy;
     const char *arg = argv[i];
-    if (arg[0] == '=') {
-      p->pos[i].anchor = a_start;
-      arg++;
-    } else if (arg[0] == '-') {
-      p->pos[i].anchor = a_end;
-      p->uses_end = sox_true;
-      arg++;
-    } else
-      p->pos[i].anchor = a_latest;
     p->pos[i].argstr = lsx_strdup(arg);
     /* dummy parse to check for syntax errors */
-    arg = lsx_parsesamples(0., arg, &dummy, 't');
-    if (!arg || *arg)
+    arg = lsx_parseposition(0., arg, NULL, (uint64_t)0, (uint64_t)0, '+');
+    if (!arg || *arg) {
+      lsx_fail("Error parsing position %u", i+1);
       return lsx_usage(effp);
+    }
   }
   return SOX_SUCCESS;
 }
@@ -80,28 +67,13 @@
   p->copying = sox_false;
 
   /* calculate absolute positions */
-  if (in_length == SOX_UNKNOWN_LEN && p->uses_end) {
-    lsx_fail("Can't use positions relative to end: audio length is unknown.");
-    return SOX_EOF;
-  }
   for (i = 0; i < p->num_pos; i++) {
-    uint64_t s, res = 0;
-    if (!lsx_parsesamples(effp->in_signal.rate, p->pos[i].argstr, &s, 't'))
-      return lsx_usage(effp);
-    switch (p->pos[i].anchor) {
-      case a_start: res = s; break;
-      case a_latest: res = last_seen + s; break;
-      case a_end:
-        if (s <= in_length)
-          res = in_length - s;
-        else {
-          lsx_fail("Position %u is before start of audio.", i+1);
-          return SOX_EOF;
-        }
-        break;
+    if (!lsx_parseposition(effp->in_signal.rate, p->pos[i].argstr, &p->pos[i].sample, last_seen, in_length, '+')) {
+      lsx_fail("Position %u is relative to end of audio, but audio length is unknown", i+1);
+      return SOX_EOF;
     }
-    last_seen = p->pos[i].sample = res;
-    lsx_debug_more("position %u at %" PRIu64, i+1, res);
+    last_seen = p->pos[i].sample;
+    lsx_debug_more("position %u at %" PRIu64, i+1, last_seen);
   }
 
   /* sanity checks */
@@ -119,6 +91,13 @@
       lsx_warn("%s position is after expected end of audio.",
           p->pos[0].sample > in_length ? "Start" : "End");
 
+  /* avoid unnecessary work */
+  if (in_length == SOX_UNKNOWN_LEN)
+    while (p->num_pos && p->pos[p->num_pos-1].sample == SOX_UNKNOWN_LEN) {
+      lsx_debug_more("removing `-0' position");
+      p->num_pos--;
+      free(p->pos[p->num_pos].argstr);
+    }
   if (p->num_pos == 1 && !p->pos[0].sample)
     return SOX_EFF_NULL;
 
@@ -207,7 +186,7 @@
 sox_effect_handler_t const *lsx_trim_effect_fn(void)
 {
   static sox_effect_handler_t handler = {
-    "trim", "{[=|-]position}",
+    "trim", "{position}",
     SOX_EFF_MCHAN | SOX_EFF_LENGTH | SOX_EFF_MODIFY,
     parse, start, flow, drain, NULL, lsx_kill,
     sizeof(priv_t)