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;
}