shithub: sox

Download patch

ref: 62eaa64589f187826fcb31bcf18341b0baf07441
parent: f05b1a3f9f311cb1b7f53c1ddc29c0ad644529c8
author: Ulrich Klauer <ulrich@chirlu.de>
date: Mon Jan 23 19:32:54 EST 2012

Simpler swap effect

--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,7 @@
   14.3.0   O -1/-2/-3/-4/-8        -b
   14.3.0   O -s/-u/-f              -e
   14.3.0   O -A/-U/-o/-i/-a/-g     -e
+  14.4.0   E swap with parameters  remix
 
 Previously deprecated features (to be removed in future):
 
@@ -22,7 +23,6 @@
   ated in  [F(ormat)] [E(ffect)]   Replacement             due after
   -------  ----------------------  ----------------------  -------
   14.4.0   E mixer                 remix                   2013-03-04
-  14.4.0   E swap with parameters  remix                   14.4.0
 
 
 sox-14.4.0	2012-03-04
--- a/FEATURES.in
+++ b/FEATURES.in
@@ -97,7 +97,7 @@
 ** channels: Auto mix or duplicate to change number of channels
 ** divide+: Divide sample values by those in the 1st channel (W.I.P.)
 ** remix: Produce arbitrarily mixed output channels
-** swap: Swap stereo channels
+** swap: Swap pairs of channels
 
 * Pitch/tempo effects
 ** bend: Bend pitch at given times without changing tempo
--- a/sox.1
+++ b/sox.1
@@ -3657,7 +3657,10 @@
 effect.
 .TP
 \fBswap\fR
-Swap stereo channels.
+Swap stereo channels.  If the input is not stereo, pairs of channels are
+swapped, and a possible odd last channel passed through.  E.g., for seven
+channels, the output order will be 2, 1, 4, 3, 6, 5, 7.
+.SP
 See also
 .B remix
 for an effect that allows arbitrary channel selection and ordering
--- a/src/swap.c
+++ b/src/swap.c
@@ -1,192 +1,62 @@
-/* libSoX swap - effect to swap ordering of channels in multi-channel audio.
+/* libSoX effect: swap pairs of audio channels
  *
- * Written by Chris Bagwell (cbagwell@sprynet.com) - March 16, 1999
+ * First version written 01/2012 by Ulrich Klauer.
+ * Replaces an older swap effect originally written by Chris Bagwell
+ * on March 16, 1999.
  *
-  * Copyright 1999 Chris Bagwell And Sundry Contributors
- * This source code is freely redistributable and may be used for
- * any purpose.  This copyright notice must be maintained.
- * Chris Bagwell And Sundry Contributors are not responsible for
- * the consequences of using this software.
+ * Copyright 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
+ * the Free Software Foundation; either version 2.1 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,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-
 #include "sox_i.h"
 
-typedef struct {
-  int         order[4];
-  int         def_opts;
-} priv_t;
-
-/*
- * Process options
- *
- * Don't do initialization now.
- * The 'info' fields are not yet filled in.
- */
-static int sox_swap_getopts(sox_effect_t * effp, int argc, char **argv)
+static int start(sox_effect_t *effp)
 {
-    priv_t * swap = (priv_t *) effp->priv;
-  --argc, ++argv;
-
-    if (argc)
-      lsx_warn("Invoking this effect with parameters is deprecated; use `remix' instead.");
-
-    swap->order[0] = swap->order[1] = swap->order[2] = swap->order[3] = 0;
-    if (argc)
-    {
-        swap->def_opts = 0;
-        if (argc != 2 && argc != 4)
-          return lsx_usage(effp);
-        else if (argc == 2)
-        {
-            sscanf(argv[0],"%d",&swap->order[0]);
-            sscanf(argv[1],"%d",&swap->order[1]);
-        }
-        else
-        {
-            sscanf(argv[0],"%d",&swap->order[0]);
-            sscanf(argv[1],"%d",&swap->order[1]);
-            sscanf(argv[2],"%d",&swap->order[2]);
-            sscanf(argv[3],"%d",&swap->order[3]);
-        }
-    }
-    else
-        swap->def_opts = 1;
-
-    return (SOX_SUCCESS);
+  return effp->in_signal.channels >= 2 ? SOX_SUCCESS : SOX_EFF_NULL;
 }
 
-/*
- * Prepare processing.
- * Do all initializations.
- */
-static int sox_swap_start(sox_effect_t * effp)
+static int flow(sox_effect_t *effp, const sox_sample_t *ibuf,
+    sox_sample_t *obuf, size_t *isamp, size_t *osamp)
 {
-    priv_t * swap = (priv_t *) effp->priv;
-    int i;
+  size_t len = min(*isamp, *osamp);
+  size_t channels = effp->in_signal.channels;
+  len /= channels;
+  *isamp = *osamp = len * channels;
 
-    if (effp->out_signal.channels == 1)
-    {
-        lsx_fail("Can't swap channels on mono data.");
-        return (SOX_EOF);
+  while (len--) {
+    size_t i;
+    for (i = 0; i + 1 < channels; i += 2) {
+      *obuf++ = ibuf[1];
+      *obuf++ = ibuf[0];
+      ibuf += 2;
     }
+    if (channels % 2)
+      *obuf++ = *ibuf++;
+  }
 
-    if (effp->out_signal.channels == 2)
-    {
-        if (swap->def_opts)
-        {
-            swap->order[0] = 2;
-            swap->order[1] = 1;
-        }
-
-        if (swap->order[2] || swap->order[3])
-        {
-            lsx_fail("invalid swap channel options used");
-        }
-        if (swap->order[0] != 1 && swap->order[0] != 2)
-            lsx_fail("invalid swap channel options used");
-        if (swap->order[1] != 1 && swap->order[1] != 2)
-            lsx_fail("invalid swap channel options used");
-
-        /* Convert to array offsets */
-        swap->order[0]--;
-        swap->order[1]--;
-    }
-
-    if (effp->out_signal.channels == 4)
-    {
-        if (swap->def_opts)
-        {
-            swap->order[0] = 2;
-            swap->order[1] = 1;
-            swap->order[2] = 4;
-            swap->order[3] = 3;
-        }
-
-        if (swap->order[0] < 1 || swap->order[0] > 4)
-            lsx_fail("invalid swap channel options used");
-        if (swap->order[1] < 1 || swap->order[1] > 4)
-            lsx_fail("invalid swap channel options used");
-        if (swap->order[2] < 1 || swap->order[2] > 4)
-            lsx_fail("invalid swap channel options used");
-        if (swap->order[3] < 1 || swap->order[3] > 4)
-            lsx_fail("invalid swap channel options used");
-
-        /* Convert to array offsets */
-        swap->order[0]--;
-        swap->order[1]--;
-        swap->order[2]--;
-        swap->order[3]--;
-
-    }
-
-    for (i = 0; i < (int)effp->out_signal.channels; ++i)
-      if (swap->order[i] != i)
-        return SOX_SUCCESS;
-
-    return SOX_EFF_NULL;
+  return SOX_SUCCESS;
 }
 
-/*
- * Processed signed long samples from ibuf to obuf.
- * Return number of samples processed.
- */
-static int sox_swap_flow(sox_effect_t * effp, const sox_sample_t *ibuf, sox_sample_t *obuf,
-                 size_t *isamp, size_t *osamp)
+sox_effect_handler_t const *lsx_swap_effect_fn(void)
 {
-    priv_t * swap = (priv_t *) effp->priv;
-    int len, done;
-
-    switch (effp->out_signal.channels)
-    {
-    case 2:
-        /* Length to process will be buffer length / 2 since we
-         * work with two samples at a time.
-         */
-        len = ((*isamp > *osamp) ? *osamp : *isamp) / 2;
-        for(done = 0; done < len; done++)
-        {
-            obuf[0] = ibuf[swap->order[0]];
-            obuf[1] = ibuf[swap->order[1]];
-            /* Advance buffer by 2 samples */
-            ibuf += 2;
-            obuf += 2;
-        }
-
-        *isamp = len * 2;
-        *osamp = len * 2;
-
-        break;
-
-    case 4:
-        /* Length to process will be buffer length / 4 since we
-         * work with four samples at a time.
-         */
-        len = ((*isamp > *osamp) ? *osamp : *isamp) / 4;
-        for(done = 0; done < len; done++)
-        {
-            obuf[0] = ibuf[swap->order[0]];
-            obuf[1] = ibuf[swap->order[1]];
-            obuf[2] = ibuf[swap->order[2]];
-            obuf[3] = ibuf[swap->order[3]];
-            /* Advance buffer by 2 samples */
-            ibuf += 4;
-            obuf += 4;
-        }
-        *isamp = len * 4;
-        *osamp = len * 4;
-
-        break;
-    }
-    return (SOX_SUCCESS);
-}
-
-const sox_effect_handler_t *lsx_swap_effect_fn(void)
-{
   static sox_effect_handler_t handler = {
-    "swap", NULL, SOX_EFF_MCHAN | SOX_EFF_MODIFY,
-    sox_swap_getopts, sox_swap_start, sox_swap_flow,
-    NULL, NULL, NULL, sizeof(priv_t)
+    "swap", NULL,
+    SOX_EFF_MCHAN | SOX_EFF_MODIFY,
+    NULL, start, flow, NULL, NULL, NULL,
+    0
   };
   return &handler;
 }