[prev in list] [next in list] [prev in thread] [next in thread] 

List:       sox-commits
Subject:    [SoX-commits] [git] 86791c4beb Merge branch 'positions'
From:       "Ulrich Klauer" <uklauer () users ! sourceforge ! net>
Date:       2013-02-01 1:30:52
Message-ID: E1U15T3-0001DG-Vu () sfs-ml-4 ! v29 ! ch3 ! sourceforge ! com
[Download RAW message or body]

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "sox".

The branch, master has been updated
       via  86791c4beb0235121173d9ced1b166d03eeda31b (commit)
       via  a586ad952b11c3717d419ce9817391d21e10e045 (commit)
       via  7672dd349f386c937b4858a074fa830471dbf7ee (commit)
       via  f52cfb29110cd62e70496b2a7b91107f2e988637 (commit)
       via  2469faa09760cccf9ac360872613fca7a42836aa (commit)
       via  851a8d152c004310afd5bdf0a300c1c74e979855 (commit)
       via  d6e47684f70c9ca1ffb9cd48c82f9513ef88eddd (commit)
       via  b4ee498064d4c43799d835f5a0ada856bf3f6838 (commit)
       via  a447efea202f06165d60800d33abc38e560f7240 (commit)
       via  b547a29888c8b6452b3f14c24bb4dda01ade6cd3 (commit)
      from  fbbc16d6de5a374253ea07b751c2e0d1c09befd5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 86791c4beb0235121173d9ced1b166d03eeda31b
Merge: fbbc16d a586ad9
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Fri Feb 1 02:23:42 2013 +0100

    Merge branch 'positions'
    
    Extended syntax for specifying audio positions to several effects
    (bend, delay, fade, pad, spectrogram, splice; trim had it before, but
    now uses the shared lsx_parseposition function).

diff --cc ChangeLog
index ac040ce,9917855..cf5c3b1
--- a/ChangeLog
+++ b/ChangeLog
@@@ -32,13 -32,6 +32,15 @@@ Effects
    o Allow sending spectrograms to stdout. (Ulrich Klauer)
    o Allow mixing time and sample-count arguments for the delay
      effect, and for spectrogram -S and -d. (Ulrich Klauer)
 +  o Support multi-channel LADSPA plugins. (Eric Wong)
 +  o Support infinite repetition with repeat. (Ulrich Klauer)
 +  o Improved pink noise frequency response in synth. (robs)
++  o Extended syntax for specifying audio positions to several
++    effects. (Ulrich Klauer)
 +
 +Other new features:
 +
 +  o New -p option for soxi to display sample precision. (Ulrich Klauer)
  
  Internal improvements:
  

commit a586ad952b11c3717d419ce9817391d21e10e045
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Fri Feb 1 01:46:02 2013 +0100

    Apply new timespec syntax to documentation example
    
    Update the "acpo" example script shown in the man page to take
    advantage of the syntax features that were added recently (chained
    time specifications, positions). All calculations that previously had
    to be done in the shell can now be done in SoX directly, and values
    like "1:03" instead of only sample numbers are allowed as parameters
    to the script.

diff --git a/sox.1 b/sox.1
index 7fa4b6f..ced6d37 100644
--- a/sox.1
+++ b/sox.1
@@ -3445,17 +3445,15 @@ invocation.  For example:
 #!/bin/sh
 # Audio Copy and Paste Over
 # acpo infile copy-start copy-stop paste-over-start outfile
-# All times measured in samples.
-rate=\`soxi \-r "$1"\`
-e=\`expr $rate '*' 5 / 1000\`  # Using default excess
+# No chained time specifications allowed for the parameters
+# (i.e. such that contain +/\-).
+e=0.005                      # Using default excess
 l=$e                         # and leeway.
-sox "$1" piece.wav trim \`expr $2 \- $e \- $l\`s \\
-   \`expr $3 \- $2 + $e + $l + $e\`s
-sox "$1" part1.wav trim 0 \`expr $4 + $e\`s
-sox "$1" part2.wav trim \`expr $4 + $3 \- $2 \- $e \- $l\`s
-sox part1.wav piece.wav part2.wav "$5" splice \\
-   \`expr $4 + $e\`s \\
-   \`expr $4 + $e + $3 \- $2 + $e + $l + $e\`s
+sox "$1" piece.wav trim $2\-$e\-$l =$3+$e
+sox "$1" part1.wav trim 0 $4+$e
+sox "$1" part2.wav trim $4+$3\-$2\-$e\-$l
+sox part1.wav piece.wav part2.wav "$5" \\
+   splice $4+$e +$3\-$2+$e+$l+$e
 .EE
 In the above Bourne shell script,
 two splices are used to `copy and paste' audio.

commit 7672dd349f386c937b4858a074fa830471dbf7ee
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Fri Feb 1 01:19:23 2013 +0100

    pad: use lsx_parseposition
    
    Use the new lsx_parseposition function for the pad effect and update
    the documentation accordingly.

diff --git a/sox.1 b/sox.1
index 7eb973b..7fa4b6f 100644
--- a/sox.1
+++ b/sox.1
@@ -2519,7 +2519,7 @@ Non linear distortion.
 The \fIcolour\fR parameter controls the amount of even harmonic content
 in the over-driven output.
 .TP
-\fBpad\fR { \fIlength\fR[\fB@\fIposition\fR] }
+\fBpad\fR { \fIlength\fR[\fB@\fIposition(=)\fR] }
 Pad the audio with silence, at the beginning, the end, or any
 specified points through the audio.
 .I length
diff --git a/src/pad.c b/src/pad.c
index 21caebb..c04086f 100644
--- a/src/pad.c
+++ b/src/pad.c
@@ -35,6 +35,10 @@ static int parse(sox_effect_t * effp, char * * argv, sox_rate_t \
rate)  priv_t * p = (priv_t *)effp->priv;
   char const * next;
   unsigned i;
+  uint64_t last_seen = 0;
+  const uint64_t in_length = argv ? 0 :
+    (effp->in_signal.length != SOX_UNKNOWN_LEN ?
+     effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN);
 
   for (i = 0; i < p->npads; ++i) {
     if (argv) /* 1st parse only */
@@ -45,8 +49,12 @@ static int parse(sox_effect_t * effp, char * * argv, sox_rate_t \
rate)  p->pads[i].start = i? UINT64_MAX : 0;
     else {
       if (*next != '@') break;
-      next = lsx_parsesamples(rate, next+1, &p->pads[i].start, 't');
+      next = lsx_parseposition(rate, next+1, argv ? NULL : &p->pads[i].start,
+               last_seen, in_length, '=');
       if (next == NULL || *next != '\0') break;
+      last_seen = p->pads[i].start;
+      if (p->pads[i].start == SOX_UNKNOWN_LEN)
+        p->pads[i].start = UINT64_MAX; /* currently the same value, but ... */
     }
     if (!argv) {
       /* Do this check only during the second pass when the actual

commit f52cfb29110cd62e70496b2a7b91107f2e988637
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Fri Feb 1 00:05:58 2013 +0100

    splice: use lsx_parseposition
    
    Use the new lsx_parseposition function for the splice effect and
    update the documentation accordingly.

diff --git a/sox.1 b/sox.1
index 8eabd71..7eb973b 100644
--- a/sox.1
+++ b/sox.1
@@ -3345,7 +3345,7 @@ and
 .B tempo
 effects.
 .TP
-\fBsplice \fR [\fB\-h\fR\^|\^\fB\-t\fR\^|\^\fB\-q\fR] { \
\fIposition\fR[\fB,\fIexcess\fR[\fB,\fIleeway\fR]] } +\fBsplice \fR \
[\fB\-h\fR\^|\^\fB\-t\fR\^|\^\fB\-q\fR] { \
\fIposition(=)\fR[\fB,\fIexcess\fR[\fB,\fIleeway\fR]] }  Splice together audio \
sections.  This effect provides two things over  simple audio concatenation: a \
(usually short) cross-fade is applied at  the join, and a wave similarity comparison \
is made to help determine the @@ -3381,12 +3381,12 @@ same
 .IR excess
 (before the ideal joining point), plus an additional
 .I leeway
-(default 0\*d005 seconds).  SoX should then be invoked with the two
+(default 0\*d005 seconds).  Any time specification may be used for these
+parameters.  SoX should then be invoked with the two
 audio sections as input files and the
 .B splice
 effect given with the position at which to perform the splice\*mthis is
 length of the first audio section (including the excess).
-Any time specification may be used for these parameters.
 .SP
 The following diagram uses the tape analogy to illustrate the splice
 operation.  The effect simulates the diagonal cuts and joins the two pieces:
diff --git a/src/splice.c b/src/splice.c
index 3c60b8c..2e70fa0 100644
--- a/src/splice.c
+++ b/src/splice.c
@@ -119,6 +119,10 @@ static int parse(sox_effect_t * effp, char * * argv, sox_rate_t \
rate)  priv_t * p = (priv_t *)effp->priv;
   char const * next;
   size_t i, buffer_size;
+  uint64_t last_seen = 0;
+  const uint64_t in_length = argv ? 0 :
+    (effp->in_signal.length != SOX_UNKNOWN_LEN ?
+     effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN);
 
   p->max_buffer_size = 0;
   for (i = 0; i < p->nsplices; ++i) {
@@ -128,8 +132,10 @@ static int parse(sox_effect_t * effp, char * * argv, sox_rate_t \
rate)  p->splices[i].overlap = rate * 0.01 + .5;
     p->splices[i].search = p->fade_type == Cosine_4? 0 : p->splices[i].overlap;
 
-    next = lsx_parsesamples(rate, p->splices[i].str, &p->splices[i].start, 't');
+    next = lsx_parseposition(rate, p->splices[i].str,
+             argv ? NULL : &p->splices[i].start, last_seen, in_length, '=');
     if (next == NULL) break;
+    last_seen = p->splices[i].start;
 
     if (*next == ',') {
       next = lsx_parsesamples(rate, next + 1, &p->splices[i].overlap, 't');
@@ -145,11 +151,13 @@ static int parse(sox_effect_t * effp, char * * argv, sox_rate_t \
rate)  p->splices[i].overlap = max(p->splices[i].overlap + 4, 16);
     p->splices[i].overlap &= ~7; /* Make divisible by 8 for loop optimisation */
 
-    if (i > 0 && p->splices[i].start <= p->splices[i-1].start) break;
-    if (p->splices[i].start < p->splices[i].overlap) break;
-    p->splices[i].start -= p->splices[i].overlap;
-    buffer_size = 2 * p->splices[i].overlap + p->splices[i].search;
-    p->max_buffer_size = max(p->max_buffer_size, buffer_size);
+    if (!argv) {
+      if (i > 0 && p->splices[i].start <= p->splices[i-1].start) break;
+      if (p->splices[i].start < p->splices[i].overlap) break;
+      p->splices[i].start -= p->splices[i].overlap;
+      buffer_size = 2 * p->splices[i].overlap + p->splices[i].search;
+      p->max_buffer_size = max(p->max_buffer_size, buffer_size);
+    }
   }
   if (i < p->nsplices)
     return lsx_usage(effp);

commit 2469faa09760cccf9ac360872613fca7a42836aa
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Thu Jan 31 17:46:04 2013 +0100

    bend: use lsx_parseposition
    
    Use the new lsx_parseposition function for the bend effect and update
    the documentation accordingly.

diff --git a/sox.1 b/sox.1
index c7f2904..8eabd71 100644
--- a/sox.1
+++ b/sox.1
@@ -1627,16 +1627,13 @@ These effects support the \fB\-\-plot\fR global option.
 .SP
 See also \fBequalizer\fR for a peaking equalisation effect.
 .TP
-\fBbend\fR [\fB\-f \fIframe-rate\fR(25)] [\fB\-o \fIover-sample\fR(16)] { \
\fIdelay\fB,\fIcents\fB,\fIduration\fR } +\fBbend\fR [\fB\-f \fIframe-rate\fR(25)] \
[\fB\-o \fIover-sample\fR(16)] { \
\fIstart-position(+)\fB,\fIcents\fB,\fIend-position(+)\fR }  Changes pitch by \
                specified amounts at specified times.
-Each given triple: \fIdelay\fB,\fIcents\fB,\fIduration\fR specifies one bend.
-.I delay
-is the amount of time after the start of the audio stream, or the end of the \
                previous bend, at which to start bending the pitch;
-.I cents
-is the number of cents (100 cents = 1 semitone) by which to bend the pitch, and
-.I duration
-the length of time over which the pitch will be bent.  For \fIdelay\fR and
-\fIduration\fR, any time specification may be used.
+Each given triple: \fIstart-position\fB,\fIcents\fB,\fIend-position\fR
+specifies one bend.
+\fIcents\fR is the number of cents (100 cents = 1 semitone) by which to
+bend the pitch. The other values specify the points in time at which to start
+and end bending the pitch, respectively.
 .SP
 The pitch-bending algorithm utilises the Discrete Fourier Transform (DFT)
 at a particular frame rate and over-sampling rate.
@@ -1654,6 +1651,8 @@ four different notes in total:
    play \-n synth 2.5 sin 667 gain 1 \\
 	bend .35,180,.25  .15,740,.53  0,\-520,.3
 .EE
+Here, the first bend runs from 0.35 to 0.6, and the second one from 0.75
+to 1.28 seconds.
 Note that the clipping that is produced in this example is deliberate;
 to remove it, use
 .B gain\ \-5
diff --git a/src/bend.c b/src/bend.c
index e9ade03..e9295f0 100644
--- a/src/bend.c
+++ b/src/bend.c
@@ -70,23 +70,43 @@ static int parse(sox_effect_t * effp, char **argv, sox_rate_t \
rate)  {
   priv_t *p = (priv_t *) effp->priv;
   size_t i;
-  uint64_t time = 0, delay;
   char const *next;
+  uint64_t last_seen = 0;
+  const uint64_t in_length = argv ? 0 :
+    (effp->in_signal.length != SOX_UNKNOWN_LEN ?
+     effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN);
 
   for (i = 0; i < p->nbends; ++i) {
     if (argv)   /* 1st parse only */
       p->bends[i].str = lsx_strdup(argv[i]);
-    next = lsx_parsesamples(rate, p->bends[i].str, &delay, 't');
+
+    next = lsx_parseposition(rate, p->bends[i].str,
+             argv ? NULL : &p->bends[i].start, last_seen, in_length, '+');
+    last_seen = p->bends[i].start;
     if (next == NULL || *next != ',')
       break;
-    p->bends[i].start = time += delay;
+
     p->bends[i].cents = strtod(next + 1, (char **)&next);
     if (p->bends[i].cents == 0 || *next != ',')
       break;
-    next = lsx_parsesamples(rate, next + 1, &p->bends[i].duration, 't');
+
+    next = lsx_parseposition(rate, next + 1,
+             argv ? NULL : &p->bends[i].duration, last_seen, in_length, '+');
+    last_seen = p->bends[i].duration;
     if (next == NULL || *next != '\0')
       break;
-    time += p->bends[i].duration;
+
+    /* sanity checks */
+    if (!argv && p->bends[i].duration < p->bends[i].start) {
+      lsx_fail("Bend %" PRIuPTR " has negative width", i+1);
+      break;
+    }
+    if (!argv && i && p->bends[i].start < p->bends[i-1].start) {
+      lsx_fail("Bend %" PRIuPTR " overlaps with previous one", i+1);
+      break;
+    }
+
+    p->bends[i].duration -= p->bends[i].start;
   }
   if (i < p->nbends)
     return lsx_usage(effp);
@@ -298,7 +318,7 @@ static int lsx_kill(sox_effect_t * effp)
 sox_effect_handler_t const *lsx_bend_effect_fn(void)
 {
   static sox_effect_handler_t handler = {
-    "bend", "[-f frame-rate(25)] [-o over-sample(16)] {delay,cents,duration}",
+    "bend", "[-f frame-rate(25)] [-o over-sample(16)] {start,cents,end}",
     0, create, start, flow, 0, stop, lsx_kill, sizeof(priv_t)
   };
   return &handler;

commit 851a8d152c004310afd5bdf0a300c1c74e979855
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Thu Oct 18 01:21:05 2012 +0200

    spectrogram -S: use lsx_parseposition
    
    Use the new lsx_parseposition function for the -S option to the
    spectrogram effect and update the documentation accordingly.

diff --git a/sox.1 b/sox.1
index e65a711..c7f2904 100644
--- a/sox.1
+++ b/sox.1
@@ -3310,7 +3310,7 @@ effect is applied to the entire audio signal.
 See also
 .B \-X
 for an alternative way of setting the X-axis resolution.
-.IP \fB\-S\ \fItime\fR
+.IP \fB\-S\ \fIposition(=)\fR
 Start the spectrogram at the given point in the audio stream.  For
 example
 .EX
@@ -3318,7 +3318,6 @@ example
 .EE
 creates a spectrogram showing all but the first minute of the audio
 (the output file, however, receives the entire audio stream).
-Any time specification may be used.
 .RE
 .TP
 \ 
diff --git a/src/spectrogram.c b/src/spectrogram.c
index 8230718..a444a35 100644
--- a/src/spectrogram.c
+++ b/src/spectrogram.c
@@ -125,7 +125,7 @@ static int getopts(sox_effect_t * effp, int argc, char **argv)
     case 't': p->title            = optstate.arg; break;
     case 'c': p->comment          = optstate.arg; break;
     case 'o': p->out_name         = optstate.arg; break;
-    case 'S': next = lsx_parsesamples(1e5, optstate.arg, &dummy, 't');
+    case 'S': next = lsx_parseposition(0., optstate.arg, NULL, (uint64_t)0, \
                (uint64_t)0, '=');
       if (next && !*next) {p->start_time_str = lsx_strdup(optstate.arg); break;}
       return lsx_usage(effp);
     case 'd': next = lsx_parsesamples(1e5, optstate.arg, &dummy, 't');
@@ -214,7 +214,12 @@ static int start(sox_effect_t * effp)
     duration = d / effp->in_signal.rate;
   }
   if (p->start_time_str) {
-    lsx_parsesamples(effp->in_signal.rate, p->start_time_str, &d, 't');
+    uint64_t in_length = effp->in_signal.length != SOX_UNKNOWN_LEN ?
+      effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN;
+    if (!lsx_parseposition(effp->in_signal.rate, p->start_time_str, &d, (uint64_t)0, \
in_length, '=') || d == SOX_UNKNOWN_LEN) { +      lsx_fail("-S option: audio length \
is unknown"); +      return SOX_EOF;
+    }
     start_time = d / effp->in_signal.rate;
     p->skip = d;
   }
@@ -673,7 +678,7 @@ sox_effect_handler_t const * lsx_spectrogram_effect_fn(void)
     "\t-c text\tComment text",
     "\t-o text\tOutput file name; default `spectrogram.png'",
     "\t-d time\tAudio duration to fit to X-axis; e.g. 1:00, 48",
-    "\t-S time\tStart the spectrogram at the given time through the input",
+    "\t-S position\tStart the spectrogram at the given input position",
   };
   static char * usage;
   handler.usage = lsx_usage_lines(&usage, lines, array_length(lines));

commit d6e47684f70c9ca1ffb9cd48c82f9513ef88eddd
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Thu Oct 18 01:05:17 2012 +0200

    fade: use lsx_parseposition
    
    Use the new lsx_parseposition function for the fade effect and update
    the documentation accordingly.

diff --git a/sox.1 b/sox.1
index b85b5b3..e65a711 100644
--- a/sox.1
+++ b/sox.1
@@ -2120,7 +2120,7 @@ This effect supports the \fB\-\-plot\fR global option.
 .SP
 See also \fBbass\fR and \fBtreble\fR for shelving equalisation effects.
 .TP
-\fBfade\fR [\fItype\fR] \fIfade-in-length\fR [\fIstop-time\fR \
[\fIfade-out-length\fR]] +\fBfade\fR [\fItype\fR] \fIfade-in-length\fR \
[\fIstop-position(=)\fR [\fIfade-out-length\fR]]  Apply a fade effect to the \
                beginning, end, or both of the audio.
 .SP
 An optional \fItype\fR can be specified to select the shape of the fade
@@ -2134,20 +2134,24 @@ to full volume over the time given as \fIfade-in-length\fR.  \
Specify 0 if  no fade-in is wanted.
 .SP
 For fade-outs, the audio will be truncated at
-.I stop-time
+.I stop-position
 and the signal level will be ramped from full volume down to 0 over an
-interval of \fIfade-out-length\fR before the \fIstop-time\fR.  If
+interval of \fIfade-out-length\fR before the \fIstop-position\fR.  If
 .I fade-out-length
 is not specified, it defaults to the same value as
 \fIfade-in-length\fR.
 No fade-out is performed if
-.I stop-time
+.I stop-position
 is not specified.
 If the audio length can be determined from the input file header and any
-previous effects, then \fB0\fR may be specified for
-.I stop-time
+previous effects, then \fB\-0\fR (or, for historical reasons, \fB0\fR) may
+be specified for
+.I stop-position
 to indicate the usual case of a fade-out that ends at the end of the input
-audio stream.  Any time specification may be used for these parameters.
+audio stream.
+.SP
+Any time specification may be used for \fIfade-in-length\fR and
+\fIfade-out-length\fR.
 .SP
 See also the
 .B splice
diff --git a/src/fade.c b/src/fade.c
index c664444..3cf4876 100644
--- a/src/fade.c
+++ b/src/fade.c
@@ -90,7 +90,7 @@ static int sox_fade_getopts(sox_effect_t * effp, int argc, char \
**argv)  fade->out_stop_str = lsx_strdup(argv[t_argno]);
 
             /* Do a dummy parse to see if it will fail */
-            n = lsx_parsesamples(0., fade->out_stop_str, &samples, 't');
+            n = lsx_parseposition(0., fade->out_stop_str, NULL, (uint64_t)0, \
(uint64_t)0, '=');  if (!n || *n)
               return lsx_usage(effp);
             fade->out_stop = samples;
@@ -119,6 +119,8 @@ static int sox_fade_start(sox_effect_t * effp)
     priv_t * fade = (priv_t *) effp->priv;
     sox_bool truncate = sox_false;
     uint64_t samples;
+    uint64_t in_length = effp->in_signal.length != SOX_UNKNOWN_LEN ?
+      effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN;
 
     /* converting time values to samples */
     fade->in_start = 0;
@@ -132,9 +134,12 @@ static int sox_fade_start(sox_effect_t * effp)
     if (fade->out_stop_str)
     {
         fade->do_out = 1;
-        if (lsx_parsesamples(effp->in_signal.rate, fade->out_stop_str,
-                            &samples, 't') == NULL)
-          return lsx_usage(effp);
+        if (!lsx_parseposition(effp->in_signal.rate, fade->out_stop_str,
+                            &samples, (uint64_t)0, in_length, '=') ||
+            samples == SOX_UNKNOWN_LEN) {
+          lsx_fail("audio length is unknown");
+          return SOX_EOF;
+        }
         fade->out_stop = samples;
 
         if (!(truncate = !!fade->out_stop)) {
@@ -376,7 +381,7 @@ static double fade_gain(uint64_t index, uint64_t range, int type)
 
 static sox_effect_handler_t sox_fade_effect = {
   "fade",
-  "[ type ] fade-in-length [ stop-time [ fade-out-length ] ]\n"
+  "[ type ] fade-in-length [ stop-position [ fade-out-length ] ]\n"
   "       Time is in hh:mm:ss.frac format.\n"
   "       Fade type one of q, h, t, l or p.",
   SOX_EFF_MCHAN | SOX_EFF_LENGTH,

commit b4ee498064d4c43799d835f5a0ada856bf3f6838
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Tue Oct 16 02:39:27 2012 +0200

    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.

diff --git a/sox.1 b/sox.1
index 76d4f9c..b85b5b3 100644
--- a/sox.1
+++ b/sox.1
@@ -3969,20 +3969,12 @@ and the depth as a percentage by
 .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 @@ will copy the first ten seconds, while
 .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
diff --git a/src/trim.c b/src/trim.c
index a707e97..5c28a36 100644
--- a/src/trim.c
+++ b/src/trim.c
@@ -28,15 +28,11 @@ typedef struct {
   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 @@ static int parse(sox_effect_t *effp, int argc, char **argv)
   --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 @@ static int start(sox_effect_t *effp)
   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 @@ static int start(sox_effect_t *effp)
       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 @@ static int lsx_kill(sox_effect_t *effp)
 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)

commit a447efea202f06165d60800d33abc38e560f7240
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Tue Oct 16 02:24:44 2012 +0200

    delay: use lsx_parseposition
    
    Use the new lsx_parseposition function for the delay effect and update
    the documentation accordingly.

diff --git a/sox.1 b/sox.1
index 031242b..76d4f9c 100644
--- a/sox.1
+++ b/sox.1
@@ -1937,14 +1937,15 @@ This effect supports the \fB\-\-plot\fR global option.
 .SP
 See also the \fBbass\fR and \fBtreble\fR shelving equalisation effects.
 .TP
-\fBdelay\fR {\fItime\fR}
-Delay one or more audio channels by the given \fItime\fR (a time
-specification).
+\fBdelay\fR {\fIposition(=)\fR}
+Delay one or more audio channels such that they start at the given
+\fIposition\fR.
 For example,
-.B delay 1\*d5 0 3000s
-delays the first channel by 1\*d5 seconds, the third channel by 3000
-samples, and leaves the second channel (and any other channels that may be
-present) un-delayed.
+.B delay 1\*d5 +1 3000s
+delays the first channel by 1\*d5 seconds, the second channel by 2\*d5
+seconds (one second more than the previous channel), the third channel
+by 3000 samples, and leaves any other channels that may be
+present un-delayed.
 The following (one long) command plays a chime sound:
 .EX
 .ne 3
diff --git a/src/delay.c b/src/delay.c
index e32aebc..14da6ac 100644
--- a/src/delay.c
+++ b/src/delay.c
@@ -43,7 +43,6 @@ static int lsx_kill(sox_effect_t * effp)
 static int create(sox_effect_t * effp, int argc, char * * argv)
 {
   priv_t * p = (priv_t *)effp->priv;
-  uint64_t dummy;
   unsigned i;
 
   --argc, ++argv;
@@ -51,7 +50,7 @@ static int create(sox_effect_t * effp, int argc, char * * argv)
   p->args = lsx_calloc(p->argc, sizeof(*p->args));
   p->max_delay = lsx_malloc(sizeof(*p->max_delay));
   for (i = 0; i < p->argc; ++i) {
-    char const * next = lsx_parsesamples(1e5, p->args[i].str = lsx_strdup(argv[i]), \
&dummy, 't'); +    char const * next = lsx_parseposition(0., p->args[i].str = \
lsx_strdup(argv[i]), NULL, (uint64_t)0, (uint64_t)0, '=');  if (!next || *next) {
       lsx_kill(effp);
       return lsx_usage(effp);
@@ -70,7 +69,9 @@ static int stop(sox_effect_t * effp)
 static int start(sox_effect_t * effp)
 {
   priv_t * p = (priv_t *)effp->priv;
-  uint64_t max_delay = 0, delay;
+  uint64_t max_delay = 0, last_seen = 0, delay;
+  uint64_t in_length = effp->in_signal.length != SOX_UNKNOWN_LEN ?
+    effp->in_signal.length / effp->in_signal.channels : SOX_UNKNOWN_LEN;
 
   if (effp->flow == 0) {
     unsigned i;
@@ -79,8 +80,11 @@ static int start(sox_effect_t * effp)
       return SOX_EOF;
     }
     for (i = 0; i < p->argc; ++i) {
-      lsx_parsesamples(effp->in_signal.rate, p->args[i].str, &delay, 't');
-      p->args[i].delay = delay;
+      if (!lsx_parseposition(effp->in_signal.rate, p->args[i].str, &delay, \
last_seen, in_length, '=') || delay == SOX_UNKNOWN_LEN) { +        lsx_fail("Position \
relative to end of audio specified, but audio length is unknown"); +        return \
SOX_EOF; +      }
+      p->args[i].delay = last_seen = delay;
       if (delay > max_delay) {
         max_delay = delay;
       }
@@ -152,7 +156,7 @@ static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t \
* osamp)  sox_effect_handler_t const * lsx_delay_effect_fn(void)
 {
   static sox_effect_handler_t handler = {
-    "delay", "{length}", SOX_EFF_LENGTH | SOX_EFF_MODIFY,
+    "delay", "{position}", SOX_EFF_LENGTH | SOX_EFF_MODIFY,
     create, start, flow, drain, stop, lsx_kill, sizeof(priv_t)
   };
   return &handler;

commit b547a29888c8b6452b3f14c24bb4dda01ade6cd3
Author: Ulrich Klauer <ulrich@chirlu.de>
Date:   Tue Oct 16 02:04:05 2012 +0200

    Introduce an extended syntax for audio positions
    
    Introduce a new lsx_parseposition function (similar to lsx_parsesamples)
    that makes a trim-like syntax for specifying audio positions available to
    all effects; it is possible to give a position relative to the start of
    audio ("=2:00"), to the end of audio ("-1:30"), or to a previous position
    ("+1:00").
    
    The original lsx_parsesamples function is replaced by a wrapper for an
    internal parsesamples function that allows a start value and an initial
    combine mode (add/subtract) to be passed in, which lsx_parseposition
    needs.
    
    This commit only introduces the function and common documentation. No
    effects are using lsx_parseposition yet.

diff --git a/sox.1 b/sox.1
index 81c0889..031242b 100644
--- a/sox.1
+++ b/sox.1
@@ -1459,6 +1459,23 @@ A frequency in Hz, or, if appended with `k', kHz.
 A power gain in dB.
 Zero gives no gain; less than zero gives an attenuation.
 .TP
+\fIposition\fR
+A position within the audio stream; the syntax is
+[\fB=\fR\^|\^\fB+\fR\^|\^\fB\-\fR]\fItimespec\fR, where \fItimespec\fR is a
+time specification (see below).  The optional first character indicates
+whether the \fItimespec\fR is to be interpreted relative to the start
+(\fB=\fR) or end (\fB\-\fR) of audio, or to the previous \fIposition\fR if
+the effect accepts multiple position arguments (\fB+\fR).  The audio length
+must be known for end-relative locations to work; some effects do accept
+\fB\-0\fR for end-of-audio, though, even if the length is unknown.  Which of
+\fB=\fR, \fB+\fR, \fB\-\fR is the default depends on the effect and is shown
+in its syntax as, e.g., \fIposition(+)\fR.
+.SP
+Examples: \fB=2:00\fR (two minutes into the audio stream), \fB\-100s\fR (one
+hundred samples before the end of audio), \fB+0:12+10s\fR (twelve seconds
+and ten samples after the previous position), \fB\-0.5+1s\fR (one sample less
+than half a second before the end of audio).
+.TP
 \fIwidth\fR[\fBh\fR\^|\^\fBk\fR\^|\^\fBo\fR\^|\^\fBq\fR]
 Used to specify the band-width of a filter.  A number of different
 methods to specify the width are available (though not all for every effect).
@@ -1498,8 +1515,8 @@ counts, \fIe notation\fR is supported: `1.7e6s' is the same as \
                `1700000s'.
 .PP
 Time specifications can also be chained with \fB+\fR or \fB\-\fR into a new
 time specification where the right part is added to or subtracted from the
-left, respectively: `3:00\-200s' means two hundred samples before the three
-minute mark.
+left, respectively: `3:00\-200s' means two hundred samples less than three
+minutes.
 .SP
 To see if SoX has support for an optional effect, enter
 .B sox \-h
diff --git a/src/effects_i.c b/src/effects_i.c
index 81a8b2d..b67d594 100644
--- a/src/effects_i.c
+++ b/src/effects_i.c
@@ -1,7 +1,7 @@
 /* Implements a libSoX internal interface for implementing effects.
  * All public functions & data are prefixed with lsx_ .
  *
- * Copyright (c) 2005-8 Chris Bagwell and SoX contributors
+ * Copyright (c) 2005-2012 Chris Bagwell and SoX contributors
  *
  * This library is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
@@ -150,11 +150,17 @@ void lsx_generate_wave_table(
  * for a bare number like "123".  It can either be 't' or 's'.
  * Returns NULL on error, pointer to next char to parse otherwise.
  */
+static char const * parsesamples(sox_rate_t rate, const char *str0, uint64_t \
*samples, int def, int combine); +
 char const * lsx_parsesamples(sox_rate_t rate, const char *str0, uint64_t *samples, \
int def)  {
-  char * str = (char *)str0;
-  char combine = '+';
   *samples = 0;
+  return parsesamples(rate, str0, samples, def, '+');
+}
+
+static char const * parsesamples(sox_rate_t rate, const char *str0, uint64_t \
*samples, int def, int combine) +{
+  char * str = (char *)str0;
 
   do {
     uint64_t samples_part;
@@ -227,7 +233,7 @@ char const * lsx_parsesamples(sox_rate_t rate, const char *str0, \
                uint64_t *sampl
                            *samples - samples_part : 0;
         break;
     }
-    if (strchr("+-", *str))
+    if (*str && strchr("+-", *str))
       combine = *str++;
     else combine = '\0';
   } while (combine);
@@ -310,6 +316,67 @@ int main(int argc, char * * argv)
 }
 #endif
 
+/*
+ * lsx_parseposition
+ *
+ * Parse a string for an audio position.  Similar to lsx_parsesamples
+ * above, but an initial '=', '+' or '-' indicates that the specified time
+ * is relative to the start of audio, last used position or end of audio,
+ * respectively.  Parameter def states which of these is the default.
+ * Parameters latest and end are the positions to which '+' and '-' relate;
+ * end may be SOX_UNKNOWN_LEN, in which case "-0" is the only valid
+ * end-relative input and will result in a position of SOX_UNKNOWN_LEN.
+ * Other parameters and return value are the same as for lsx_parsesamples.
+ *
+ * A test parse that only checks for valid syntax can be done by
+ * specifying samples = NULL.  If this passes, a later reparse of the same
+ * input will only fail if it is relative to the end ("-"), not "-0", and
+ * the end position is unknown.
+ */
+char const * lsx_parseposition(sox_rate_t rate, const char *str0, uint64_t *samples, \
uint64_t latest, uint64_t end, int def) +{
+  char *str = (char *)str0;
+  char anchor, combine;
+
+  if (!strchr("+-=", def))
+    return NULL; /* error: invalid default anchor */
+  anchor = def;
+  if (*str && strchr("+-=", *str))
+    anchor = *str++;
+
+  combine = '+';
+  if (strchr("+-", anchor)) {
+    combine = anchor;
+    if (*str && strchr("+-", *str))
+      combine = *str++;
+  }
+
+  if (!samples) {
+    /* dummy parse, syntax checking only */
+    uint64_t dummy = 0;
+    return parsesamples(0., str, &dummy, 't', '+');
+  }
+
+  switch (anchor) {
+    case '=': *samples = 0; break;
+    case '+': *samples = latest; break;
+    case '-': *samples = end; break;
+  }
+
+  if (anchor == '-' && end == SOX_UNKNOWN_LEN) {
+    /* "-0" only valid input here */
+    char const *l;
+    for (l = str; *l && strchr("0123456789:.ets+-", *l); ++l);
+    if (l == str+1 && *str == '0') {
+      /* *samples already set to SOX_UNKNOWN_LEN */
+      return l;
+    }
+    return NULL; /* error: end-relative position, but end unknown */
+  }
+
+  return parsesamples(rate, str, samples, 't', combine);
+}
+
 /* a note is given as an int,
  * 0   => 440 Hz = A
  * >0  => number of half notes 'up',
diff --git a/src/sox_i.h b/src/sox_i.h
index 2c222e2..a69f7d6 100644
--- a/src/sox_i.h
+++ b/src/sox_i.h
@@ -2,7 +2,7 @@
  *
  *   This file is meant for libSoX internal use only
  *
- * Copyright 2001-2008 Chris Bagwell and SoX Contributors
+ * Copyright 2001-2012 Chris Bagwell and SoX Contributors
  *
  * This source code is freely redistributable and may be used for
  * any purpose.  This copyright notice must be maintained.
@@ -74,6 +74,7 @@ void lsx_generate_wave_table(
     double max,         /* Maximum value on the y-axis. (e.g. +1) */
     double phase);      /* Phase at 1st point; 0..2pi. (e.g. pi/2 for cosine) */
 char const * lsx_parsesamples(sox_rate_t rate, const char *str, uint64_t *samples, \
int def); +char const * lsx_parseposition(sox_rate_t rate, const char *str, uint64_t \
*samples, uint64_t latest, uint64_t end, int def);  int lsx_parse_note(char const * \
text, char * * end_ptr);  double lsx_parse_frequency_k(char const * text, char * * \
end_ptr, int key);  #define lsx_parse_frequency(a, b) lsx_parse_frequency_k(a, b, \
INT_MAX)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog         |    2 +
 sox.1             |  118 +++++++++++++++++++++++++++++-----------------------
 src/bend.c        |   32 ++++++++++++---
 src/delay.c       |   16 +++++---
 src/effects_i.c   |   73 +++++++++++++++++++++++++++++++-
 src/fade.c        |   15 +++++--
 src/pad.c         |   10 ++++-
 src/sox_i.h       |    3 +-
 src/spectrogram.c |   11 ++++-
 src/splice.c      |   20 ++++++---
 src/trim.c        |   55 ++++++++-----------------
 11 files changed, 234 insertions(+), 121 deletions(-)


hooks/post-receive
-- 
sox

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_jan
_______________________________________________
SoX-commits mailing list
SoX-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sox-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic