shithub: sox

Download patch

ref: 0dc533594b4286b2cf2c878d13b25278a76f041a
parent: 784f11d5e684bd50c0c0c98f5e552740a0e6ea86
author: cbagwell <cbagwell>
date: Tue Sep 7 18:25:24 EDT 2004

Adding initial support for sox reading multiple input files and
concat'ing into output file.

--- a/Changelog
+++ b/Changelog
@@ -14,9 +14,13 @@
     block when there wasn't.
   o Restructured directory layout so that source code is in
     a seperate directory.
+  o Modified SoX to accept multiple input files.  Concatenates
+    files together in this case.
+  o Removed map effect so that loops and instr could be removed
+    from effects structures.  This makes effects engine stand
+    alone from the rest of the sox package.
   o Benedikt Zeyen found a bug in synth effect when generating
     brown noise that could cause clipping.
-   
 
 sox-12.17.5
 -----------
--- a/sox.1
+++ b/sox.1
@@ -90,8 +90,6 @@
 .br
     \fBlowpass\fR \fIfrequency\fR
 .br
-    \fBmap\fR
-.br
     \fBmask\fR
 .br
     \fBpan\fR \fIdirection\fR
@@ -878,10 +876,6 @@
 .TP 10
 lowpass \fIfrequency\fB
 Butterworth lowpass filter.  Description coming soon!
-.TP 10
-map 
-Display a list of loops in a sample,
-and miscellaneous loop info.
 .TP 10
 mask
 Add "masking noise" to signal.
--- a/src/Makefile.dos
+++ b/src/Makefile.dos
@@ -22,7 +22,7 @@
 EOBJ	= avg.obj band.obj bandpass.obj breject.obj btrworth.obj chorus.obj \
 	  compand.obj copy.obj dcshift.obj deemphas.obj earwax.o \
 	  echo.obj echos.obj fade.obj filter.obj flanger.obj highp.obj \
-	  highpass.obj lowp.obj lowpass.obj map.obj mask.obj phaser.obj \
+	  highpass.obj lowp.obj lowpass.obj mask.obj phaser.obj \
 	  pitch.obj pan.obj polyphase.obj rate.obj repeat.obj resample.obj \
 	  reverb.obj reverse.obj silence.obj speed.obj stat.obj \
 	  stretch.obj swap.obj synth.obj trim.obj vibro.obj vol.obj
--- a/src/Makefile.gcc
+++ b/src/Makefile.gcc
@@ -27,7 +27,7 @@
 
 EOBJ    = avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
           copy.o dcshift.o deemphas.o earwax.o echo.o echos.o fade.o \
-	  filter.o flanger.o highp.o highpass.o lowp.o lowpass.o map.o \
+	  filter.o flanger.o highp.o highpass.o lowp.o lowpass.o \
 	  mask.o pan.o phaser.o pitch.o polyphas.o rate.o repeat.o \
 	  resample.o reverb.o reverse.o silence.o speed.o \
 	  stat.o stretch.o swap.o synth.o trim.o vibro.o vol.o
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -49,7 +49,7 @@
 EOBJ	= avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
 	  copy.o dcshift.o deemphas.o earwax.o echo.o echos.o \
 	  fade.o filter.o flanger.o highp.o highpass.o lowp.o \
-	  lowpass.o map.o mask.o pan.o phaser.o pitch.o polyphas.o \
+	  lowpass.o mask.o pan.o phaser.o pitch.o polyphas.o \
 	  rate.o repeat.o resample.o reverb.o reverse.o silence.o speed.o \
 	  stat.o stretch.o swap.o synth.o trim.o vibro.o vol.o
 
@@ -138,7 +138,7 @@
 	$(RM) $(includedir)/ststdint.h
 
 clean:
-	$(RM) *.o
+	$(RM) *.o libst.a
 	cd gsm && $(RM) *.o
 
 distclean:
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -462,9 +462,6 @@
         {"lowpass", 0,
                 st_lowpass_getopts, st_lowpass_start, st_butterworth_flow,
                 st_effect_nothing_drain, st_effect_nothing},
-        {"map", ST_EFF_REPORT,
-                st_map_getopts, st_map_start, st_map_flow,
-                st_effect_nothing_drain, st_effect_nothing},
         {"mask", ST_EFF_MCHAN,
                 st_mask_getopts, st_effect_nothing, st_mask_flow,
                 st_effect_nothing_drain, st_effect_nothing},
--- a/src/raw.c
+++ b/src/raw.c
@@ -91,12 +91,12 @@
             break;
         default:
             st_fail_errno(ft,ST_ENOTSUP,"Can't seek this data size");
-            return(ft->st_errno);
+            return ft->st_errno;
     }
 
     ft->st_errno = st_seek(ft,offset*ft->info.size,SEEK_SET);
 
-    return(ft->st_errno);
+    return ft->st_errno;
 }
 
 int st_rawstartread(ft_t ft)
@@ -105,7 +105,7 @@
     if (!ft->file.buf)
     {
         st_fail_errno(ft,ST_ENOMEM,"Unable to alloc resources");
-        return(ST_EOF);
+        return ST_EOF;
     }
     ft->file.size = ST_BUFSIZ;
     ft->file.count = 0;
@@ -112,7 +112,7 @@
     ft->file.pos = 0;
     ft->file.eof = 0;
 
-    return(ST_SUCCESS);
+    return ST_SUCCESS;
 }
 
 int st_rawstartwrite(ft_t ft)
@@ -121,13 +121,13 @@
     if (!ft->file.buf)
     {
         st_fail_errno(ft,ST_ENOMEM,"Unable to alloc resources");
-        return(ST_EOF);
+        return ST_EOF;
     }
     ft->file.size = ST_BUFSIZ;
     ft->file.pos = 0;
     ft->file.eof = 0;
 
-    return(ST_SUCCESS);
+    return ST_SUCCESS;
 }
 
 void st_ub_read_buf(st_sample_t *buf1, char *buf2, st_ssize_t len, char swap)
@@ -360,7 +360,7 @@
                     break;
                 default:
                     st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
-                    return(0);
+                    return ST_EOF;
             }
             break;
 
@@ -375,7 +375,7 @@
                     break;
                 default:
                     st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
-                    return(0);
+                    return ST_EOF;
             }
             break;
 
@@ -393,7 +393,7 @@
                     break;
                 default:
                     st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
-                    return(0);
+                    return ST_EOF;
             }
             break;
 
@@ -410,7 +410,7 @@
 
         default:
             st_fail_errno(ft,ST_EFMT,"Do not support this data size for this handler");
-            return (0);
+            return ST_EOF;
     }
 
 
@@ -456,6 +456,10 @@
         if (ft->file.eof)
             break;
     }
+
+    if (done == 0 && ft->file.eof)
+        return ST_EOF;
+
     return done;
 }
 
@@ -463,7 +467,7 @@
 {
         free(ft->file.buf);
 
-        return(ST_SUCCESS);
+        return ST_SUCCESS;
 }
 
 void st_ub_write_buf(char* buf1, st_sample_t *buf2, st_ssize_t len, char swap)
@@ -668,7 +672,7 @@
                     break;
                 default:
                     st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
-                    return(0);
+                    return ST_EOF;
             }
             break;
 
@@ -683,7 +687,7 @@
                     break;
                 default:
                     st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
-                    return(0);
+                    return ST_EOF;
             }
             break;
 
@@ -701,7 +705,7 @@
                     break;
                 default:
                     st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
-                    return(0);
+                    return ST_EOF;
             }
             break;
 
@@ -713,13 +717,13 @@
                     break;
                 default:
                     st_fail_errno(ft,ST_EFMT,"Do not support this encoding for this data size");
-                    return(0);
+                    return ST_EOF;
             }
             break;
 
         default:
             st_fail_errno(ft,ST_EFMT,"Do not support this data size for this handler");
-            return (0);
+            return ST_EOF;
     }
 
     while (done < nsamp && !ft->file.eof)
@@ -744,7 +748,7 @@
 {
         writeflush(ft);
         free(ft->file.buf);
-        return(ST_SUCCESS);
+        return ST_SUCCESS;
 }
 
 /*
--- a/src/sox.c
+++ b/src/sox.c
@@ -61,7 +61,7 @@
 static int dovolume = 0;        /* User wants volume change */
 static double volume = 1.0;     /* Linear volume change */
 static int clipped = 0;         /* Volume change clipping errors */
-static int writing = 0;         /* are we writing to a file? */
+static int writing = 1;         /* are we writing to a file? assume yes. */
 static int soxpreview = 0;      /* preview mode */
 
 static st_sample_t ibufl[ST_BUFSIZ/2];    /* Left/right interleave buffers */
@@ -69,11 +69,21 @@
 static st_sample_t obufl[ST_BUFSIZ/2];
 static st_sample_t obufr[ST_BUFSIZ/2];
 
+typedef struct file_options
+{
+    char *filename;
+    char *filetype;
+    st_signalinfo_t info;
+    char swap;
+    double volume;
+    char *comment;
+} file_options_t;
+
 /* local forward declarations */
-static void doopts(ft_t, int, char **);
-static void copy_input(ft_t);
+static void doopts(file_options_t *fo, int, char **);
+static void copy_input(int offset);
 static void open_input(ft_t);
-static void copy_output(ft_t);
+static void copy_output(int offset);
 static void open_output(ft_t);
 static void usage(char *) NORET;
 static int filetype(int);
@@ -85,20 +95,20 @@
 static int flow_effect(int);
 static int drain_effect(int);
 
-#ifdef SOXMIX
 #define MAX_INPUT_FILES 2
+#define MAX_FILES MAX_INPUT_FILES + 1
+#ifdef SOXMIX
 #define REQUIRED_INPUT_FILES 2
 #else
-#define MAX_INPUT_FILES 1
 #define REQUIRED_INPUT_FILES 1
 #endif
 
-static ft_t informat[MAX_INPUT_FILES];
+/* Array's tracking input and output files */
+static file_options_t *file_opts[MAX_FILES];
+static ft_t file_desc[MAX_FILES];
+static int file_count = 0;
 static int input_count = 0;
 
-static ft_t outformat;
-static int output_count = 0;
-
 /* We parse effects into a temporary effects table and then place into
  * the real effects table.  This makes it easier to reorder some effects
  * as needed.  For instance, we can run a resampling effect before
@@ -107,7 +117,7 @@
  *
  * Real effects table only needs to be 2 entries bigger then the user
  * specified table.  This is because at most we will need to add
- * a resample effect and an channel averaging effect.
+ * a resample effect and a channel averaging effect.
  */
 #define MAX_EFF 16
 #define MAX_USER_EFF 14
@@ -126,200 +136,160 @@
 static struct st_effect user_efftab[MAX_USER_EFF];
 static int nuser_effects;
 
-int main(argc, argv)
-int argc;
-char **argv;
+int main(int argc, char **argv)
 {
-        int argc_effect;
-        ft_t ft;
-        int parsing_output = 0;
-        int i;
+    int argc_effect;
+    file_options_t *fo;
+    int i;
 
-        myname = argv[0];
+    myname = argv[0];
 
-        /* Loop over arguments and filenames, stop when an effect name is found */
-        while (optind < argc && output_count < 1 &&
-               st_checkeffect(argv[optind]) != ST_SUCCESS)
+    /* Loop over arguments and filenames, stop when an effect name is 
+     * found.
+     */
+    while (optind < argc && st_checkeffect(argv[optind]) != ST_SUCCESS)
+    {
+        /*
+         * Its possible to not specify the output filename by using
+         * "-e" option. This allows effects to be ran on data but
+         * no output file to be written.
+         */
+        if (strcmp(argv[optind], "-e") == 0)
         {
-
-            /*
-             * Its possible to not specify the output filename by using
-             * "-e" option. This allows effects to be ran on data but
-             * no output file to be written.
+            /* -e option found.  Only thing valid after an -e
+             * option are effects.
              */
-            if (strcmp(argv[optind], "-e"))
+            optind++;
+            if (optind >= argc ||
+                st_checkeffect(argv[optind]) == ST_SUCCESS)
             {
-                /* No -e option appears to be set.  Attempt to see if
-                 * this is the last filename or not.  If we see no more
-                 * options or an effect name then we assume this is
-                 * the last filename.
-                 */
-                if (input_count >= REQUIRED_INPUT_FILES &&
-                    (optind == (argc-1) ||
-                     st_checkeffect(argv[optind+1]) == ST_SUCCESS ||
-                     input_count >= MAX_INPUT_FILES))
-                {
-                    parsing_output = 1;
-                }
-
-                if (parsing_output)
-                    writing = 1;
+                writing = 0;
             }
             else
             {
-                /* -e option found.  Make sure this was done on the
-                 * output side.  Should be no more parameters or
-                 * a valid effects name.
-                 */
-                if (input_count >= REQUIRED_INPUT_FILES &&
-                    (optind == (argc-1) ||
-                     st_checkeffect(argv[optind+1]) == ST_SUCCESS ||
-                     input_count >= MAX_INPUT_FILES))
-                {
-                    parsing_output = 1;
-                }
-
-                if (parsing_output)
-                {
-                    writing = 0;
-                    optind++;  /* Move passed -e */
-                }
-                else
-                {
-                    usage("Can only specify \"-e\" for output filenames");
-                }
+                usage("Can only specify \"-e\" for output filenames");
             }
+        }
+        else
+        {
+            /* FIXME: Afterwards, set volume option to 1 / # inputs */
+            fo = calloc(sizeof(file_options_t), 1);
+            fo->info.size = -1;
+            fo->info.encoding = -1;
+            fo->info.channels = -1;
+            fo->volume = 1.0;
+            file_opts[file_count++] = fo;
 
-            ft = st_initformat();
+            doopts(fo, argc, argv);
 
-            doopts(ft, argc, argv);
-
-            /* See if we have all the input filenames we need.
-             * If not, then parse this as input filenames.
-             *
-             * If we have enough but haven't reached the max #
-             * of inputs, then only treat this as an input filename
-             * if it looks like we have more filenames left.
-             */
-            if (!parsing_output)
+            if (optind < argc)
             {
-                if (optind < argc)
-                {
-                    ft->filename = strdup(argv[optind]);
-                    optind++;
-
-                    copy_input(ft);
-                    open_input(ft);
-                }
+                fo->filename = strdup(argv[optind]);
+                optind++;
             }
             else
             {
-                if (optind < argc && writing)
-                {
-                    ft->filename = strdup(argv[optind]);
-                    optind++;
-                }
-                else
-                {
-                    ft->filename = 0;
-                }
-
-                copy_output(ft);
-                /* Hold off on opening file until the very last minute.
-                 * This allows us to verify header in input files are
-                 * what they should be and parse effect command lines.
-                 * That way if anything is found invalid, we will abort
-                 * without truncating any existing file that has the same
-                 * output filename.
-                 */
+                usage("missing filename");
             }
         }
+    } /* while (commandline options) */
 
-        /* Make sure we got at least the required # of input filename */
-        if (input_count < REQUIRED_INPUT_FILES ||
-            !informat[REQUIRED_INPUT_FILES-1] ||
-            !informat[REQUIRED_INPUT_FILES-1]->filename)
-            usage("Not enough input files specified");
+    if (writing)
+        input_count = file_count - 1;
+    else
+        input_count = file_count;
 
-        if (!outformat || (!outformat->filename && writing))
-            usage("No output file?");
+    /* Make sure we got at least the required # of input filename */
+    if (input_count < REQUIRED_INPUT_FILES)
+        usage("Not enough input or output filenames specified");
 
-        /* Loop through the reset of the arguments looking for effects */
-        nuser_effects = 0;
+    for (i = 0; i < input_count; i++)
+    {
+        copy_input(i);
+        open_input(file_desc[i]);
+    }
 
-        while (optind < argc)
-        {
-            if (nuser_effects >= MAX_USER_EFF)
-            {
-                st_fail("To many effects specified.\n");
-            }
+    if (writing)
+    {
+        copy_output(file_count-1);
+        /* Hold off on opening file until the very last minute.
+         * This allows us to verify header in input files are
+         * what they should be and parse effect command lines.
+         * That way if anything is found invalid, we will abort
+         * without truncating any existing file that has the same
+         * output filename.
+         */
+    }
 
-            argc_effect = st_geteffect_opt(&user_efftab[nuser_effects],
-                                           argc - optind, &argv[optind]);
+    /* Loop through the reset of the arguments looking for effects */
+    nuser_effects = 0;
 
-            if (argc_effect == ST_EOF)
-            {
-                int i1;
-                fprintf(stderr, "%s: Known effects: ",myname);
-                for (i1 = 0; st_effects[i1].name; i1++)
-                    fprintf(stderr, "%s ", st_effects[i1].name);
-                fprintf(stderr, "\n\n");
-                st_fail("Effect '%s' is not known!", argv[optind]);
-            }
+    while (optind < argc)
+    {
+        if (nuser_effects >= MAX_USER_EFF)
+        {
+            st_fail("To many effects specified.\n");
+        }
 
+        argc_effect = st_geteffect_opt(&user_efftab[nuser_effects],
+                                       argc - optind, &argv[optind]);
 
-            /* Skip past effect name */
-            optind++;
+        if (argc_effect == ST_EOF)
+        {
+            int i1;
+            fprintf(stderr, "%s: Known effects: ",myname);
+            for (i1 = 0; st_effects[i1].name; i1++)
+                fprintf(stderr, "%s ", st_effects[i1].name);
+            fprintf(stderr, "\n\n");
+            st_fail("Effect '%s' is not known!", argv[optind]);
+        }
 
-            (*user_efftab[nuser_effects].h->getopts)(&user_efftab[nuser_effects],
-                                                     argc_effect,
-                                                     &argv[optind]);
 
-            /* Skip past the effect arguments */
-            optind += argc_effect;
-            nuser_effects++;
-        }
+        /* Skip past effect name */
+        optind++;
 
-        if (dovolume)
-            st_report("Volume factor: %f\n", volume);
+        (*user_efftab[nuser_effects].h->getopts)(&user_efftab[nuser_effects],
+                                                 argc_effect,
+                                                 &argv[optind]);
 
-        if (dovolume && volume < 0.0)
-            st_report("Volume adjustment is negative.  This will result in a phase change\n");
+        /* Skip past the effect arguments */
+        optind += argc_effect;
+        nuser_effects++;
+    }
 
-        process();
-        statistics();
+    process();
+    statistics();
 
-        for (i = 0; i < input_count; i++)
-        {
-            if (informat[i])
-                free(informat[i]);
-        }
-        if (outformat)
-            free(outformat);
-        return(0);
+    for (i = 0; i < file_count; i++)
+        free(file_desc[i]);
+
+    return(0);
 }
 
-static void copy_input(ft_t ft)
+static void copy_input(int offset)
 {
-    informat[input_count] = ft;
-
+    /* FIXME: Check for malloc for failures */
+    file_desc[offset] = st_initformat();
+    file_desc[offset]->info = file_opts[offset]->info;
+    file_desc[offset]->filename = file_opts[offset]->filename;
     /* Let auto effect do the work if user is not overriding. */
-    if (!ft->filetype)
-        ft->filetype = "auto";
+    if (!file_opts[offset]->filetype)
+        file_desc[offset]->filetype = "auto";
+    else
+        file_desc[offset]->filetype = strdup(file_opts[offset]->filetype);
 
-    if ( st_gettype(ft) )
+    if (st_gettype(file_desc[offset]))
         st_fail("Unknown input file format for '%s':  %s", 
-                ft->filename, ft->st_errstr);
-
-    input_count++;
+                file_desc[offset]->filename, 
+                file_desc[offset]->st_errstr);
 }
 
 static void open_input(ft_t ft)
 {
     /* Open file handler based on input name.  Used stdin file handler
-     * if the filename is "="
+     * if the filename is "-"
      */
-    if (! strcmp(ft->filename, "-"))
+    if (!strcmp(ft->filename, "-"))
         ft->fp = stdin;
     else if ((ft->fp = fopen(ft->filename, "rb")) == NULL)
         st_fail("Can't open input file '%s': %s", ft->filename,
@@ -339,34 +309,42 @@
 #define LASTCHAR '/'
 #endif
 
-static void copy_output(ft_t ft)
+static void copy_output(int offset)
 {
-    outformat = ft;
-
-    if (writing && !ft->filetype && ft->filename) {
+    /* FIXME: Check for malloc for failures */
+    file_desc[offset] = st_initformat();;
+    file_desc[offset]->info = file_opts[offset]->info;
+    file_desc[offset]->filename = file_opts[offset]->filename;
+    file_desc[offset]->filetype = file_opts[offset]->filetype;
+ 
+    if (writing && !file_desc[offset]->filetype) {
         /* Use filename extension to determine audio type. */
 
         /* First, chop off any path portions of filename.  This
          * prevents the next search from considering that part. */
-        if ((ft->filetype = strrchr(ft->filename, LASTCHAR)) == NULL)
-            ft->filetype = ft->filename;
+        /* FIXME: using strrchr can only lead to problems when knowing
+         * what to free()
+         */
+        if ((file_desc[offset]->filetype = 
+             strrchr(file_desc[offset]->filename, LASTCHAR)) == NULL)
+            file_desc[offset]->filetype = file_desc[offset]->filename;
 
         /* Now look for an filename extension */
-        if ((ft->filetype = strrchr(ft->filetype, '.')) != NULL)
-            ft->filetype++;
+        if ((file_desc[offset]->filetype = 
+             strrchr(file_desc[offset]->filetype, '.')) != NULL)
+            file_desc[offset]->filetype++;
         else
-            ft->filetype = NULL;
+            file_desc[offset]->filetype = NULL;
     }
 
-    if (writing && ft->filename)
+    if (writing)
     {
-        if ( st_gettype(ft) )
+        if (st_gettype(file_desc[offset]))
             st_fail("Unknown output file format for '%s': %s",
-                    ft->filename, ft->st_errstr);
+                    file_desc[offset]->filename, 
+                    file_desc[offset]->st_errstr);
 
     }
-
-    output_count++;
 }
 
 static void open_output(ft_t ft)
@@ -418,124 +396,107 @@
 static char *getoptstr = "r:v:t:c:phsuUAaigbwlfdxV";
 #endif
 
-static void doopts(ft_t ft, int argc, char **argv)
+static void doopts(file_options_t *fo, int argc, char **argv)
 {
-        int c, i;
-        char *str;
+    int c, i;
+    char *str;
 
-        while ((c = getopt(argc, argv, getoptstr)) != -1) {
-                switch(c) {
-                case 'p':
-                        soxpreview++;
-                        break;
+    while ((c = getopt(argc, argv, getoptstr)) != -1) {
+        switch(c) {
+            case 'p':
+                soxpreview++;
+                break;
 
-                case 'h':
-                        usage((char *)0);
-                        /* no return from above */
+            case 'h':
+                usage((char *)0);
+                /* no return from above */
 
-                case 't':
-                        if (! ft) usage("-t");
-                        ft->filetype = optarg;
-                        if (ft->filetype[0] == '.')
-                                ft->filetype++;
-                        break;
+            case 't':
+                fo->filetype = optarg;
+                if (fo->filetype[0] == '.')
+                    fo->filetype++;
+                break;
 
-                case 'r':
-                        if (! ft) usage("-r");
-                        str = optarg;
-                        if ((! sscanf(str, "%u", &ft->info.rate)) ||
-                                        (ft->info.rate <= 0))
-                                st_fail("-r must be given a positive integer");
-                        break;
-                case 'v':
-                        if (!ft || dovolume) usage("-v");
-                        str = optarg;
-                        if (! sscanf(str, "%lf", &volume))
-                            st_fail("Volume value '%s' is not a number",
-                                    optarg);
-                        dovolume = 1;
-                        break;
+            case 'r':
+                str = optarg;
+                if ((!sscanf(optarg, "%u", &fo->info.rate)) ||
+                    (fo->info.rate <= 0))
+                    st_fail("-r must be given a positive integer");
+                break;
+            case 'v':
+                str = optarg;
+                if (!sscanf(str, "%lf", &fo->volume))
+                    st_fail("Volume value '%s' is not a number",
+                            optarg);
+                if (fo->volume < 0.0)
+                    st_report("Volume adjustment is negative.  This will result in a phase change\n");
+                break;
 
-                case 'c':
-                        if (! ft) usage("-c");
-                        str = optarg;
-                        if (!sscanf(str, "%d", &i))
-                            st_fail("-c must be given a number");
-                        /* Since we use -1 as a special internal value,
-                         * we must do some extra logic so user doesn't
-                         * get confused when we translate -1 to mean
-                         * something valid.
-                         */
-                        if (i < 1)
-                            st_fail("-c must be given a positive number");
-                        ft->info.channels = i;
-                        break;
-                case 'b':
-                        if (! ft) usage("-b");
-                        ft->info.size = ST_SIZE_BYTE;
-                        break;
-                case 'w':
-                        if (! ft) usage("-w");
-                        ft->info.size = ST_SIZE_WORD;
-                        break;
-                case 'l':
-                        if (! ft) usage("-l");
-                        ft->info.size = ST_SIZE_DWORD;
-                        break;
-                case 'd':
-                        if (! ft) usage("-d");
-                        ft->info.size = ST_SIZE_DDWORD;
-                        break;
-                case 's':
-                        if (! ft) usage("-s");
-                        ft->info.encoding = ST_ENCODING_SIGN2;
-                        break;
-                case 'u':
-                        if (! ft) usage("-u");
-                        ft->info.encoding = ST_ENCODING_UNSIGNED;
-                        break;
-                case 'U':
-                        if (! ft) usage("-U");
-                        ft->info.encoding = ST_ENCODING_ULAW;
-                        if (ft->info.size == -1)
-                            ft->info.size = ST_SIZE_BYTE;
-                        break;
-                case 'A':
-                        if (! ft) usage("-A");
-                        ft->info.encoding = ST_ENCODING_ALAW;
-                        if (ft->info.size == -1)
-                            ft->info.size = ST_SIZE_BYTE;
-                        break;
-                case 'f':
-                        if (! ft) usage("-f");
-                        ft->info.encoding = ST_ENCODING_FLOAT;
-                        break;
-                case 'a':
-                        if (! ft) usage("-a");
-                        ft->info.encoding = ST_ENCODING_ADPCM;
-                        break;
-                case 'i':
-                        if (! ft) usage("-i");
-                        ft->info.encoding = ST_ENCODING_IMA_ADPCM;
-                        break;
-                case 'g':
-                        if (! ft) usage("-g");
-                        ft->info.encoding = ST_ENCODING_GSM;
-                        break;
+            case 'c':
+                str = optarg;
+                if (!sscanf(str, "%d", &i))
+                    st_fail("-c must be given a number");
+                /* Since we use -1 as a special internal value,
+                 * we must do some extra logic so user doesn't
+                 * get confused when we translate -1 to mean
+                 * something valid.
+                 */
+                if (i < 1)
+                    st_fail("-c must be given a positive number");
+                fo->info.channels = i;
+                break;
+            case 'b':
+                fo->info.size = ST_SIZE_BYTE;
+                break;
+            case 'w':
+                fo->info.size = ST_SIZE_WORD;
+                break;
+            case 'l':
+                fo->info.size = ST_SIZE_DWORD;
+                break;
+            case 'd':
+                fo->info.size = ST_SIZE_DDWORD;
+                break;
+            case 's':
+                fo->info.encoding = ST_ENCODING_SIGN2;
+                break;
+            case 'u':
+                fo->info.encoding = ST_ENCODING_UNSIGNED;
+                break;
+            case 'U':
+                fo->info.encoding = ST_ENCODING_ULAW;
+                if (fo->info.size == -1)
+                    fo->info.size = ST_SIZE_BYTE;
+                break;
+            case 'A':
+                fo->info.encoding = ST_ENCODING_ALAW;
+                if (fo->info.size == -1)
+                    fo->info.size = ST_SIZE_BYTE;
+                break;
+            case 'f':
+                fo->info.encoding = ST_ENCODING_FLOAT;
+                break;
+            case 'a':
+                fo->info.encoding = ST_ENCODING_ADPCM;
+                break;
+            case 'i':
+                fo->info.encoding = ST_ENCODING_IMA_ADPCM;
+                break;
+            case 'g':
+                fo->info.encoding = ST_ENCODING_GSM;
+                break;
 
-                case 'x':
-                        if (! ft) usage("-x");
-                        ft->swap = 1;
-                        break;
+            case 'x':
+                fo->swap = 1;
+                break;
 
-                case 'V':
-                        verbose = 1;
-                        break;
-                }
+            case 'V':
+                verbose = 1;
+                break;
         }
+    }
 }
 
-#ifdef SOXMIX
 static int compare_input(ft_t ft1, ft_t ft2)
 {
     if (ft1->info.rate != ft2->info.rate)
@@ -549,7 +510,6 @@
 
     return ST_SUCCESS;
 }
-#endif
 
 /*
  * Process input file -> effect table -> output file
@@ -558,7 +518,9 @@
 
 static void process(void) {
     int e, f, flowstatus;
-#ifdef SOXMIX
+#ifndef SOXMIX
+    int current_input;
+#else
     st_size_t s;
     st_ssize_t ilen[MAX_INPUT_FILES];
     st_sample_t *ibuf[MAX_INPUT_FILES];
@@ -567,10 +529,10 @@
     for (f = 0; f < input_count; f++)
     {
         /* Read and write starters can change their formats. */
-        if ((* informat[f]->h->startread)(informat[f]) != ST_SUCCESS)
+        if ((*file_desc[f]->h->startread)(file_desc[f]) != ST_SUCCESS)
         {
-            st_fail("Failed reading %s: %s",informat[f]->filename,
-                    informat[f]->st_errstr);
+            st_fail("Failed reading %s: %s",file_desc[f]->filename,
+                    file_desc[f]->st_errstr);
         }
 
         /* Go a head and assume 1 channel audio if nothing is detected.
@@ -577,60 +539,60 @@
          * This is because libst usually doesn't set this for mono file
          * formats (for historical reasons).
          */
-        if (informat[f]->info.channels == -1)
-            informat[f]->info.channels = 1;
+        if (file_desc[f]->info.channels == -1)
+            file_desc[f]->info.channels = 1;
 
-        if ( st_checkformat(informat[f]) )
-            st_fail("bad input format for file %s: %s",informat[f]->filename,informat[f]->st_errstr);
+        if (st_checkformat(file_desc[f]) )
+            st_fail("bad input format for file %s: %s", file_desc[f]->filename,
+                    file_desc[f]->st_errstr);
 
         st_report("Input file %s: using sample rate %lu\n\tsize %s, encoding %s, %d %s",
-                  informat[f]->filename, informat[f]->info.rate,
-                  st_sizes_str[(unsigned char)informat[f]->info.size],
-                  st_encodings_str[(unsigned char)informat[f]->info.encoding],
-                  informat[f]->info.channels,
-                  (informat[f]->info.channels > 1) ? "channels" : "channel");
+                  file_desc[f]->filename, file_desc[f]->info.rate,
+                  st_sizes_str[(unsigned char)file_desc[f]->info.size],
+                  st_encodings_str[(unsigned char)file_desc[f]->info.encoding],
+                  file_desc[f]->info.channels,
+                  (file_desc[f]->info.channels > 1) ? "channels" : "channel");
 
-        if (informat[f]->comment)
+        if (file_desc[f]->comment)
             st_report("Input file %s: comment \"%s\"\n",
-                      informat[f]->filename, informat[f]->comment);
+                      file_desc[f]->filename, file_desc[f]->comment);
     }
 
-#ifdef SOXMIX
     for (f = 1; f < input_count; f++)
     {
-        if (compare_input(informat[0], informat[f]) != ST_SUCCESS)
+        if (compare_input(file_desc[0], file_desc[f]) != ST_SUCCESS)
         {
             st_fail("Input files must have the same rate, channels, data size, and encoding");
         }
     }
-#endif
 
     if (writing)
     {
-        open_output(outformat);
+        open_output(file_desc[file_count-1]);
 
         /* Always use first input file as a reference for output
          * file format.
          */
-        st_copyformat(informat[0], outformat);
+        st_copyformat(file_desc[0], file_desc[file_count-1]);
 
-        if ((*outformat->h->startwrite)(outformat) == ST_EOF)
-        {
-            st_fail(outformat->st_errstr);
-        }
+        if ((*file_desc[file_count-1]->h->startwrite)(file_desc[file_count-1]) == ST_EOF)
+            st_fail(file_desc[file_count-1]->st_errstr);
 
-        if (st_checkformat(outformat))
-                st_fail("bad output format: %s",outformat->st_errstr);
+        if (st_checkformat(file_desc[file_count-1]))
+            st_fail("bad output format: %s", 
+                    file_desc[file_count-1]->st_errstr);
 
         st_report("Output file %s: using sample rate %lu\n\tsize %s, encoding %s, %d %s",
-               outformat->filename, outformat->info.rate,
-               st_sizes_str[(unsigned char)outformat->info.size],
-               st_encodings_str[(unsigned char)outformat->info.encoding],
-               outformat->info.channels,
-               (outformat->info.channels > 1) ? "channels" : "channel");
+                  file_desc[file_count-1]->filename, 
+                  file_desc[file_count-1]->info.rate,
+                  st_sizes_str[(unsigned char)file_desc[file_count-1]->info.size],
+                  st_encodings_str[(unsigned char)file_desc[file_count-1]->info.encoding],
+                  file_desc[file_count-1]->info.channels,
+                  (file_desc[file_count-1]->info.channels > 1) ? "channels" : "channel");
 
-        if (outformat->comment)
-            st_report("Output file: comment \"%s\"\n", outformat->comment);
+        if (file_desc[file_count-1]->comment)
+            st_report("Output file: comment \"%s\"\n", 
+                      file_desc[file_count-1]->comment);
     }
 
     /* build efftab */
@@ -678,31 +640,54 @@
      * Just like errno, we must set st_errno to known values before
      * calling I/O operations.
      */
-    for (f = 0; f < input_count; f++)
-        informat[f]->st_errno = 0;
-    outformat->st_errno = 0;
+    for (f = 0; f < file_count; f++)
+        file_desc[f]->st_errno = 0;
 
-    /* Run input data through effects and get more until olen == 0 */
-    do {
+#ifndef SOXMIX
+    current_input = 0;
+#endif
 
+    /* Run input data through effects and get more until olen == 0 
+     * (or ST_EOF).
+     */
+    do {
 #ifndef SOXMIX
-        /* FIXME: Need to look at retur code and abort on failure */
-        efftab[0].olen = (*informat[0]->h->read)(informat[0],
-                                                 efftab[0].obuf, 
-                                                 (st_ssize_t)ST_BUFSIZ);
+        efftab[0].olen = (*file_desc[current_input]->h->read)(file_desc[current_input],
+                                                              efftab[0].obuf, 
+                                                              (st_ssize_t)ST_BUFSIZ);
+        /* FIXME: libst needs the feof() and ferror() concepts
+         * to see if ST_EOF means a real failure.  Until then we
+         * must treat ST_EOF as just hiting the end of the buffer.
+         */
+        if (efftab[0].olen == ST_EOF)
+        {
+            if (current_input < input_count-1)
+            {
+                current_input++;
+                continue;
+            }
+            efftab[0].olen = 0;
+        }
 #else
         for (f = 0; f < input_count; f++)
         {
-            ilen[f] = (*informat[f]->h->read)(informat[f],
-                                              ibuf[f], 
-                                              (st_ssize_t)ST_BUFSIZ);
+            ilen[f] = (*file_desc[f]->h->read)(file_desc[f],
+                                               ibuf[f], 
+                                               (st_ssize_t)ST_BUFSIZ);
+            /* FIXME: libst needs the feof() and ferror() concepts
+             * to see if ST_EOF means a real failure.  Until then we
+             * must treat ST_EOF as just hiting the end of the buffer.
+             */
+            if (ilen[f] == ST_EOF)
+                ilen[f] = 0;
         }
 
-        /* FIXME: Should check for ST_EOF from read and
-         * abort!
-         * FIXME: Should warn if the size of the reads are not
-         * the same!
+        /* FIXME: Run threw input data and change its volume
+         * based on value in in_file_opts[x]->volume
          */
+        /* FIXME: Should report if the size of the reads are not
+         * the same.
+         */
         efftab[0].olen = 0;
         for (f = 0; f < input_count; f++)
             if ((st_size_t)ilen[f] > efftab[0].olen)
@@ -725,7 +710,6 @@
             }
         }
 #endif
-
         efftab[0].odone = 0;
 
         /* If not writing and no effects are occuring then not much
@@ -739,7 +723,7 @@
             break;
 
         /* Change the volume of this initial input data if needed. */
-        if (dovolume)
+        if (writing && file_opts[file_count-1]->volume != 1.0)
             clipped += volumechange(efftab[0].obuf, efftab[0].olen,
                                     volume);
 
@@ -750,7 +734,8 @@
         flowstatus = flow_effect_out();
 
         /* Negative flowstatus says no more output will ever be generated. */
-        if (flowstatus < 0 || outformat->st_errno)
+        if (flowstatus < 0 || 
+            (writing && file_desc[file_count-1]->st_errno))
             break;
 
     } while (1); /* break; efftab[0].olen == 0 */
@@ -763,7 +748,6 @@
     }
 #endif
 
-
     /* Drain the effects out first to last,
      * pushing residue through subsequent effects */
     /* oh, what a tangled web we weave */
@@ -775,15 +759,16 @@
                 break;          /* out of while (1) */
 
             /* FIXME: Need to look at return code and abort on failure */
-            if (writing&&efftab[neffects-1].olen > 0)
-                (* outformat->h->write)(outformat, efftab[neffects-1].obuf,
-                                       (st_ssize_t) efftab[neffects-1].olen);
+            if (writing && efftab[neffects-1].olen > 0)
+                (*file_desc[file_count-1]->h->write)(file_desc[file_count-1], 
+                                                     efftab[neffects-1].obuf,
+                                                     (st_ssize_t)efftab[neffects-1].olen);
 
             if (efftab[f].olen != ST_BUFSIZ)
                 break;
         }
     }
-    
+
     /* Free output buffers now that they won't be used */
     for(e = 0; e < neffects; e++)
     {
@@ -798,7 +783,7 @@
      */
 
     for (e = 1; e < neffects; e++) {
-        (* efftab[e].h->stop)(&efftab[e]);
+        (*efftab[e].h->stop)(&efftab[e]);
         if (efftabR[e].name)
             (* efftabR[e].h->stop)(&efftabR[e]);
     }
@@ -808,10 +793,10 @@
         /* If problems closing input file, just warn user since
          * we are exiting anyways.
          */
-        if ((* informat[f]->h->stopread)(informat[f]) == ST_EOF)
-            st_warn(informat[f]->st_errstr);
-        fclose(informat[f]->fp);
-        free(informat[f]->filename);
+        if ((*file_desc[f]->h->stopread)(file_desc[f]) == ST_EOF)
+            st_warn(file_desc[f]->st_errstr);
+        fclose(file_desc[f]->fp);
+        free(file_desc[f]->filename);
     }
 
     if (writing)
@@ -819,13 +804,12 @@
         /* problem closing output file, just warn user since we
          * are exiting anyways.
          */
-        if ((*outformat->h->stopwrite)(outformat) == ST_EOF)
-            st_warn(outformat->st_errstr);
-        free(outformat->filename);
-        free(outformat->comment);
+        if ((*file_desc[file_count-1]->h->stopwrite)(file_desc[file_count-1]) == ST_EOF)
+            st_warn(file_desc[file_count-1]->st_errstr);
+        free(file_desc[file_count-1]->filename);
+        free(file_desc[file_count-1]->comment);
+        fclose(file_desc[file_count-1]->fp);
     }
-    if (writing)
-        fclose(outformat->fp);
 }
 
 static int flow_effect_out(void)
@@ -843,18 +827,21 @@
       }
 
       /* If outputing and output data was generated then write it */
-      if (writing&&(efftab[neffects-1].olen>efftab[neffects-1].odone))
+      if (writing && (efftab[neffects-1].olen>efftab[neffects-1].odone))
       {
-          (* outformat->h->write)(outformat,
-                                  efftab[neffects-1].obuf,
-                                  (st_ssize_t)efftab[neffects-1].olen);
+          /* FIXME: Should look at return code and abort
+           * on ST_EOF
+           */
+          (*file_desc[file_count-1]->h->write)(file_desc[file_count-1],
+                                               efftab[neffects-1].obuf,
+                                               (st_ssize_t)efftab[neffects-1].olen);
           efftab[neffects-1].odone = efftab[neffects-1].olen;
-      }
 
-      if (outformat->st_errno)
-      {
-          st_warn("Error writing: %s",outformat->st_errstr);
-          break;
+          if (file_desc[file_count-1]->st_errno)
+          {
+              st_warn("Error writing: %s", file_desc[file_count-1]->st_errstr);
+              break;
+          }
       }
 
       /* If any effect will never again produce data, give up.  This
@@ -893,6 +880,7 @@
          */
         idone = efftab[e-1].olen - efftab[e-1].odone;
         odone = ST_BUFSIZ;
+        /* FIXME: Should look at return code and abort on ST_EOF */
         effstatus = (* efftab[e].h->flow)(&efftab[e],
                                           &efftab[e-1].obuf[efftab[e-1].odone],
                                           efftab[e].obuf, &idone, &odone);
@@ -916,6 +904,7 @@
         /* left */
         idonel = (idone + 1)/2;         /* odd-length logic */
         odonel = odone/2;
+        /* FIXME: Should look at return code and abort on ST_EOF */
         effstatus = (* efftab[e].h->flow)(&efftab[e],
                                           ibufl, obufl, &idonel, &odonel);
 
@@ -922,6 +911,7 @@
         /* right */
         idoner = idone/2;               /* odd-length logic */
         odoner = odone/2;
+        /* FIXME: Should look at return code and abort on ST_EOF */
         effstatus = (* efftabR[e].h->flow)(&efftabR[e],
                                            ibufr, obufr, &idoner, &odoner);
 
@@ -965,6 +955,7 @@
 
         /* right */
         olenr = olen/2;
+        /* FIXME: Should look at return code and abort on ST_EOF */
         (* efftab[e].h->drain)(&efftabR[e], obufr, &olenr);
 
         obuf = efftab[e].obuf;
@@ -992,8 +983,11 @@
         int needchan = 0, needrate = 0, haschan = 0, hasrate = 0;
         int effects_mask = 0;
 
-        needrate = (informat[0]->info.rate != outformat->info.rate);
-        needchan = (informat[0]->info.channels != outformat->info.channels);
+        if (writing)
+        {
+            needrate = (file_desc[0]->info.rate != file_desc[file_count-1]->info.rate);
+            needchan = (file_desc[0]->info.channels != file_desc[file_count-1]->info.channels);
+        }
 
         for (i = 0; i < nuser_effects; i++)
         {
@@ -1031,18 +1025,21 @@
          * after the avg effect.
          */
         if (needchan && !(haschan) &&
-            (informat[0]->info.channels > outformat->info.channels))
+            (file_desc[0]->info.channels > file_desc[file_count-1]->info.channels))
         {
             /* Find effect and update initial pointers */
             st_geteffect(&efftab[neffects], "avg");
 
             /* give default opts for added effects */
+            /* FIXME: Should look at return code and abort on ST_EOF */
             (* efftab[neffects].h->getopts)(&efftab[neffects],(int)0,
                                             (char **)0);
 
             /* Copy format info to effect table */
-            effects_mask = st_updateeffect(&efftab[neffects], informat[0],
-                                           outformat, effects_mask);
+            effects_mask = st_updateeffect(&efftab[neffects], 
+                                           &file_desc[0]->info,
+                                           &file_desc[file_count-1]->info, 
+                                           effects_mask);
 
             neffects++;
         }
@@ -1051,7 +1048,7 @@
          * after the resample effect.
          */
         if (needrate && !(hasrate) &&
-            (informat[0]->info.rate > outformat->info.rate))
+            (file_desc[0]->info.rate > file_desc[file_count-1]->info.rate))
         {
             if (soxpreview)
                 st_geteffect(&efftab[neffects], "rate");
@@ -1059,12 +1056,15 @@
                 st_geteffect(&efftab[neffects], "resample");
 
             /* set up & give default opts for added effects */
+            /* FIXME: Should look at return code and abort on ST_EOF */
             (* efftab[neffects].h->getopts)(&efftab[neffects],(int)0,
                                             (char **)0);
 
             /* Copy format info to effect table */
-            effects_mask = st_updateeffect(&efftab[neffects], informat[0],
-                                           outformat, effects_mask);
+            effects_mask = st_updateeffect(&efftab[neffects], 
+                                           &file_desc[0]->info,
+                                           &file_desc[file_count-1]->info, 
+                                           effects_mask);
 
             /* Rate can't handle multiple channels so be sure and
              * account for that.
@@ -1085,8 +1085,10 @@
                    sizeof(struct st_effect));
 
             /* Copy format info to effect table */
-            effects_mask = st_updateeffect(&efftab[neffects], informat[0],
-                                           outformat, effects_mask);
+            effects_mask = st_updateeffect(&efftab[neffects], 
+                                           &file_desc[0]->info,
+                                           &file_desc[file_count-1]->info, 
+                                           effects_mask);
 
             /* If this effect can't handle multiple channels then
              * account for this.
@@ -1113,12 +1115,15 @@
                 st_geteffect(&efftab[neffects], "resample");
 
             /* set up & give default opts for added effects */
+            /* FIXME: Should look at return code and abort on ST_EOF */
             (* efftab[neffects].h->getopts)(&efftab[neffects],(int)0,
                                             (char **)0);
 
             /* Copy format info to effect table */
-            effects_mask = st_updateeffect(&efftab[neffects], informat[0],
-                                           outformat, effects_mask);
+            effects_mask = st_updateeffect(&efftab[neffects], 
+                                           &file_desc[0]->info,
+                                           &file_desc[file_count-1]->info, 
+                                           effects_mask);
 
             /* Rate can't handle multiple channels so be sure and
              * account for that.
@@ -1140,12 +1145,15 @@
             st_geteffect(&efftab[neffects], "avg");
 
             /* set up & give default opts for added effects */
+            /* FIXME: Should look at return code and abort on ST_EOF */
             (* efftab[neffects].h->getopts)(&efftab[neffects],(int)0,
                                             (char **)0);
 
             /* Copy format info to effect table */
-            effects_mask = st_updateeffect(&efftab[neffects], informat[0],
-                                           outformat, effects_mask);
+            effects_mask = st_updateeffect(&efftab[neffects], 
+                                           &file_desc[0]->info,
+                                           &file_desc[file_count-1]->info, 
+                                           effects_mask);
 
             neffects++;
         }
@@ -1235,18 +1243,18 @@
     /* Close the input file and outputfile before exiting*/
     for (i = 0; i < input_count; i++)
     {
-        if (informat[i] && informat[i]->fp)
-                fclose(informat[i]->fp);
-        if (informat[i])
-            free(informat[i]);
+        if (file_desc[i] && file_desc[i]->fp)
+                fclose(file_desc[i]->fp);
+        if (file_desc[i])
+            free(file_desc[i]);
     }
-    if (outformat && outformat->fp) {
-        fclose(outformat->fp);
+    if (writing && file_desc[file_count-1] && file_desc[file_count-1]->fp) {
+        fclose(file_desc[file_count-1]->fp);
         /* remove the output file because we failed, if it's ours. */
         /* Don't if its not a regular file. */
-        if (filetype(fileno(outformat->fp)) == S_IFREG)
-            unlink(outformat->filename);
+        if (filetype(fileno(file_desc[file_count-1]->fp)) == S_IFREG)
+            unlink(file_desc[file_count-1]->filename);
+        if (file_desc[file_count-1])
+            free(file_desc[file_count-1]);
     }
-    if (outformat)
-        free(outformat);
 }
--- a/src/st.h
+++ b/src/st.h
@@ -228,8 +228,6 @@
 {
     char            *name;          /* effect name */
     struct st_signalinfo ininfo;    /* input signal specifications */
-    struct st_loopinfo   loops[8];  /* input loops  specifications */
-    struct st_instrinfo  instr;     /* input instrument  specifications */
     struct st_signalinfo outinfo;   /* output signal specifications */
     st_effect_t     *h;             /* effects driver */
     st_sample_t     *obuf;          /* output buffer */
@@ -249,7 +247,7 @@
 int st_geteffect_opt(eff_t, int, char **);
 int st_geteffect(eff_t, char *);
 int st_checkeffect(char *);
-int st_updateeffect(eff_t, ft_t, ft_t, int);
+int st_updateeffect(eff_t, st_signalinfo_t *in, st_signalinfo_t *out, int);
 int st_gettype(ft_t);
 ft_t st_initformat(void);
 void st_copyformat(ft_t, ft_t);
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -483,11 +483,6 @@
 int st_lowpass_getopts(eff_t effp, int argc, char **argv);
 int st_lowpass_start(eff_t effp);
 
-int st_map_getopts(eff_t effp, int argc, char **argv);
-int st_map_start(eff_t effp);
-int st_map_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
-                st_size_t *isamp, st_size_t *osamp);
-
 int st_mask_getopts(eff_t effp, int argc, char **argv);
 int st_mask_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
                  st_size_t *isamp, st_size_t *osamp);
--- a/src/util.c
+++ b/src/util.c
@@ -271,24 +271,14 @@
  * calls.
  */
 
-int st_updateeffect(eff_t effp, ft_t in, ft_t out, int effect_mask)
+int st_updateeffect(eff_t effp, st_signalinfo_t *in, st_signalinfo_t *out, 
+                    int effect_mask)
 {
-    int i;
+    effp->ininfo = *in;
 
-    effp->ininfo = in->info;
-    effp->ininfo = in->info;
+    effp->outinfo = *out;
 
-    effp->outinfo = out->info;
-    effp->outinfo = out->info;
-
-    for(i = 0; i < 8; i++) {
-        memcpy(&effp->loops[i], &in->loops[i], sizeof(struct st_loopinfo));
-        memcpy(&effp->loops[i], &in->loops[i], sizeof(struct st_loopinfo));
-    }
-    effp->instr = in->instr;
-    effp->instr = in->instr;
-
-    if (in->info.channels != out->info.channels)
+    if (in->channels != out->channels)
     {
         /* Only effects with ST_EFF_CHAN flag can actually handle
          * outputing a different number of channels then the input.
@@ -301,14 +291,14 @@
              * file.
              */
             if (effect_mask & ST_EFF_CHAN)
-                effp->ininfo.channels = out->info.channels;
+                effp->ininfo.channels = out->channels;
             else
-                effp->outinfo.channels = in->info.channels;
+                effp->outinfo.channels = in->channels;
 
         }
     }
 
-    if (in->info.rate != out->info.rate)
+    if (in->rate != out->rate)
     {
         /* Only the ST_EFF_RATE effect can handle an input that
          * is a different sample rate then the output.
@@ -316,9 +306,9 @@
         if (!(effp->h->flags & ST_EFF_RATE))
         {
             if (effect_mask & ST_EFF_RATE)
-                effp->ininfo.rate = out->info.rate;
+                effp->ininfo.rate = out->rate;
             else
-                effp->outinfo.rate = in->info.rate;
+                effp->outinfo.rate = in->rate;
         }
     }