shithub: sox

Download patch

ref: eb04277997cce429f14473ae15277eac03b69e85
parent: 6763cba31dea9a680d10d085e5e8e3f04e8cf3ce
author: robs <robs>
date: Sat Mar 8 14:24:23 EST 2008

new delay effect

--- a/ChangeLog
+++ b/ChangeLog
@@ -39,8 +39,6 @@
     encoding/decoding; display name of unsupported encoding.  (robs)
   o Can now write .amb (.wav variant) files [FR 1902232].  (robs)
   o Can now read 2,3(2.6),4 bit ADPCM .voc files [FR 1714991].  (robs)
-  o Fix auto-detect of hcom files.  (robs)
-  o Added auto-detect for caf, txw & sf files.  (robs)
 
 Effects:
 
@@ -47,6 +45,7 @@
   o New `splice' effect; splice together audio sections.  (robs)
   o New `remix' effect; complements the mixer effect.  (robs)
   o New `norm' (normalise) effect.  (robs)
+  o New `delay' effect; delay one or more channels.  (robs)
   o Fix crash on 64-bit arch. with tempo & key effects.  (Sami Liedes)
   o Fix synth max. level setting for some output encodings.  (robs)
 
@@ -70,6 +69,8 @@
 
   o Fix [1890983] rec shortcut should apply bit depth (8-bit,
     16-bit, etc.) to input handler.  (robs)
+  o Fix auto-detect of hcom files.  (robs)
+  o Added auto-detect for caf, txw & sf files.  (robs)
 
 Internal improvements:
 
--- a/soxeffect.7
+++ b/soxeffect.7
@@ -254,6 +254,22 @@
 .SP
 See also the \fBbass\fR and \fBtreble\fR shelving equalisation effects.
 .TP
+\fBdelay\fR {\fIlength\fR}
+Delay one or more audio channels.
+.I length
+can specify a time or, if appended with an `s', a number of samples.
+For example,
+.B delay 1\*d5 0 0\*d5
+delays the first channel by 1\*d5 seconds, the third channel by 0\*d5
+seconds, and leaves the second channel (and any other channels that may be
+present) un-delayed.
+The following (one long) command plays a chime sound:
+.EX
+	play -n synth sin %-21.5 sin %-14.5 sin %-9.5 sin %-5.5 \\
+	  sin %-2.5 sin %2.5 gain -5.4 fade h 0.008 2 1.5 \\
+	  delay 0 .27 .54 .76 1.01 1.3 remix - fade h 0.1 2.72 2.5
+.EE
+.TP
 \fBdither\fR [\fIdepth\fR]
 Apply dithering to the audio.
 Dithering deliberately adds digital white noise to the signal
@@ -624,7 +640,7 @@
 .I position
 is optional for the first and last lengths specified and
 if omitted correspond to the beginning and the end of the audio respectively.
-For example:
+For example,
 .B pad 1\*d5 1\*d5
 adds 1\*d5 seconds of silence padding at each end of the audio, whilst
 .B pad 4000s@3:00
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,15 +19,15 @@
 
 # Format with: !xargs echo|tr ' ' '\n'|sort|column|expand|sed 's/^/  /'
 set(effects_srcs
-  biquad          echos           noiseprof       repeat          stretch
-  biquads         effects         noisered        resample        swap
-  chorus          fade            normalise       reverb          synth
-  compand         FFT             pad             reverse         tempo
+  FFT             earwax          mixer           remix           stat
+  biquad          echo            noiseprof       repeat          stretch
+  biquads         echos           noisered        resample        swap
+  chorus          effects         normalise       reverb          synth
+  compand         fade            pad             reverse         tempo
   compandt        filter          pan             silence         tremolo
   dcshift         flanger         phaser          skeleff         trim
-  dither          key             pitch           speed           vol
-  earwax          mcompand        polyphas        splice
-  echo            mixer           remix           stat
+  delay           key             pitch           speed           vol
+  dither          mcompand        polyphas        splice
 )
 set(formats_srcs
   8svx            cvsd-fmt        htk             s1-fmt          u2-fmt
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -198,7 +198,7 @@
 	  pan.c phaser.c pitch.c polyphas.c rabbit.c remix.c repeat.c \
 	  resample.c reverb.c reverse.c silence.c skeleff.c speed.c	\
 	  splice.c stat.c stretch.c swap.c synth.c tempo.c tremolo.c trim.c \
-	  vol.c normalise.c
+	  vol.c normalise.c delay.c
 libsfx_la_CFLAGS = @SAMPLERATE_CFLAGS@
 libsfx_la_LIBADD = @SAMPLERATE_LIBS@ libsox.la
 
--- /dev/null
+++ b/src/delay.c
@@ -1,0 +1,129 @@
+/*
+ * Effect: Delay one or more channels.   (c) 2008 robs@users.sourceforge.net
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library.  If not, write to the Free Software Foundation,
+ * Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
+ */
+
+#include "sox_i.h"
+#include <string.h>
+
+typedef struct delay {
+  size_t argc;
+  char * * argv, * max_arg;
+  sox_size_t delay, pad, buffer_size, buffer_index;
+  sox_sample_t * buffer;
+} * priv_t;
+
+assert_static(sizeof(struct delay) <= SOX_MAX_EFFECT_PRIVSIZE,
+              /* else */ delay_PRIVSIZE_too_big);
+
+static int kill(sox_effect_t * effp)
+{
+  priv_t p = (priv_t) effp->priv;
+  unsigned i;
+
+  for (i = 0; i < p->argc; ++i)
+    free(p->argv[i]);
+  free(p->argv);
+  return SOX_SUCCESS;
+}
+
+static int create(sox_effect_t * effp, int argc, char * * argv)
+{
+  priv_t p = (priv_t) effp->priv;
+  sox_size_t delay, max_samples = 0;
+  unsigned i;
+
+  p->argv = xcalloc(p->argc = argc, sizeof(*p->argv));
+  for (i = 0; i < p->argc; ++i) {
+    char const * next = sox_parsesamples(96000., p->argv[i] = xstrdup(argv[i]), &delay, 't');
+    if (!next || *next) {
+      kill(effp);
+      return sox_usage(effp);
+    }
+    if (delay > max_samples) {
+      max_samples = delay;
+      p->max_arg = p->argv[i];
+    }
+  }
+  return SOX_SUCCESS;
+}
+
+static int stop(sox_effect_t * effp)
+{
+  priv_t p = (priv_t) effp->priv;
+  free(p->buffer);
+  return SOX_SUCCESS;
+}
+
+static int start(sox_effect_t * effp)
+{
+  priv_t p = (priv_t) effp->priv;
+  sox_size_t max_delay;
+
+  if (!p->max_arg)
+    return SOX_EFF_NULL;
+  if (effp->flow < p->argc)
+    sox_parsesamples(effp->in_signal.rate, p->argv[effp->flow], &p->buffer_size, 't');
+  sox_parsesamples(effp->in_signal.rate, p->max_arg, &max_delay, 't');
+  p->buffer_index = p->delay = 0;
+  p->pad = max_delay - p->buffer_size;
+  p->buffer = xmalloc(p->buffer_size * sizeof(*p->buffer));
+  return SOX_SUCCESS;
+}
+
+static int flow(sox_effect_t * effp, const sox_sample_t * ibuf,
+    sox_sample_t * obuf, sox_size_t * isamp, sox_size_t * osamp)
+{
+  priv_t p = (priv_t) effp->priv;
+  sox_size_t len = *isamp = *osamp = min(*isamp, *osamp);
+
+  if (!p->buffer_size)
+    memcpy(obuf, ibuf, len * sizeof(*obuf));
+  else for (; len; --len) {
+    if (p->delay < p->buffer_size) {
+      p->buffer[p->delay++] = *ibuf++;
+      *obuf++ = 0;
+    } else {
+      *obuf++ = p->buffer[p->buffer_index];
+      p->buffer[p->buffer_index++] = *ibuf++;
+      p->buffer_index %= p->buffer_size;
+    }
+  }
+  return SOX_SUCCESS;
+}
+
+static int drain(sox_effect_t * effp, sox_sample_t * obuf, sox_size_t * osamp)
+{
+  priv_t p = (priv_t) effp->priv;
+  sox_size_t len = *osamp = min(p->delay + p->pad, *osamp);
+
+  for (; p->delay && len; --p->delay, --len) {
+    *obuf++ = p->buffer[p->buffer_index++];
+    p->buffer_index %= p->buffer_size;
+  }
+  for (; p->pad && len; --p->pad, --len)
+    *obuf++ = 0;
+  return SOX_SUCCESS;
+}
+
+sox_effect_handler_t const * sox_delay_effect_fn(void)
+{
+  static sox_effect_handler_t handler = {
+    "delay", "{length}", SOX_EFF_LENGTH,
+    create, start, flow, drain, stop, kill
+  };
+  return &handler;
+}
--- a/src/effects.h
+++ b/src/effects.h
@@ -9,6 +9,7 @@
   EFFECT(compand)
   EFFECT(dcshift)
   EFFECT(deemph)
+  EFFECT(delay)
   EFFECT(dither)
   EFFECT(earwax)
   EFFECT(echo)