shithub: sox

Download patch

ref: 9a200a7528cfbfaed3fcd14c44bffb01f4340371
parent: 9f49ec7293098b36e8e521c4da98520a0005284a
author: Ulrich Klauer <ulrich@chirlu.de>
date: Sat Sep 1 14:50:35 EDT 2012

delay: allow mixing time and sample-count args

Parse the arguments to the delay effect when the sample rate is known
(i.e. in start()). Previously, a dummy rate (100000) was used to do the
parsing on creation, which could lead to the maximum delay not being
identified correctly. (Example: sample rate = 48000, arguments "1" and
"50000s"; here, the first argument was erroneously identified as the
maximum, being interpreted as 100000 samples even though it actually
only represented 48000.)

Update the man page to no longer warn against mixing the two methods
of specifying delay values.

--- a/ChangeLog
+++ b/ChangeLog
@@ -30,6 +30,8 @@
   o 'Deemph' can now also be used at 48kHz sample rate.  (robs)
   o 'Rate' now much faster in many cases.  (robs)
   o Allow sending spectrograms to stdout. (Ulrich Klauer)
+  o Allow mixing time and sample-count arguments for the delay
+    effect. (Ulrich Klauer)
 
 Internal improvements:
 
--- a/sox.1
+++ b/sox.1
@@ -1903,7 +1903,6 @@
 Delay one or more audio channels.
 .I length
 can specify a time or, if appended with an `s', a number of samples.
-Do not specify both time and samples delays in the same command.
 For example,
 .B delay 1\*d5 0 0\*d5
 delays the first channel by 1\*d5 seconds, the third channel by 0\*d5
--- a/src/delay.c
+++ b/src/delay.c
@@ -20,7 +20,8 @@
 
 typedef struct {
   size_t argc;
-  char * * argv, * max_arg;
+  struct { char *str; uint64_t delay; } *args;
+  uint64_t *max_delay;
   uint64_t delay, pre_pad, pad;
   size_t buffer_size, buffer_index;
   sox_sample_t * buffer;
@@ -33,8 +34,9 @@
   unsigned i;
 
   for (i = 0; i < p->argc; ++i)
-    free(p->argv[i]);
-  free(p->argv);
+    free(p->args[i].str);
+  free(p->args);
+  free(p->max_delay);
   return SOX_SUCCESS;
 }
 
@@ -41,22 +43,19 @@
 static int create(sox_effect_t * effp, int argc, char * * argv)
 {
   priv_t * p = (priv_t *)effp->priv;
-  uint64_t delay, max_samples = 0;
+  uint64_t dummy;
   unsigned i;
 
   --argc, ++argv;
   p->argc = argc;
-  p->argv = lsx_calloc(p->argc, sizeof(*p->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->argv[i] = lsx_strdup(argv[i]), &delay, 't');
+    char const * next = lsx_parsesamples(1e5, p->args[i].str = lsx_strdup(argv[i]), &dummy, 't');
     if (!next || *next) {
       lsx_kill(effp);
       return lsx_usage(effp);
     }
-    if (delay > max_samples) {
-      max_samples = delay;
-      p->max_arg = p->argv[i];
-    }
   }
   return SOX_SUCCESS;
 }
@@ -71,25 +70,33 @@
 static int start(sox_effect_t * effp)
 {
   priv_t * p = (priv_t *)effp->priv;
-  uint64_t max_delay, temp;
+  uint64_t max_delay = 0, delay;
 
-  if (!p->max_arg)
-    return SOX_EFF_NULL;
-  if (p->argc > effp->in_signal.channels) {
-    lsx_fail("too few input channels");
-    return SOX_EOF;
-  }
-  if (effp->flow < p->argc) {
-    lsx_parsesamples(effp->in_signal.rate, p->argv[effp->flow], &temp, 't');
-    p->buffer_size = temp;
-  }
-  lsx_parsesamples(effp->in_signal.rate, p->max_arg, &max_delay, 't');
   if (effp->flow == 0) {
+    unsigned i;
+    if (p->argc > effp->in_signal.channels) {
+      lsx_fail("too few input channels");
+      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 (delay > max_delay) {
+        max_delay = delay;
+      }
+    }
+    *p->max_delay = max_delay;
+    if (max_delay == 0)
+      return SOX_EFF_NULL;
     effp->out_signal.length = effp->in_signal.length != SOX_UNKNOWN_LEN ?
        effp->in_signal.length + max_delay * effp->in_signal.channels :
        SOX_UNKNOWN_LEN;
     lsx_debug("extending audio by %" PRIu64 " samples", max_delay);
   }
+
+  max_delay = *p->max_delay;
+  if (effp->flow < p->argc)
+    p->buffer_size = p->args[effp->flow].delay;
   p->buffer_index = p->delay = p->pre_pad = 0;
   p->pad = max_delay - p->buffer_size;
   p->buffer = lsx_malloc(p->buffer_size * sizeof(*p->buffer));